diff options
author | Dave Airlie <airlied@redhat.com> | 2022-05-19 14:09:46 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2022-05-19 14:09:54 +1000 |
commit | 00df0514ab13813655a6fbaba85425f8f4780be2 (patch) | |
tree | 85e9e8908b702575ff4a7e4a58cf36dcca93c204 /drivers/gpu/drm/amd/amdgpu/mes_v10_1.c | |
parent | f8122500a039abeabfff41b0ad8b6a2c94c1107d (diff) | |
parent | 0223e516470aa0589da6c03e6d177c10594cabbd (diff) | |
download | linux-00df0514ab13813655a6fbaba85425f8f4780be2.tar.bz2 |
Merge tag 'amd-drm-next-5.19-2022-05-18' of https://gitlab.freedesktop.org/agd5f/linux into drm-next
amd-drm-next-5.19-2022-05-18:
amdgpu:
- Misc code cleanups
- Additional SMU 13.x enablement
- Smartshift fixes
- GFX11 fixes
- Support for SMU 13.0.4
- SMU mutex fix
- Suspend/resume fix
amdkfd:
- static checker fix
- Doorbell/MMIO resource handling fix
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220518205621.5741-1-alexander.deucher@amd.com
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/mes_v10_1.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/mes_v10_1.c | 630 |
1 files changed, 415 insertions, 215 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c index a7ec4ac89da5..18a129f36215 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c @@ -28,16 +28,21 @@ #include "nv.h" #include "gc/gc_10_1_0_offset.h" #include "gc/gc_10_1_0_sh_mask.h" +#include "gc/gc_10_1_0_default.h" #include "v10_structs.h" #include "mes_api_def.h" #define mmCP_MES_IC_OP_CNTL_Sienna_Cichlid 0x2820 #define mmCP_MES_IC_OP_CNTL_Sienna_Cichlid_BASE_IDX 1 +#define mmRLC_CP_SCHEDULERS_Sienna_Cichlid 0x4ca1 +#define mmRLC_CP_SCHEDULERS_Sienna_Cichlid_BASE_IDX 1 MODULE_FIRMWARE("amdgpu/navi10_mes.bin"); MODULE_FIRMWARE("amdgpu/sienna_cichlid_mes.bin"); +MODULE_FIRMWARE("amdgpu/sienna_cichlid_mes1.bin"); static int mes_v10_1_hw_fini(void *handle); +static int mes_v10_1_kiq_hw_init(struct amdgpu_device *adev); #define MES_EOP_SIZE 2048 @@ -46,7 +51,7 @@ static void mes_v10_1_ring_set_wptr(struct amdgpu_ring *ring) struct amdgpu_device *adev = ring->adev; if (ring->use_doorbell) { - atomic64_set((atomic64_t *)&adev->wb.wb[ring->wptr_offs], + atomic64_set((atomic64_t *)ring->wptr_cpu_addr, ring->wptr); WDOORBELL64(ring->doorbell_index, ring->wptr); } else { @@ -56,7 +61,7 @@ static void mes_v10_1_ring_set_wptr(struct amdgpu_ring *ring) static u64 mes_v10_1_ring_get_rptr(struct amdgpu_ring *ring) { - return ring->adev->wb.wb[ring->rptr_offs]; + return *ring->rptr_cpu_addr; } static u64 mes_v10_1_ring_get_wptr(struct amdgpu_ring *ring) @@ -64,8 +69,7 @@ static u64 mes_v10_1_ring_get_wptr(struct amdgpu_ring *ring) u64 wptr; if (ring->use_doorbell) - wptr = atomic64_read((atomic64_t *) - &ring->adev->wb.wb[ring->wptr_offs]); + wptr = atomic64_read((atomic64_t *)ring->wptr_cpu_addr); else BUG(); return wptr; @@ -130,6 +134,8 @@ static int mes_v10_1_add_hw_queue(struct amdgpu_mes *mes, { struct amdgpu_device *adev = mes->adev; union MESAPI__ADD_QUEUE mes_add_queue_pkt; + struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0]; + uint32_t vm_cntx_cntl = hub->vm_cntx_cntl; memset(&mes_add_queue_pkt, 0, sizeof(mes_add_queue_pkt)); @@ -138,8 +144,7 @@ static int mes_v10_1_add_hw_queue(struct amdgpu_mes *mes, mes_add_queue_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS; mes_add_queue_pkt.process_id = input->process_id; - mes_add_queue_pkt.page_table_base_addr = - input->page_table_base_addr - adev->gmc.vram_start; + mes_add_queue_pkt.page_table_base_addr = input->page_table_base_addr; mes_add_queue_pkt.process_va_start = input->process_va_start; mes_add_queue_pkt.process_va_end = input->process_va_end; mes_add_queue_pkt.process_quantum = input->process_quantum; @@ -156,6 +161,10 @@ static int mes_v10_1_add_hw_queue(struct amdgpu_mes *mes, mes_add_queue_pkt.queue_type = convert_to_mes_queue_type(input->queue_type); mes_add_queue_pkt.paging = input->paging; + mes_add_queue_pkt.vm_context_cntl = vm_cntx_cntl; + mes_add_queue_pkt.gws_base = input->gws_base; + mes_add_queue_pkt.gws_size = input->gws_size; + mes_add_queue_pkt.trap_handler_addr = input->tba_addr; mes_add_queue_pkt.api_status.api_completion_fence_addr = mes->ring.fence_drv.gpu_addr; @@ -189,6 +198,44 @@ static int mes_v10_1_remove_hw_queue(struct amdgpu_mes *mes, &mes_remove_queue_pkt, sizeof(mes_remove_queue_pkt)); } +static int mes_v10_1_unmap_legacy_queue(struct amdgpu_mes *mes, + struct mes_unmap_legacy_queue_input *input) +{ + union MESAPI__REMOVE_QUEUE mes_remove_queue_pkt; + + memset(&mes_remove_queue_pkt, 0, sizeof(mes_remove_queue_pkt)); + + mes_remove_queue_pkt.header.type = MES_API_TYPE_SCHEDULER; + mes_remove_queue_pkt.header.opcode = MES_SCH_API_REMOVE_QUEUE; + mes_remove_queue_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS; + + mes_remove_queue_pkt.doorbell_offset = input->doorbell_offset; + mes_remove_queue_pkt.gang_context_addr = 0; + + mes_remove_queue_pkt.pipe_id = input->pipe_id; + mes_remove_queue_pkt.queue_id = input->queue_id; + + if (input->action == PREEMPT_QUEUES_NO_UNMAP) { + mes_remove_queue_pkt.preempt_legacy_gfx_queue = 1; + mes_remove_queue_pkt.tf_addr = input->trail_fence_addr; + mes_remove_queue_pkt.tf_data = + lower_32_bits(input->trail_fence_data); + } else { + if (input->queue_type == AMDGPU_RING_TYPE_GFX) + mes_remove_queue_pkt.unmap_legacy_gfx_queue = 1; + else + mes_remove_queue_pkt.unmap_kiq_utility_queue = 1; + } + + mes_remove_queue_pkt.api_status.api_completion_fence_addr = + mes->ring.fence_drv.gpu_addr; + mes_remove_queue_pkt.api_status.api_completion_fence_value = + ++mes->ring.fence_drv.sync_seq; + + return mes_v10_1_submit_pkt_and_poll_completion(mes, + &mes_remove_queue_pkt, sizeof(mes_remove_queue_pkt)); +} + static int mes_v10_1_suspend_gang(struct amdgpu_mes *mes, struct mes_suspend_gang_input *input) { @@ -251,9 +298,21 @@ static int mes_v10_1_set_hw_resources(struct amdgpu_mes *mes) mes_set_hw_res_pkt.sdma_hqd_mask[i] = mes->sdma_hqd_mask[i]; for (i = 0; i < AMD_PRIORITY_NUM_LEVELS; i++) - mes_set_hw_res_pkt.agreegated_doorbells[i] = + mes_set_hw_res_pkt.aggregated_doorbells[i] = mes->agreegated_doorbells[i]; + for (i = 0; i < 5; i++) { + mes_set_hw_res_pkt.gc_base[i] = adev->reg_offset[GC_HWIP][0][i]; + mes_set_hw_res_pkt.mmhub_base[i] = + adev->reg_offset[MMHUB_HWIP][0][i]; + mes_set_hw_res_pkt.osssys_base[i] = + adev->reg_offset[OSSSYS_HWIP][0][i]; + } + + mes_set_hw_res_pkt.disable_reset = 1; + mes_set_hw_res_pkt.disable_mes_log = 1; + mes_set_hw_res_pkt.use_different_vmid_compute = 1; + mes_set_hw_res_pkt.api_status.api_completion_fence_addr = mes->ring.fence_drv.gpu_addr; mes_set_hw_res_pkt.api_status.api_completion_fence_value = @@ -266,11 +325,13 @@ static int mes_v10_1_set_hw_resources(struct amdgpu_mes *mes) static const struct amdgpu_mes_funcs mes_v10_1_funcs = { .add_hw_queue = mes_v10_1_add_hw_queue, .remove_hw_queue = mes_v10_1_remove_hw_queue, + .unmap_legacy_queue = mes_v10_1_unmap_legacy_queue, .suspend_gang = mes_v10_1_suspend_gang, .resume_gang = mes_v10_1_resume_gang, }; -static int mes_v10_1_init_microcode(struct amdgpu_device *adev) +static int mes_v10_1_init_microcode(struct amdgpu_device *adev, + enum admgpu_mes_pipe pipe) { const char *chip_name; char fw_name[30]; @@ -278,51 +339,69 @@ static int mes_v10_1_init_microcode(struct amdgpu_device *adev) const struct mes_firmware_header_v1_0 *mes_hdr; struct amdgpu_firmware_info *info; - switch (adev->asic_type) { - case CHIP_NAVI10: + switch (adev->ip_versions[GC_HWIP][0]) { + case IP_VERSION(10, 1, 10): chip_name = "navi10"; break; - case CHIP_SIENNA_CICHLID: + case IP_VERSION(10, 3, 0): chip_name = "sienna_cichlid"; break; default: BUG(); } - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes.bin", chip_name); - err = request_firmware(&adev->mes.fw, fw_name, adev->dev); + if (pipe == AMDGPU_MES_SCHED_PIPE) + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes.bin", + chip_name); + else + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes1.bin", + chip_name); + + err = request_firmware(&adev->mes.fw[pipe], fw_name, adev->dev); if (err) return err; - err = amdgpu_ucode_validate(adev->mes.fw); + err = amdgpu_ucode_validate(adev->mes.fw[pipe]); if (err) { - release_firmware(adev->mes.fw); - adev->mes.fw = NULL; + release_firmware(adev->mes.fw[pipe]); + adev->mes.fw[pipe] = NULL; return err; } - mes_hdr = (const struct mes_firmware_header_v1_0 *)adev->mes.fw->data; - adev->mes.ucode_fw_version = le32_to_cpu(mes_hdr->mes_ucode_version); - adev->mes.ucode_fw_version = + mes_hdr = (const struct mes_firmware_header_v1_0 *) + adev->mes.fw[pipe]->data; + adev->mes.ucode_fw_version[pipe] = + le32_to_cpu(mes_hdr->mes_ucode_version); + adev->mes.ucode_fw_version[pipe] = le32_to_cpu(mes_hdr->mes_ucode_data_version); - adev->mes.uc_start_addr = + adev->mes.uc_start_addr[pipe] = le32_to_cpu(mes_hdr->mes_uc_start_addr_lo) | ((uint64_t)(le32_to_cpu(mes_hdr->mes_uc_start_addr_hi)) << 32); - adev->mes.data_start_addr = + adev->mes.data_start_addr[pipe] = le32_to_cpu(mes_hdr->mes_data_start_addr_lo) | ((uint64_t)(le32_to_cpu(mes_hdr->mes_data_start_addr_hi)) << 32); if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { - info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MES]; - info->ucode_id = AMDGPU_UCODE_ID_CP_MES; - info->fw = adev->mes.fw; + int ucode, ucode_data; + + if (pipe == AMDGPU_MES_SCHED_PIPE) { + ucode = AMDGPU_UCODE_ID_CP_MES; + ucode_data = AMDGPU_UCODE_ID_CP_MES_DATA; + } else { + ucode = AMDGPU_UCODE_ID_CP_MES1; + ucode_data = AMDGPU_UCODE_ID_CP_MES1_DATA; + } + + info = &adev->firmware.ucode[ucode]; + info->ucode_id = ucode; + info->fw = adev->mes.fw[pipe]; adev->firmware.fw_size += ALIGN(le32_to_cpu(mes_hdr->mes_ucode_size_bytes), PAGE_SIZE); - info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MES_DATA]; - info->ucode_id = AMDGPU_UCODE_ID_CP_MES_DATA; - info->fw = adev->mes.fw; + info = &adev->firmware.ucode[ucode_data]; + info->ucode_id = ucode_data; + info->fw = adev->mes.fw[pipe]; adev->firmware.fw_size += ALIGN(le32_to_cpu(mes_hdr->mes_ucode_data_size_bytes), PAGE_SIZE); @@ -331,13 +410,15 @@ static int mes_v10_1_init_microcode(struct amdgpu_device *adev) return 0; } -static void mes_v10_1_free_microcode(struct amdgpu_device *adev) +static void mes_v10_1_free_microcode(struct amdgpu_device *adev, + enum admgpu_mes_pipe pipe) { - release_firmware(adev->mes.fw); - adev->mes.fw = NULL; + release_firmware(adev->mes.fw[pipe]); + adev->mes.fw[pipe] = NULL; } -static int mes_v10_1_allocate_ucode_buffer(struct amdgpu_device *adev) +static int mes_v10_1_allocate_ucode_buffer(struct amdgpu_device *adev, + enum admgpu_mes_pipe pipe) { int r; const struct mes_firmware_header_v1_0 *mes_hdr; @@ -345,31 +426,32 @@ static int mes_v10_1_allocate_ucode_buffer(struct amdgpu_device *adev) unsigned fw_size; mes_hdr = (const struct mes_firmware_header_v1_0 *) - adev->mes.fw->data; + adev->mes.fw[pipe]->data; - fw_data = (const __le32 *)(adev->mes.fw->data + + fw_data = (const __le32 *)(adev->mes.fw[pipe]->data + le32_to_cpu(mes_hdr->mes_ucode_offset_bytes)); fw_size = le32_to_cpu(mes_hdr->mes_ucode_size_bytes); r = amdgpu_bo_create_reserved(adev, fw_size, PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT, - &adev->mes.ucode_fw_obj, - &adev->mes.ucode_fw_gpu_addr, - (void **)&adev->mes.ucode_fw_ptr); + &adev->mes.ucode_fw_obj[pipe], + &adev->mes.ucode_fw_gpu_addr[pipe], + (void **)&adev->mes.ucode_fw_ptr[pipe]); if (r) { dev_err(adev->dev, "(%d) failed to create mes fw bo\n", r); return r; } - memcpy(adev->mes.ucode_fw_ptr, fw_data, fw_size); + memcpy(adev->mes.ucode_fw_ptr[pipe], fw_data, fw_size); - amdgpu_bo_kunmap(adev->mes.ucode_fw_obj); - amdgpu_bo_unreserve(adev->mes.ucode_fw_obj); + amdgpu_bo_kunmap(adev->mes.ucode_fw_obj[pipe]); + amdgpu_bo_unreserve(adev->mes.ucode_fw_obj[pipe]); return 0; } -static int mes_v10_1_allocate_ucode_data_buffer(struct amdgpu_device *adev) +static int mes_v10_1_allocate_ucode_data_buffer(struct amdgpu_device *adev, + enum admgpu_mes_pipe pipe) { int r; const struct mes_firmware_header_v1_0 *mes_hdr; @@ -377,53 +459,65 @@ static int mes_v10_1_allocate_ucode_data_buffer(struct amdgpu_device *adev) unsigned fw_size; mes_hdr = (const struct mes_firmware_header_v1_0 *) - adev->mes.fw->data; + adev->mes.fw[pipe]->data; - fw_data = (const __le32 *)(adev->mes.fw->data + + fw_data = (const __le32 *)(adev->mes.fw[pipe]->data + le32_to_cpu(mes_hdr->mes_ucode_data_offset_bytes)); fw_size = le32_to_cpu(mes_hdr->mes_ucode_data_size_bytes); r = amdgpu_bo_create_reserved(adev, fw_size, 64 * 1024, AMDGPU_GEM_DOMAIN_GTT, - &adev->mes.data_fw_obj, - &adev->mes.data_fw_gpu_addr, - (void **)&adev->mes.data_fw_ptr); + &adev->mes.data_fw_obj[pipe], + &adev->mes.data_fw_gpu_addr[pipe], + (void **)&adev->mes.data_fw_ptr[pipe]); if (r) { dev_err(adev->dev, "(%d) failed to create mes data fw bo\n", r); return r; } - memcpy(adev->mes.data_fw_ptr, fw_data, fw_size); + memcpy(adev->mes.data_fw_ptr[pipe], fw_data, fw_size); - amdgpu_bo_kunmap(adev->mes.data_fw_obj); - amdgpu_bo_unreserve(adev->mes.data_fw_obj); + amdgpu_bo_kunmap(adev->mes.data_fw_obj[pipe]); + amdgpu_bo_unreserve(adev->mes.data_fw_obj[pipe]); return 0; } -static void mes_v10_1_free_ucode_buffers(struct amdgpu_device *adev) +static void mes_v10_1_free_ucode_buffers(struct amdgpu_device *adev, + enum admgpu_mes_pipe pipe) { - amdgpu_bo_free_kernel(&adev->mes.data_fw_obj, - &adev->mes.data_fw_gpu_addr, - (void **)&adev->mes.data_fw_ptr); + amdgpu_bo_free_kernel(&adev->mes.data_fw_obj[pipe], + &adev->mes.data_fw_gpu_addr[pipe], + (void **)&adev->mes.data_fw_ptr[pipe]); - amdgpu_bo_free_kernel(&adev->mes.ucode_fw_obj, - &adev->mes.ucode_fw_gpu_addr, - (void **)&adev->mes.ucode_fw_ptr); + amdgpu_bo_free_kernel(&adev->mes.ucode_fw_obj[pipe], + &adev->mes.ucode_fw_gpu_addr[pipe], + (void **)&adev->mes.ucode_fw_ptr[pipe]); } static void mes_v10_1_enable(struct amdgpu_device *adev, bool enable) { - uint32_t data = 0; + uint32_t pipe, data = 0; if (enable) { data = RREG32_SOC15(GC, 0, mmCP_MES_CNTL); data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE0_RESET, 1); + data = REG_SET_FIELD(data, CP_MES_CNTL, + MES_PIPE1_RESET, adev->enable_mes_kiq ? 1 : 0); WREG32_SOC15(GC, 0, mmCP_MES_CNTL, data); - /* set ucode start address */ - WREG32_SOC15(GC, 0, mmCP_MES_PRGRM_CNTR_START, - (uint32_t)(adev->mes.uc_start_addr) >> 2); + mutex_lock(&adev->srbm_mutex); + for (pipe = 0; pipe < AMDGPU_MAX_MES_PIPES; pipe++) { + if (!adev->enable_mes_kiq && + pipe == AMDGPU_MES_KIQ_PIPE) + continue; + + nv_grbm_select(adev, 3, pipe, 0, 0); + WREG32_SOC15(GC, 0, mmCP_MES_PRGRM_CNTR_START, + (uint32_t)(adev->mes.uc_start_addr[pipe]) >> 2); + } + nv_grbm_select(adev, 0, 0, 0, 0); + mutex_unlock(&adev->srbm_mutex); /* clear BYPASS_UNCACHED to avoid hangs after interrupt. */ data = RREG32_SOC15(GC, 0, mmCP_MES_DC_OP_CNTL); @@ -433,70 +527,77 @@ static void mes_v10_1_enable(struct amdgpu_device *adev, bool enable) /* unhalt MES and activate pipe0 */ data = REG_SET_FIELD(0, CP_MES_CNTL, MES_PIPE0_ACTIVE, 1); + data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE1_ACTIVE, + adev->enable_mes_kiq ? 1 : 0); WREG32_SOC15(GC, 0, mmCP_MES_CNTL, data); + udelay(100); } else { data = RREG32_SOC15(GC, 0, mmCP_MES_CNTL); data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE0_ACTIVE, 0); + data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE1_ACTIVE, 0); data = REG_SET_FIELD(data, CP_MES_CNTL, MES_INVALIDATE_ICACHE, 1); data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE0_RESET, 1); + data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE1_RESET, + adev->enable_mes_kiq ? 1 : 0); data = REG_SET_FIELD(data, CP_MES_CNTL, MES_HALT, 1); WREG32_SOC15(GC, 0, mmCP_MES_CNTL, data); } } /* This function is for backdoor MES firmware */ -static int mes_v10_1_load_microcode(struct amdgpu_device *adev) +static int mes_v10_1_load_microcode(struct amdgpu_device *adev, + enum admgpu_mes_pipe pipe) { int r; uint32_t data; - if (!adev->mes.fw) + mes_v10_1_enable(adev, false); + + if (!adev->mes.fw[pipe]) return -EINVAL; - r = mes_v10_1_allocate_ucode_buffer(adev); + r = mes_v10_1_allocate_ucode_buffer(adev, pipe); if (r) return r; - r = mes_v10_1_allocate_ucode_data_buffer(adev); + r = mes_v10_1_allocate_ucode_data_buffer(adev, pipe); if (r) { - mes_v10_1_free_ucode_buffers(adev); + mes_v10_1_free_ucode_buffers(adev, pipe); return r; } - mes_v10_1_enable(adev, false); - WREG32_SOC15(GC, 0, mmCP_MES_IC_BASE_CNTL, 0); mutex_lock(&adev->srbm_mutex); /* me=3, pipe=0, queue=0 */ - nv_grbm_select(adev, 3, 0, 0, 0); + nv_grbm_select(adev, 3, pipe, 0, 0); /* set ucode start address */ WREG32_SOC15(GC, 0, mmCP_MES_PRGRM_CNTR_START, - (uint32_t)(adev->mes.uc_start_addr) >> 2); + (uint32_t)(adev->mes.uc_start_addr[pipe]) >> 2); /* set ucode fimrware address */ WREG32_SOC15(GC, 0, mmCP_MES_IC_BASE_LO, - lower_32_bits(adev->mes.ucode_fw_gpu_addr)); + lower_32_bits(adev->mes.ucode_fw_gpu_addr[pipe])); WREG32_SOC15(GC, 0, mmCP_MES_IC_BASE_HI, - upper_32_bits(adev->mes.ucode_fw_gpu_addr)); + upper_32_bits(adev->mes.ucode_fw_gpu_addr[pipe])); /* set ucode instruction cache boundary to 2M-1 */ WREG32_SOC15(GC, 0, mmCP_MES_MIBOUND_LO, 0x1FFFFF); /* set ucode data firmware address */ WREG32_SOC15(GC, 0, mmCP_MES_MDBASE_LO, - lower_32_bits(adev->mes.data_fw_gpu_addr)); + lower_32_bits(adev->mes.data_fw_gpu_addr[pipe])); WREG32_SOC15(GC, 0, mmCP_MES_MDBASE_HI, - upper_32_bits(adev->mes.data_fw_gpu_addr)); + upper_32_bits(adev->mes.data_fw_gpu_addr[pipe])); /* Set 0x3FFFF (256K-1) to CP_MES_MDBOUND_LO */ WREG32_SOC15(GC, 0, mmCP_MES_MDBOUND_LO, 0x3FFFF); /* invalidate ICACHE */ - switch (adev->asic_type) { - case CHIP_SIENNA_CICHLID: + switch (adev->ip_versions[GC_HWIP][0]) { + case IP_VERSION(10, 3, 0): data = RREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL_Sienna_Cichlid); break; default: @@ -505,8 +606,8 @@ static int mes_v10_1_load_microcode(struct amdgpu_device *adev) } data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, PRIME_ICACHE, 0); data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, INVALIDATE_CACHE, 1); - switch (adev->asic_type) { - case CHIP_SIENNA_CICHLID: + switch (adev->ip_versions[GC_HWIP][0]) { + case IP_VERSION(10, 3, 0): WREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL_Sienna_Cichlid, data); break; default: @@ -515,8 +616,8 @@ static int mes_v10_1_load_microcode(struct amdgpu_device *adev) } /* prime the ICACHE. */ - switch (adev->asic_type) { - case CHIP_SIENNA_CICHLID: + switch (adev->ip_versions[GC_HWIP][0]) { + case IP_VERSION(10, 3, 0): data = RREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL_Sienna_Cichlid); break; default: @@ -524,8 +625,8 @@ static int mes_v10_1_load_microcode(struct amdgpu_device *adev) break; } data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, PRIME_ICACHE, 1); - switch (adev->asic_type) { - case CHIP_SIENNA_CICHLID: + switch (adev->ip_versions[GC_HWIP][0]) { + case IP_VERSION(10, 3, 0): WREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL_Sienna_Cichlid, data); break; default: @@ -539,61 +640,32 @@ static int mes_v10_1_load_microcode(struct amdgpu_device *adev) return 0; } -static int mes_v10_1_allocate_eop_buf(struct amdgpu_device *adev) +static int mes_v10_1_allocate_eop_buf(struct amdgpu_device *adev, + enum admgpu_mes_pipe pipe) { int r; u32 *eop; r = amdgpu_bo_create_reserved(adev, MES_EOP_SIZE, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_GTT, - &adev->mes.eop_gpu_obj, - &adev->mes.eop_gpu_addr, - (void **)&eop); + AMDGPU_GEM_DOMAIN_GTT, + &adev->mes.eop_gpu_obj[pipe], + &adev->mes.eop_gpu_addr[pipe], + (void **)&eop); if (r) { dev_warn(adev->dev, "(%d) create EOP bo failed\n", r); return r; } - memset(eop, 0, adev->mes.eop_gpu_obj->tbo.base.size); - - amdgpu_bo_kunmap(adev->mes.eop_gpu_obj); - amdgpu_bo_unreserve(adev->mes.eop_gpu_obj); + memset(eop, 0, adev->mes.eop_gpu_obj[pipe]->tbo.base.size); - return 0; -} - -static int mes_v10_1_allocate_mem_slots(struct amdgpu_device *adev) -{ - int r; - - r = amdgpu_device_wb_get(adev, &adev->mes.sch_ctx_offs); - if (r) { - dev_err(adev->dev, - "(%d) mes sch_ctx_offs wb alloc failed\n", r); - return r; - } - adev->mes.sch_ctx_gpu_addr = - adev->wb.gpu_addr + (adev->mes.sch_ctx_offs * 4); - adev->mes.sch_ctx_ptr = - (uint64_t *)&adev->wb.wb[adev->mes.sch_ctx_offs]; - - r = amdgpu_device_wb_get(adev, &adev->mes.query_status_fence_offs); - if (r) { - dev_err(adev->dev, - "(%d) query_status_fence_offs wb alloc failed\n", r); - return r; - } - adev->mes.query_status_fence_gpu_addr = - adev->wb.gpu_addr + (adev->mes.query_status_fence_offs * 4); - adev->mes.query_status_fence_ptr = - (uint64_t *)&adev->wb.wb[adev->mes.query_status_fence_offs]; + amdgpu_bo_kunmap(adev->mes.eop_gpu_obj[pipe]); + amdgpu_bo_unreserve(adev->mes.eop_gpu_obj[pipe]); return 0; } static int mes_v10_1_mqd_init(struct amdgpu_ring *ring) { - struct amdgpu_device *adev = ring->adev; struct v10_compute_mqd *mqd = ring->mqd_ptr; uint64_t hqd_gpu_addr, wb_gpu_addr, eop_base_addr; uint32_t tmp; @@ -607,38 +679,18 @@ static int mes_v10_1_mqd_init(struct amdgpu_ring *ring) mqd->compute_misc_reserved = 0x00000003; eop_base_addr = ring->eop_gpu_addr >> 8; - mqd->cp_hqd_eop_base_addr_lo = eop_base_addr; - mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_base_addr); /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */ - tmp = RREG32_SOC15(GC, 0, mmCP_HQD_EOP_CONTROL); + tmp = mmCP_HQD_EOP_CONTROL_DEFAULT; tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE, (order_base_2(MES_EOP_SIZE / 4) - 1)); + mqd->cp_hqd_eop_base_addr_lo = lower_32_bits(eop_base_addr); + mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_base_addr); mqd->cp_hqd_eop_control = tmp; - /* enable doorbell? */ - tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL); - - if (ring->use_doorbell) { - tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, - DOORBELL_OFFSET, ring->doorbell_index); - tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, - DOORBELL_EN, 1); - tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, - DOORBELL_SOURCE, 0); - tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, - DOORBELL_HIT, 0); - } - else - tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, - DOORBELL_EN, 0); - - mqd->cp_hqd_pq_doorbell_control = tmp; - /* disable the queue if it's active */ ring->wptr = 0; - mqd->cp_hqd_dequeue_request = 0; mqd->cp_hqd_pq_rptr = 0; mqd->cp_hqd_pq_wptr_lo = 0; mqd->cp_hqd_pq_wptr_hi = 0; @@ -648,17 +700,28 @@ static int mes_v10_1_mqd_init(struct amdgpu_ring *ring) mqd->cp_mqd_base_addr_hi = upper_32_bits(ring->mqd_gpu_addr); /* set MQD vmid to 0 */ - tmp = RREG32_SOC15(GC, 0, mmCP_MQD_CONTROL); + tmp = mmCP_MQD_CONTROL_DEFAULT; tmp = REG_SET_FIELD(tmp, CP_MQD_CONTROL, VMID, 0); mqd->cp_mqd_control = tmp; /* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */ hqd_gpu_addr = ring->gpu_addr >> 8; - mqd->cp_hqd_pq_base_lo = hqd_gpu_addr; + mqd->cp_hqd_pq_base_lo = lower_32_bits(hqd_gpu_addr); mqd->cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr); + /* set the wb address whether it's enabled or not */ + wb_gpu_addr = ring->rptr_gpu_addr; + mqd->cp_hqd_pq_rptr_report_addr_lo = wb_gpu_addr & 0xfffffffc; + mqd->cp_hqd_pq_rptr_report_addr_hi = + upper_32_bits(wb_gpu_addr) & 0xffff; + + /* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */ + wb_gpu_addr = ring->wptr_gpu_addr; + mqd->cp_hqd_pq_wptr_poll_addr_lo = wb_gpu_addr & 0xfffffff8; + mqd->cp_hqd_pq_wptr_poll_addr_hi = upper_32_bits(wb_gpu_addr) & 0xffff; + /* set up the HQD, this is similar to CP_RB0_CNTL */ - tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_CONTROL); + tmp = mmCP_HQD_PQ_CONTROL_DEFAULT; tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, QUEUE_SIZE, (order_base_2(ring->ring_size / 4) - 1)); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE, @@ -666,30 +729,18 @@ static int mes_v10_1_mqd_init(struct amdgpu_ring *ring) #ifdef __BIG_ENDIAN tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ENDIAN_SWAP, 1); #endif - tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 0); + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 1); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH, 0); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE, 1); + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, NO_UPDATE_RPTR, 1); mqd->cp_hqd_pq_control = tmp; - /* set the wb address whether it's enabled or not */ - wb_gpu_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4); - mqd->cp_hqd_pq_rptr_report_addr_lo = wb_gpu_addr & 0xfffffffc; - mqd->cp_hqd_pq_rptr_report_addr_hi = - upper_32_bits(wb_gpu_addr) & 0xffff; - - /* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */ - wb_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4); - mqd->cp_hqd_pq_wptr_poll_addr_lo = wb_gpu_addr & 0xfffffff8; - mqd->cp_hqd_pq_wptr_poll_addr_hi = upper_32_bits(wb_gpu_addr) & 0xffff; - + /* enable doorbell? */ tmp = 0; - /* enable the doorbell if requested */ if (ring->use_doorbell) { - tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, - DOORBELL_OFFSET, ring->doorbell_index); - + DOORBELL_OFFSET, ring->doorbell_index); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_EN, 1); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, @@ -697,30 +748,28 @@ static int mes_v10_1_mqd_init(struct amdgpu_ring *ring) tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_HIT, 0); } - + else + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, + DOORBELL_EN, 0); mqd->cp_hqd_pq_doorbell_control = tmp; - /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */ - ring->wptr = 0; - mqd->cp_hqd_pq_rptr = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_RPTR); - - /* set the vmid for the queue */ mqd->cp_hqd_vmid = 0; - - tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PERSISTENT_STATE); - tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x53); - mqd->cp_hqd_persistent_state = tmp; - - /* set MIN_IB_AVAIL_SIZE */ - tmp = RREG32_SOC15(GC, 0, mmCP_HQD_IB_CONTROL); - tmp = REG_SET_FIELD(tmp, CP_HQD_IB_CONTROL, MIN_IB_AVAIL_SIZE, 3); - mqd->cp_hqd_ib_control = tmp; - /* activate the queue */ mqd->cp_hqd_active = 1; + mqd->cp_hqd_persistent_state = mmCP_HQD_PERSISTENT_STATE_DEFAULT; + mqd->cp_hqd_ib_control = mmCP_HQD_IB_CONTROL_DEFAULT; + mqd->cp_hqd_iq_timer = mmCP_HQD_IQ_TIMER_DEFAULT; + mqd->cp_hqd_quantum = mmCP_HQD_QUANTUM_DEFAULT; + + tmp = mmCP_HQD_GFX_CONTROL_DEFAULT; + tmp = REG_SET_FIELD(tmp, CP_HQD_GFX_CONTROL, DB_UPDATED_MSG_EN, 1); + /* offset: 184 - this is used for CP_HQD_GFX_CONTROL */ + mqd->cp_hqd_suspend_cntl_stack_offset = tmp; + return 0; } +#if 0 static void mes_v10_1_queue_init_register(struct amdgpu_ring *ring) { struct v10_compute_mqd *mqd = ring->mqd_ptr; @@ -728,7 +777,7 @@ static void mes_v10_1_queue_init_register(struct amdgpu_ring *ring) uint32_t data = 0; mutex_lock(&adev->srbm_mutex); - nv_grbm_select(adev, 3, 0, 0, 0); + nv_grbm_select(adev, 3, ring->pipe, 0, 0); /* set CP_HQD_VMID.VMID = 0. */ data = RREG32_SOC15(GC, 0, mmCP_HQD_VMID); @@ -782,8 +831,8 @@ static void mes_v10_1_queue_init_register(struct amdgpu_ring *ring) nv_grbm_select(adev, 0, 0, 0, 0); mutex_unlock(&adev->srbm_mutex); } +#endif -#if 0 static int mes_v10_1_kiq_enable_queue(struct amdgpu_device *adev) { struct amdgpu_kiq *kiq = &adev->gfx.kiq; @@ -806,9 +855,9 @@ static int mes_v10_1_kiq_enable_queue(struct amdgpu_device *adev) DRM_ERROR("kfq enable failed\n"); kiq_ring->sched.ready = false; } + return r; } -#endif static int mes_v10_1_queue_init(struct amdgpu_device *adev) { @@ -818,13 +867,9 @@ static int mes_v10_1_queue_init(struct amdgpu_device *adev) if (r) return r; -#if 0 r = mes_v10_1_kiq_enable_queue(adev); if (r) return r; -#else - mes_v10_1_queue_init_register(&adev->mes.ring); -#endif return 0; } @@ -843,8 +888,8 @@ static int mes_v10_1_ring_init(struct amdgpu_device *adev) ring->ring_obj = NULL; ring->use_doorbell = true; - ring->doorbell_index = adev->doorbell_index.mes_ring << 1; - ring->eop_gpu_addr = adev->mes.eop_gpu_addr; + ring->doorbell_index = adev->doorbell_index.mes_ring0 << 1; + ring->eop_gpu_addr = adev->mes.eop_gpu_addr[AMDGPU_MES_SCHED_PIPE]; ring->no_scheduler = true; sprintf(ring->name, "mes_%d.%d.%d", ring->me, ring->pipe, ring->queue); @@ -852,10 +897,43 @@ static int mes_v10_1_ring_init(struct amdgpu_device *adev) AMDGPU_RING_PRIO_DEFAULT, NULL); } -static int mes_v10_1_mqd_sw_init(struct amdgpu_device *adev) +static int mes_v10_1_kiq_ring_init(struct amdgpu_device *adev) +{ + struct amdgpu_ring *ring; + + spin_lock_init(&adev->gfx.kiq.ring_lock); + + ring = &adev->gfx.kiq.ring; + + ring->me = 3; + ring->pipe = 1; + ring->queue = 0; + + ring->adev = NULL; + ring->ring_obj = NULL; + ring->use_doorbell = true; + ring->doorbell_index = adev->doorbell_index.mes_ring1 << 1; + ring->eop_gpu_addr = adev->mes.eop_gpu_addr[AMDGPU_MES_KIQ_PIPE]; + ring->no_scheduler = true; + sprintf(ring->name, "mes_kiq_%d.%d.%d", + ring->me, ring->pipe, ring->queue); + + return amdgpu_ring_init(adev, ring, 1024, NULL, 0, + AMDGPU_RING_PRIO_DEFAULT, NULL); +} + +static int mes_v10_1_mqd_sw_init(struct amdgpu_device *adev, + enum admgpu_mes_pipe pipe) { int r, mqd_size = sizeof(struct v10_compute_mqd); - struct amdgpu_ring *ring = &adev->mes.ring; + struct amdgpu_ring *ring; + + if (pipe == AMDGPU_MES_KIQ_PIPE) + ring = &adev->gfx.kiq.ring; + else if (pipe == AMDGPU_MES_SCHED_PIPE) + ring = &adev->mes.ring; + else + BUG(); if (ring->mqd_obj) return 0; @@ -867,10 +945,11 @@ static int mes_v10_1_mqd_sw_init(struct amdgpu_device *adev) dev_warn(adev->dev, "failed to create ring mqd bo (%d)", r); return r; } + memset(ring->mqd_ptr, 0, mqd_size); /* prepare MQD backup */ - adev->mes.mqd_backup = kmalloc(mqd_size, GFP_KERNEL); - if (!adev->mes.mqd_backup) + adev->mes.mqd_backup[pipe] = kmalloc(mqd_size, GFP_KERNEL); + if (!adev->mes.mqd_backup[pipe]) dev_warn(adev->dev, "no memory to create MQD backup for ring %s\n", ring->name); @@ -880,29 +959,41 @@ static int mes_v10_1_mqd_sw_init(struct amdgpu_device *adev) static int mes_v10_1_sw_init(void *handle) { - int r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; + int pipe, r; adev->mes.adev = adev; adev->mes.funcs = &mes_v10_1_funcs; + adev->mes.kiq_hw_init = &mes_v10_1_kiq_hw_init; - r = mes_v10_1_init_microcode(adev); + r = amdgpu_mes_init(adev); if (r) return r; - r = mes_v10_1_allocate_eop_buf(adev); - if (r) - return r; + for (pipe = 0; pipe < AMDGPU_MAX_MES_PIPES; pipe++) { + if (!adev->enable_mes_kiq && pipe == AMDGPU_MES_KIQ_PIPE) + continue; - r = mes_v10_1_mqd_sw_init(adev); - if (r) - return r; + r = mes_v10_1_init_microcode(adev, pipe); + if (r) + return r; - r = mes_v10_1_ring_init(adev); - if (r) - return r; + r = mes_v10_1_allocate_eop_buf(adev, pipe); + if (r) + return r; - r = mes_v10_1_allocate_mem_slots(adev); + r = mes_v10_1_mqd_sw_init(adev, pipe); + if (r) + return r; + } + + if (adev->enable_mes_kiq) { + r = mes_v10_1_kiq_ring_init(adev); + if (r) + return r; + } + + r = mes_v10_1_ring_init(adev); if (r) return r; @@ -912,40 +1003,116 @@ static int mes_v10_1_sw_init(void *handle) static int mes_v10_1_sw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + int pipe; amdgpu_device_wb_free(adev, adev->mes.sch_ctx_offs); amdgpu_device_wb_free(adev, adev->mes.query_status_fence_offs); - kfree(adev->mes.mqd_backup); + for (pipe = 0; pipe < AMDGPU_MAX_MES_PIPES; pipe++) { + kfree(adev->mes.mqd_backup[pipe]); + + amdgpu_bo_free_kernel(&adev->mes.eop_gpu_obj[pipe], + &adev->mes.eop_gpu_addr[pipe], + NULL); + + mes_v10_1_free_microcode(adev, pipe); + } + + amdgpu_bo_free_kernel(&adev->gfx.kiq.ring.mqd_obj, + &adev->gfx.kiq.ring.mqd_gpu_addr, + &adev->gfx.kiq.ring.mqd_ptr); amdgpu_bo_free_kernel(&adev->mes.ring.mqd_obj, &adev->mes.ring.mqd_gpu_addr, &adev->mes.ring.mqd_ptr); - amdgpu_bo_free_kernel(&adev->mes.eop_gpu_obj, - &adev->mes.eop_gpu_addr, - NULL); - - mes_v10_1_free_microcode(adev); + amdgpu_ring_fini(&adev->gfx.kiq.ring); + amdgpu_ring_fini(&adev->mes.ring); + amdgpu_mes_fini(adev); return 0; } -static int mes_v10_1_hw_init(void *handle) +static void mes_v10_1_kiq_setting(struct amdgpu_ring *ring) { - int r; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; + uint32_t tmp; + struct amdgpu_device *adev = ring->adev; + + /* tell RLC which is KIQ queue */ + switch (adev->ip_versions[GC_HWIP][0]) { + case IP_VERSION(10, 3, 0): + case IP_VERSION(10, 3, 2): + case IP_VERSION(10, 3, 1): + case IP_VERSION(10, 3, 4): + tmp = RREG32_SOC15(GC, 0, mmRLC_CP_SCHEDULERS_Sienna_Cichlid); + tmp &= 0xffffff00; + tmp |= (ring->me << 5) | (ring->pipe << 3) | (ring->queue); + WREG32_SOC15(GC, 0, mmRLC_CP_SCHEDULERS_Sienna_Cichlid, tmp); + tmp |= 0x80; + WREG32_SOC15(GC, 0, mmRLC_CP_SCHEDULERS_Sienna_Cichlid, tmp); + break; + default: + tmp = RREG32_SOC15(GC, 0, mmRLC_CP_SCHEDULERS); + tmp &= 0xffffff00; + tmp |= (ring->me << 5) | (ring->pipe << 3) | (ring->queue); + WREG32_SOC15(GC, 0, mmRLC_CP_SCHEDULERS, tmp); + tmp |= 0x80; + WREG32_SOC15(GC, 0, mmRLC_CP_SCHEDULERS, tmp); + break; + } +} + +static int mes_v10_1_kiq_hw_init(struct amdgpu_device *adev) +{ + int r = 0; if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { - r = mes_v10_1_load_microcode(adev); + r = mes_v10_1_load_microcode(adev, AMDGPU_MES_KIQ_PIPE); if (r) { - DRM_ERROR("failed to MES fw, r=%d\n", r); + DRM_ERROR("failed to load MES kiq fw, r=%d\n", r); + return r; + } + + r = mes_v10_1_load_microcode(adev, AMDGPU_MES_SCHED_PIPE); + if (r) { + DRM_ERROR("failed to load MES fw, r=%d\n", r); return r; } } mes_v10_1_enable(adev, true); + mes_v10_1_kiq_setting(&adev->gfx.kiq.ring); + + r = mes_v10_1_queue_init(adev); + if (r) + goto failure; + + return r; + +failure: + mes_v10_1_hw_fini(adev); + return r; +} + +static int mes_v10_1_hw_init(void *handle) +{ + int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (!adev->enable_mes_kiq) { + if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { + r = mes_v10_1_load_microcode(adev, + AMDGPU_MES_SCHED_PIPE); + if (r) { + DRM_ERROR("failed to MES fw, r=%d\n", r); + return r; + } + } + + mes_v10_1_enable(adev, true); + } + r = mes_v10_1_queue_init(adev); if (r) goto failure; @@ -960,6 +1127,13 @@ static int mes_v10_1_hw_init(void *handle) goto failure; } + /* + * Disable KIQ ring usage from the driver once MES is enabled. + * MES uses KIQ ring exclusively so driver cannot access KIQ ring + * with MES enabled. + */ + adev->gfx.kiq.ring.sched.ready = false; + return 0; failure: @@ -973,24 +1147,50 @@ static int mes_v10_1_hw_fini(void *handle) mes_v10_1_enable(adev, false); - if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) - mes_v10_1_free_ucode_buffers(adev); + if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { + mes_v10_1_free_ucode_buffers(adev, AMDGPU_MES_KIQ_PIPE); + mes_v10_1_free_ucode_buffers(adev, AMDGPU_MES_SCHED_PIPE); + } return 0; } static int mes_v10_1_suspend(void *handle) { - return 0; + int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + r = amdgpu_mes_suspend(adev); + if (r) + return r; + + return mes_v10_1_hw_fini(adev); } static int mes_v10_1_resume(void *handle) { + int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + r = mes_v10_1_hw_init(adev); + if (r) + return r; + + return amdgpu_mes_resume(adev); +} + +static int mes_v10_0_late_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + amdgpu_mes_self_test(adev); + return 0; } static const struct amd_ip_funcs mes_v10_1_ip_funcs = { .name = "mes_v10_1", + .late_init = mes_v10_0_late_init, .sw_init = mes_v10_1_sw_init, .sw_fini = mes_v10_1_sw_fini, .hw_init = mes_v10_1_hw_init, |