diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 97 |
1 files changed, 74 insertions, 23 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c index 0d4c77c1b4b5..e3972673fd64 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c @@ -103,7 +103,7 @@ static inline u32 amdgpu_mes_get_hqd_mask(u32 num_pipe, int amdgpu_mes_init(struct amdgpu_device *adev) { - int i, r, num_pipes; + int i, r, num_pipes, num_queues = 0; u32 total_vmid_mask, reserved_vmid_mask; int num_xcc = adev->gfx.xcc_mask ? NUM_XCC(adev->gfx.xcc_mask) : 1; u32 gfx_hqd_mask = amdgpu_mes_get_hqd_mask(adev->gfx.me.num_pipe_per_me, @@ -159,7 +159,8 @@ int amdgpu_mes_init(struct amdgpu_device *adev) adev->mes.compute_hqd_mask[i] = compute_hqd_mask; } - num_pipes = adev->sdma.num_instances; + num_pipes = adev->sdma.num_inst_per_xcc ? + adev->sdma.num_inst_per_xcc : adev->sdma.num_instances; if (num_pipes > AMDGPU_MES_MAX_SDMA_PIPES) dev_warn(adev->dev, "more SDMA pipes than supported by MES! (%d vs %d)\n", num_pipes, AMDGPU_MES_MAX_SDMA_PIPES); @@ -216,8 +217,27 @@ int amdgpu_mes_init(struct amdgpu_device *adev) if (r) goto error_doorbell; + if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 1, 0)) { + /* When queue/pipe reset is done in MES instead of in the + * driver, MES passes hung queues information to the driver in + * hung_queue_hqd_info. Calculate required space to store this + * information. + */ + for (i = 0; i < AMDGPU_MES_MAX_GFX_PIPES; i++) + num_queues += hweight32(adev->mes.gfx_hqd_mask[i]); + + for (i = 0; i < AMDGPU_MES_MAX_COMPUTE_PIPES; i++) + num_queues += hweight32(adev->mes.compute_hqd_mask[i]); + + for (i = 0; i < AMDGPU_MES_MAX_SDMA_PIPES; i++) + num_queues += hweight32(adev->mes.sdma_hqd_mask[i]) * num_xcc; + + adev->mes.hung_queue_hqd_info_offset = num_queues; + adev->mes.hung_queue_db_array_size = num_queues * 2; + } + if (adev->mes.hung_queue_db_array_size) { - for (i = 0; i < AMDGPU_MAX_MES_PIPES * num_xcc; i++) { + for (i = 0; i < AMDGPU_MAX_MES_PIPES; i++) { r = amdgpu_bo_create_kernel(adev, adev->mes.hung_queue_db_array_size * sizeof(u32), PAGE_SIZE, @@ -264,10 +284,10 @@ void amdgpu_mes_fini(struct amdgpu_device *adev) &adev->mes.event_log_cpu_addr); for (i = 0; i < AMDGPU_MAX_MES_PIPES * num_xcc; i++) { - amdgpu_bo_free_kernel(&adev->mes.hung_queue_db_array_gpu_obj[i], - &adev->mes.hung_queue_db_array_gpu_addr[i], - &adev->mes.hung_queue_db_array_cpu_addr[i]); - + if (adev->mes.hung_queue_db_array_gpu_obj[i]) + amdgpu_bo_free_kernel(&adev->mes.hung_queue_db_array_gpu_obj[i], + &adev->mes.hung_queue_db_array_gpu_addr[i], + &adev->mes.hung_queue_db_array_cpu_addr[i]); if (adev->mes.sch_ctx_ptr[i]) amdgpu_device_wb_free(adev, adev->mes.sch_ctx_offs[i]); if (adev->mes.query_status_fence_ptr[i]) @@ -281,7 +301,7 @@ void amdgpu_mes_fini(struct amdgpu_device *adev) mutex_destroy(&adev->mes.mutex_hidden); } -int amdgpu_mes_suspend(struct amdgpu_device *adev) +int amdgpu_mes_suspend(struct amdgpu_device *adev, u32 xcc_id) { struct mes_suspend_gang_input input; int r; @@ -291,6 +311,10 @@ int amdgpu_mes_suspend(struct amdgpu_device *adev) memset(&input, 0x0, sizeof(struct mes_suspend_gang_input)); input.suspend_all_gangs = 1; + input.xcc_id = xcc_id; + if ((amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(12, 1, 0)) && + ((adev->mes.sched_version & AMDGPU_MES_VERSION_MASK) >= 0x71)) + input.suspend_all_sdma_gangs = 1; /* * Avoid taking any other locks under MES lock to avoid circular @@ -305,7 +329,7 @@ int amdgpu_mes_suspend(struct amdgpu_device *adev) return r; } -int amdgpu_mes_resume(struct amdgpu_device *adev) +int amdgpu_mes_resume(struct amdgpu_device *adev, u32 xcc_id) { struct mes_resume_gang_input input; int r; @@ -315,6 +339,7 @@ int amdgpu_mes_resume(struct amdgpu_device *adev) memset(&input, 0x0, sizeof(struct mes_resume_gang_input)); input.resume_all_gangs = 1; + input.xcc_id = xcc_id; /* * Avoid taking any other locks under MES lock to avoid circular @@ -428,7 +453,7 @@ int amdgpu_mes_detect_and_reset_hung_queues(struct amdgpu_device *adev, { struct mes_detect_and_reset_queue_input input; u32 *db_array = adev->mes.hung_queue_db_array_cpu_addr[xcc_id]; - int r, i; + int hqd_info_offset = adev->mes.hung_queue_hqd_info_offset, r, i; if (!hung_db_num || !hung_db_array) return -EINVAL; @@ -443,26 +468,34 @@ int amdgpu_mes_detect_and_reset_hung_queues(struct amdgpu_device *adev, adev->mes.hung_queue_db_array_size * sizeof(u32)); input.queue_type = queue_type; input.detect_only = detect_only; + input.xcc_id = xcc_id; r = adev->mes.funcs->detect_and_reset_hung_queues(&adev->mes, &input); - if (r) { - dev_err(adev->dev, "failed to detect and reset\n"); - } else { - *hung_db_num = 0; - for (i = 0; i < adev->mes.hung_queue_hqd_info_offset; i++) { - if (db_array[i] != AMDGPU_MES_INVALID_DB_OFFSET) { - hung_db_array[i] = db_array[i]; - *hung_db_num += 1; - } + + if (r && detect_only) { + dev_err(adev->dev, "Failed to detect hung queues\n"); + return r; + } + + *hung_db_num = 0; + /* MES passes hung queues' doorbell to driver */ + for (i = 0; i < adev->mes.hung_queue_hqd_info_offset; i++) { + /* Finding hung queues where db_array[i] is a valid doorbell */ + if (db_array[i] != AMDGPU_MES_INVALID_DB_OFFSET) { + hung_db_array[i] = db_array[i]; + *hung_db_num += 1; } + } - /* - * TODO: return HQD info for MES scheduled user compute queue reset cases - * stored in hung_db_array hqd info offset to full array size - */ + if (r && !(*hung_db_num)) { + dev_err(adev->dev, "Failed to detect and reset hung queues\n"); + return r; } + for (i = hqd_info_offset; i < hqd_info_offset + *hung_db_num; i++) + hung_db_array[i] = db_array[i]; + return r; } @@ -748,6 +781,18 @@ out: return r; } +void amdgpu_mes_validate_fw_version(struct amdgpu_device *adev) +{ + u32 fw_from_ucode = adev->mes.fw_version[AMDGPU_MES_SCHED_PIPE]; + u32 fw_from_reg = adev->mes.sched_version & AMDGPU_MES_VERSION_MASK; + + if (fw_from_ucode != fw_from_reg) + dev_info(adev->dev, + "MES firmware reports incorrect version in ucode binary (0x%x vs 0x%x)\n", + fw_from_ucode, fw_from_reg); +} + + bool amdgpu_mes_suspend_resume_all_supported(struct amdgpu_device *adev) { uint32_t mes_rev = adev->mes.sched_version & AMDGPU_MES_VERSION_MASK; @@ -758,6 +803,12 @@ bool amdgpu_mes_suspend_resume_all_supported(struct amdgpu_device *adev) amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 0, 0)); } +bool amdgpu_mes_queue_reset_by_mes_supported(struct amdgpu_device *adev) +{ + return (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(12, 1, 0) && + (adev->mes.sched_version & AMDGPU_MES_VERSION_MASK) >= 0x73); +} + /* Fix me -- node_id is used to identify the correct MES instances in the future */ static int amdgpu_mes_set_enforce_isolation(struct amdgpu_device *adev, uint32_t node_id, bool enable) |
