Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/amdkfd: Free queue after unmap queue success

After queue unmap or remove from MES successfully, free queue sysfs
entries, doorbell and remove from queue list. Otherwise, application may
destroy queue again, cause below kernel warning or crash backtrace.

For outstanding queues, either application forget to destroy or failed
to destroy, kfd_process_notifier_release will remove queue sysfs
entries, kfd_process_wq_release will free queue doorbell.

v2: decrement_queue_count for MES queue

refcount_t: underflow; use-after-free.
WARNING: CPU: 7 PID: 3053 at lib/refcount.c:28
Call Trace:
kobject_put+0xd6/0x1a0
kfd_procfs_del_queue+0x27/0x30 [amdgpu]
pqm_destroy_queue+0xeb/0x240 [amdgpu]
kfd_ioctl_destroy_queue+0x32/0x70 [amdgpu]
kfd_ioctl+0x27d/0x500 [amdgpu]
do_syscall_64+0x35/0x80

WARNING: CPU: 2 PID: 3053 at drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_device_queue_manager.c:400
Call Trace:
deallocate_doorbell.isra.0+0x39/0x40 [amdgpu]
destroy_queue_cpsch+0xb3/0x270 [amdgpu]
pqm_destroy_queue+0x108/0x240 [amdgpu]
kfd_ioctl_destroy_queue+0x32/0x70 [amdgpu]
kfd_ioctl+0x27d/0x500 [amdgpu]

general protection fault, probably for non-canonical address
0xdead000000000108:
Call Trace:
pqm_destroy_queue+0xf0/0x200 [amdgpu]
kfd_ioctl_destroy_queue+0x2f/0x60 [amdgpu]
kfd_ioctl+0x19b/0x600 [amdgpu]

Signed-off-by: Philip Yang <Philip.Yang@amd.com>
Reviewed-by: Graham Sider <Graham.Sider@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Philip Yang and committed by
Alex Deucher
ab8529b0 f4f9b827

+18 -12
+17 -11
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
··· 1872 1872 1873 1873 } 1874 1874 1875 + if (q->properties.is_active) { 1876 + if (!dqm->dev->shared_resources.enable_mes) { 1877 + retval = execute_queues_cpsch(dqm, 1878 + KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); 1879 + if (retval == -ETIME) 1880 + qpd->reset_wavefronts = true; 1881 + } else { 1882 + retval = remove_queue_mes(dqm, q, qpd); 1883 + } 1884 + 1885 + if (retval) 1886 + goto failed_unmap_queue; 1887 + 1888 + decrement_queue_count(dqm, qpd, q); 1889 + } 1890 + 1875 1891 mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( 1876 1892 q->properties.type)]; 1877 1893 ··· 1901 1885 1902 1886 list_del(&q->list); 1903 1887 qpd->queue_count--; 1904 - if (q->properties.is_active) { 1905 - if (!dqm->dev->shared_resources.enable_mes) { 1906 - decrement_queue_count(dqm, qpd, q); 1907 - retval = execute_queues_cpsch(dqm, 1908 - KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); 1909 - if (retval == -ETIME) 1910 - qpd->reset_wavefronts = true; 1911 - } else { 1912 - retval = remove_queue_mes(dqm, q, qpd); 1913 - } 1914 - } 1915 1888 1916 1889 /* 1917 1890 * Unconditionally decrement this counter, regardless of the queue's ··· 1917 1912 1918 1913 return retval; 1919 1914 1915 + failed_unmap_queue: 1920 1916 failed_try_destroy_debugged_queue: 1921 1917 1922 1918 dqm_unlock(dqm);
+1 -1
drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
··· 419 419 } 420 420 421 421 if (pqn->q) { 422 - kfd_procfs_del_queue(pqn->q); 423 422 dqm = pqn->q->device->dqm; 424 423 retval = dqm->ops.destroy_queue(dqm, &pdd->qpd, pqn->q); 425 424 if (retval) { ··· 438 439 if (dev->shared_resources.enable_mes) 439 440 amdgpu_amdkfd_free_gtt_mem(dev->adev, 440 441 pqn->q->gang_ctx_bo); 442 + kfd_procfs_del_queue(pqn->q); 441 443 uninit_queue(pqn->q); 442 444 } 443 445