amd-drm-fixes-6.9-2024-04-24:
amdgpu: - Suspend/resume fix - Don't expose gpu_od directory if it's empty - SDMA 4.4.2 fix - VPE fix - BO eviction fix - UMSCH fix - SMU 13.0.6 reset fixes - GPUVM flush accounting fix - SDMA 5.2 fix - Fix possible UAF in mes code amdkfd: - Eviction fence handling fix - Fix memory leak when GPU memory allocation fails - Fix dma-buf validation - Fix rescheduling of restore worker - SVM fix -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCZilpfgAKCRC93/aFa7yZ 2AaRAP9OptPS/1JwNDHWD3pTGhXYbowVl6tVAWrMKT1JDotixAD/T4+jAQTcghTD tKmhqX1ULNqijmYZPXBIsGpDM45Fgw4= =Pnrb -----END PGP SIGNATURE----- Merge tag 'amd-drm-fixes-6.9-2024-04-24' of https://gitlab.freedesktop.org/agd5f/linux into drm-fixes amd-drm-fixes-6.9-2024-04-24: amdgpu: - Suspend/resume fix - Don't expose gpu_od directory if it's empty - SDMA 4.4.2 fix - VPE fix - BO eviction fix - UMSCH fix - SMU 13.0.6 reset fixes - GPUVM flush accounting fix - SDMA 5.2 fix - Fix possible UAF in mes code amdkfd: - Eviction fence handling fix - Fix memory leak when GPU memory allocation fails - Fix dma-buf validation - Fix rescheduling of restore worker - SVM fix Signed-off-by: Dave Airlie <airlied@redhat.com> From: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20240424202408.1973661-1-alexander.deucher@amd.com
This commit is contained in:
commit
26da9bfdb8
@ -1854,6 +1854,7 @@ err_node_allow:
|
||||
err_bo_create:
|
||||
amdgpu_amdkfd_unreserve_mem_limit(adev, aligned_size, flags, xcp_id);
|
||||
err_reserve_limit:
|
||||
amdgpu_sync_free(&(*mem)->sync);
|
||||
mutex_destroy(&(*mem)->lock);
|
||||
if (gobj)
|
||||
drm_gem_object_put(gobj);
|
||||
@ -2900,13 +2901,12 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence __rcu *
|
||||
|
||||
amdgpu_sync_create(&sync_obj);
|
||||
|
||||
/* Validate BOs and map them to GPUVM (update VM page tables). */
|
||||
/* Validate BOs managed by KFD */
|
||||
list_for_each_entry(mem, &process_info->kfd_bo_list,
|
||||
validate_list) {
|
||||
|
||||
struct amdgpu_bo *bo = mem->bo;
|
||||
uint32_t domain = mem->domain;
|
||||
struct kfd_mem_attachment *attachment;
|
||||
struct dma_resv_iter cursor;
|
||||
struct dma_fence *fence;
|
||||
|
||||
@ -2931,6 +2931,25 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence __rcu *
|
||||
goto validate_map_fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (failed_size)
|
||||
pr_debug("0x%lx/0x%lx in system\n", failed_size, total_size);
|
||||
|
||||
/* Validate PDs, PTs and evicted DMABuf imports last. Otherwise BO
|
||||
* validations above would invalidate DMABuf imports again.
|
||||
*/
|
||||
ret = process_validate_vms(process_info, &exec.ticket);
|
||||
if (ret) {
|
||||
pr_debug("Validating VMs failed, ret: %d\n", ret);
|
||||
goto validate_map_fail;
|
||||
}
|
||||
|
||||
/* Update mappings managed by KFD. */
|
||||
list_for_each_entry(mem, &process_info->kfd_bo_list,
|
||||
validate_list) {
|
||||
struct kfd_mem_attachment *attachment;
|
||||
|
||||
list_for_each_entry(attachment, &mem->attachments, list) {
|
||||
if (!attachment->is_mapped)
|
||||
continue;
|
||||
@ -2947,18 +2966,6 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence __rcu *
|
||||
}
|
||||
}
|
||||
|
||||
if (failed_size)
|
||||
pr_debug("0x%lx/0x%lx in system\n", failed_size, total_size);
|
||||
|
||||
/* Validate PDs, PTs and evicted DMABuf imports last. Otherwise BO
|
||||
* validations above would invalidate DMABuf imports again.
|
||||
*/
|
||||
ret = process_validate_vms(process_info, &exec.ticket);
|
||||
if (ret) {
|
||||
pr_debug("Validating VMs failed, ret: %d\n", ret);
|
||||
goto validate_map_fail;
|
||||
}
|
||||
|
||||
/* Update mappings not managed by KFD */
|
||||
list_for_each_entry(peer_vm, &process_info->vm_list_head,
|
||||
vm_list_node) {
|
||||
|
@ -1132,6 +1132,7 @@ void amdgpu_mes_remove_ring(struct amdgpu_device *adev,
|
||||
return;
|
||||
|
||||
amdgpu_mes_remove_hw_queue(adev, ring->hw_queue_id);
|
||||
del_timer_sync(&ring->fence_drv.fallback_timer);
|
||||
amdgpu_ring_fini(ring);
|
||||
kfree(ring);
|
||||
}
|
||||
|
@ -605,6 +605,8 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
|
||||
else
|
||||
amdgpu_bo_placement_from_domain(bo, bp->domain);
|
||||
if (bp->type == ttm_bo_type_kernel)
|
||||
bo->tbo.priority = 2;
|
||||
else if (!(bp->flags & AMDGPU_GEM_CREATE_DISCARDABLE))
|
||||
bo->tbo.priority = 1;
|
||||
|
||||
if (!bp->destroy)
|
||||
|
@ -774,6 +774,9 @@ static int umsch_mm_late_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
if (amdgpu_in_reset(adev) || adev->in_s0ix || adev->in_suspend)
|
||||
return 0;
|
||||
|
||||
return umsch_mm_test(adev);
|
||||
}
|
||||
|
||||
|
@ -205,7 +205,7 @@ disable_dpm:
|
||||
dpm_ctl &= 0xfffffffe; /* Disable DPM */
|
||||
WREG32(vpe_get_reg_offset(vpe, 0, vpe->regs.dpm_enable), dpm_ctl);
|
||||
dev_dbg(adev->dev, "%s: disable vpe dpm\n", __func__);
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int amdgpu_vpe_psp_update_sram(struct amdgpu_device *adev)
|
||||
|
@ -9186,7 +9186,7 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_gfx = {
|
||||
7 + /* PIPELINE_SYNC */
|
||||
SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
|
||||
SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
|
||||
2 + /* VM_FLUSH */
|
||||
4 + /* VM_FLUSH */
|
||||
8 + /* FENCE for VM_FLUSH */
|
||||
20 + /* GDS switch */
|
||||
4 + /* double SWITCH_BUFFER,
|
||||
@ -9276,7 +9276,6 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_kiq = {
|
||||
7 + /* gfx_v10_0_ring_emit_pipeline_sync */
|
||||
SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
|
||||
SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
|
||||
2 + /* gfx_v10_0_ring_emit_vm_flush */
|
||||
8 + 8 + 8, /* gfx_v10_0_ring_emit_fence_kiq x3 for user fence, vm fence */
|
||||
.emit_ib_size = 7, /* gfx_v10_0_ring_emit_ib_compute */
|
||||
.emit_ib = gfx_v10_0_ring_emit_ib_compute,
|
||||
|
@ -6192,7 +6192,7 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_gfx = {
|
||||
7 + /* PIPELINE_SYNC */
|
||||
SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
|
||||
SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
|
||||
2 + /* VM_FLUSH */
|
||||
4 + /* VM_FLUSH */
|
||||
8 + /* FENCE for VM_FLUSH */
|
||||
20 + /* GDS switch */
|
||||
5 + /* COND_EXEC */
|
||||
@ -6278,7 +6278,6 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_kiq = {
|
||||
7 + /* gfx_v11_0_ring_emit_pipeline_sync */
|
||||
SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
|
||||
SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
|
||||
2 + /* gfx_v11_0_ring_emit_vm_flush */
|
||||
8 + 8 + 8, /* gfx_v11_0_ring_emit_fence_kiq x3 for user fence, vm fence */
|
||||
.emit_ib_size = 7, /* gfx_v11_0_ring_emit_ib_compute */
|
||||
.emit_ib = gfx_v11_0_ring_emit_ib_compute,
|
||||
|
@ -6981,7 +6981,6 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_compute = {
|
||||
7 + /* gfx_v9_0_ring_emit_pipeline_sync */
|
||||
SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
|
||||
SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
|
||||
2 + /* gfx_v9_0_ring_emit_vm_flush */
|
||||
8 + 8 + 8 + /* gfx_v9_0_ring_emit_fence x3 for user fence, vm fence */
|
||||
7 + /* gfx_v9_0_emit_mem_sync */
|
||||
5 + /* gfx_v9_0_emit_wave_limit for updating mmSPI_WCL_PIPE_PERCENT_GFX register */
|
||||
@ -7019,7 +7018,6 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_kiq = {
|
||||
7 + /* gfx_v9_0_ring_emit_pipeline_sync */
|
||||
SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
|
||||
SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
|
||||
2 + /* gfx_v9_0_ring_emit_vm_flush */
|
||||
8 + 8 + 8, /* gfx_v9_0_ring_emit_fence_kiq x3 for user fence, vm fence */
|
||||
.emit_ib_size = 7, /* gfx_v9_0_ring_emit_ib_compute */
|
||||
.emit_fence = gfx_v9_0_ring_emit_fence_kiq,
|
||||
|
@ -368,7 +368,8 @@ static void sdma_v4_4_2_ring_emit_hdp_flush(struct amdgpu_ring *ring)
|
||||
u32 ref_and_mask = 0;
|
||||
const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio.hdp_flush_reg;
|
||||
|
||||
ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0 << ring->me;
|
||||
ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0
|
||||
<< (ring->me % adev->sdma.num_inst_per_aid);
|
||||
|
||||
sdma_v4_4_2_wait_reg_mem(ring, 0, 1,
|
||||
adev->nbio.funcs->get_hdp_flush_done_offset(adev),
|
||||
|
@ -280,17 +280,21 @@ static void sdma_v5_2_ring_emit_hdp_flush(struct amdgpu_ring *ring)
|
||||
u32 ref_and_mask = 0;
|
||||
const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio.hdp_flush_reg;
|
||||
|
||||
ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0 << ring->me;
|
||||
if (ring->me > 1) {
|
||||
amdgpu_asic_flush_hdp(adev, ring);
|
||||
} else {
|
||||
ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0 << ring->me;
|
||||
|
||||
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
|
||||
SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(1) |
|
||||
SDMA_PKT_POLL_REGMEM_HEADER_FUNC(3)); /* == */
|
||||
amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_done_offset(adev)) << 2);
|
||||
amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_req_offset(adev)) << 2);
|
||||
amdgpu_ring_write(ring, ref_and_mask); /* reference */
|
||||
amdgpu_ring_write(ring, ref_and_mask); /* mask */
|
||||
amdgpu_ring_write(ring, SDMA_PKT_POLL_REGMEM_DW5_RETRY_COUNT(0xfff) |
|
||||
SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); /* retry count, poll interval */
|
||||
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
|
||||
SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(1) |
|
||||
SDMA_PKT_POLL_REGMEM_HEADER_FUNC(3)); /* == */
|
||||
amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_done_offset(adev)) << 2);
|
||||
amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_req_offset(adev)) << 2);
|
||||
amdgpu_ring_write(ring, ref_and_mask); /* reference */
|
||||
amdgpu_ring_write(ring, ref_and_mask); /* mask */
|
||||
amdgpu_ring_write(ring, SDMA_PKT_POLL_REGMEM_DW5_RETRY_COUNT(0xfff) |
|
||||
SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); /* retry count, poll interval */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -144,6 +144,12 @@ static int vpe_v6_1_load_microcode(struct amdgpu_vpe *vpe)
|
||||
WREG32(vpe_get_reg_offset(vpe, j, regVPEC_CNTL), ret);
|
||||
}
|
||||
|
||||
/* setup collaborate mode */
|
||||
vpe_v6_1_set_collaborate_mode(vpe, true);
|
||||
/* setup DPM */
|
||||
if (amdgpu_vpe_configure_dpm(vpe))
|
||||
dev_warn(adev->dev, "VPE failed to enable DPM\n");
|
||||
|
||||
/*
|
||||
* For VPE 6.1.1, still only need to add master's offset, and psp will apply it to slave as well.
|
||||
* Here use instance 0 as master.
|
||||
@ -159,11 +165,7 @@ static int vpe_v6_1_load_microcode(struct amdgpu_vpe *vpe)
|
||||
adev->vpe.cmdbuf_cpu_addr[0] = f32_offset;
|
||||
adev->vpe.cmdbuf_cpu_addr[1] = f32_cntl;
|
||||
|
||||
amdgpu_vpe_psp_update_sram(adev);
|
||||
vpe_v6_1_set_collaborate_mode(vpe, true);
|
||||
amdgpu_vpe_configure_dpm(vpe);
|
||||
|
||||
return 0;
|
||||
return amdgpu_vpe_psp_update_sram(adev);
|
||||
}
|
||||
|
||||
vpe_hdr = (const struct vpe_firmware_header_v1_0 *)adev->vpe.fw->data;
|
||||
@ -196,8 +198,6 @@ static int vpe_v6_1_load_microcode(struct amdgpu_vpe *vpe)
|
||||
}
|
||||
|
||||
vpe_v6_1_halt(vpe, false);
|
||||
vpe_v6_1_set_collaborate_mode(vpe, true);
|
||||
amdgpu_vpe_configure_dpm(vpe);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -509,10 +509,19 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
|
||||
start = start_mgr << PAGE_SHIFT;
|
||||
end = (last_mgr + 1) << PAGE_SHIFT;
|
||||
|
||||
r = amdgpu_amdkfd_reserve_mem_limit(node->adev,
|
||||
prange->npages * PAGE_SIZE,
|
||||
KFD_IOC_ALLOC_MEM_FLAGS_VRAM,
|
||||
node->xcp ? node->xcp->id : 0);
|
||||
if (r) {
|
||||
dev_dbg(node->adev->dev, "failed to reserve VRAM, r: %ld\n", r);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
r = svm_range_vram_node_new(node, prange, true);
|
||||
if (r) {
|
||||
dev_dbg(node->adev->dev, "fail %ld to alloc vram\n", r);
|
||||
return r;
|
||||
goto out;
|
||||
}
|
||||
ttm_res_offset = (start_mgr - prange->start + prange->offset) << PAGE_SHIFT;
|
||||
|
||||
@ -545,6 +554,11 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
|
||||
svm_range_vram_node_free(prange);
|
||||
}
|
||||
|
||||
out:
|
||||
amdgpu_amdkfd_unreserve_mem_limit(node->adev,
|
||||
prange->npages * PAGE_SIZE,
|
||||
KFD_IOC_ALLOC_MEM_FLAGS_VRAM,
|
||||
node->xcp ? node->xcp->id : 0);
|
||||
return r < 0 ? r : 0;
|
||||
}
|
||||
|
||||
|
@ -1922,6 +1922,8 @@ static int signal_eviction_fence(struct kfd_process *p)
|
||||
rcu_read_lock();
|
||||
ef = dma_fence_get_rcu_safe(&p->ef);
|
||||
rcu_read_unlock();
|
||||
if (!ef)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dma_fence_signal(ef);
|
||||
dma_fence_put(ef);
|
||||
@ -1949,10 +1951,9 @@ static void evict_process_worker(struct work_struct *work)
|
||||
* they are responsible stopping the queues and scheduling
|
||||
* the restore work.
|
||||
*/
|
||||
if (!signal_eviction_fence(p))
|
||||
queue_delayed_work(kfd_restore_wq, &p->restore_work,
|
||||
msecs_to_jiffies(PROCESS_RESTORE_TIME_MS));
|
||||
else
|
||||
if (signal_eviction_fence(p) ||
|
||||
mod_delayed_work(kfd_restore_wq, &p->restore_work,
|
||||
msecs_to_jiffies(PROCESS_RESTORE_TIME_MS)))
|
||||
kfd_process_restore_queues(p);
|
||||
|
||||
pr_debug("Finished evicting pasid 0x%x\n", p->pasid);
|
||||
@ -2011,9 +2012,9 @@ static void restore_process_worker(struct work_struct *work)
|
||||
if (ret) {
|
||||
pr_debug("Failed to restore BOs of pasid 0x%x, retry after %d ms\n",
|
||||
p->pasid, PROCESS_BACK_OFF_TIME_MS);
|
||||
ret = queue_delayed_work(kfd_restore_wq, &p->restore_work,
|
||||
msecs_to_jiffies(PROCESS_BACK_OFF_TIME_MS));
|
||||
WARN(!ret, "reschedule restore work failed\n");
|
||||
if (mod_delayed_work(kfd_restore_wq, &p->restore_work,
|
||||
msecs_to_jiffies(PROCESS_RESTORE_TIME_MS)))
|
||||
kfd_process_restore_queues(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3426,7 +3426,7 @@ svm_range_trigger_migration(struct mm_struct *mm, struct svm_range *prange,
|
||||
mm, KFD_MIGRATE_TRIGGER_PREFETCH);
|
||||
*migrated = !r;
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int svm_range_schedule_evict_svm_bo(struct amdgpu_amdkfd_fence *fence)
|
||||
|
@ -3029,6 +3029,7 @@ static int dm_resume(void *handle)
|
||||
dc_stream_release(dm_new_crtc_state->stream);
|
||||
dm_new_crtc_state->stream = NULL;
|
||||
}
|
||||
dm_new_crtc_state->base.color_mgmt_changed = true;
|
||||
}
|
||||
|
||||
for_each_new_plane_in_state(dm->cached_state, plane, new_plane_state, i) {
|
||||
|
@ -4261,6 +4261,13 @@ static int amdgpu_od_set_init(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If gpu_od is the only member in the list, that means gpu_od is an
|
||||
* empty directory, so remove it.
|
||||
*/
|
||||
if (list_is_singular(&adev->pm.od_kobj_list))
|
||||
goto err_out;
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
|
@ -2294,6 +2294,17 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
|
||||
return sizeof(*gpu_metrics);
|
||||
}
|
||||
|
||||
static void smu_v13_0_6_restore_pci_config(struct smu_context *smu)
|
||||
{
|
||||
struct amdgpu_device *adev = smu->adev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
pci_write_config_dword(adev->pdev, i * 4,
|
||||
adev->pdev->saved_config_space[i]);
|
||||
pci_restore_msi_state(adev->pdev);
|
||||
}
|
||||
|
||||
static int smu_v13_0_6_mode2_reset(struct smu_context *smu)
|
||||
{
|
||||
int ret = 0, index;
|
||||
@ -2315,6 +2326,20 @@ static int smu_v13_0_6_mode2_reset(struct smu_context *smu)
|
||||
/* Restore the config space saved during init */
|
||||
amdgpu_device_load_pci_state(adev->pdev);
|
||||
|
||||
/* Certain platforms have switches which assign virtual BAR values to
|
||||
* devices. OS uses the virtual BAR values and device behind the switch
|
||||
* is assgined another BAR value. When device's config space registers
|
||||
* are queried, switch returns the virtual BAR values. When mode-2 reset
|
||||
* is performed, switch is unaware of it, and will continue to return
|
||||
* the same virtual values to the OS.This affects
|
||||
* pci_restore_config_space() API as it doesn't write the value saved if
|
||||
* the current value read from config space is the same as what is
|
||||
* saved. As a workaround, make sure the config space is restored
|
||||
* always.
|
||||
*/
|
||||
if (!(adev->flags & AMD_IS_APU))
|
||||
smu_v13_0_6_restore_pci_config(smu);
|
||||
|
||||
dev_dbg(smu->adev->dev, "wait for reset ack\n");
|
||||
do {
|
||||
ret = smu_cmn_wait_for_response(smu);
|
||||
|
Loading…
Reference in New Issue
Block a user