amdgpu_debugfs_gpr_read() drops its runtime PM reference right after
reading the wave registers. When copying them to userspace fails, it
jumps to the err label, which drops the reference a second time. A read
into a bad buffer on Navi31 either steals a reference somebody else
holds (power/runtime_usage goes from 1 to 0) or underflows the count:
amdgpu 0000:03:00.0: Runtime PM usage count underflow!
The registers are already in the kernel buffer at that point, so finish
the hardware access first and copy the buffer with a single
copy_to_user() instead of the put_user() loop with its own error path.
Fixes: 9eee152aab56 ("drm/amdgpu/debugfs: fix ref count leak when
pm_runtime_get_sync fails")
Signed-off-by: Jesse Zhang <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 21 +++------------------
1 file changed, 3 insertions(+), 18 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
index 35cbd358c28c..3dc95d9accf2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
@@ -1267,7 +1267,6 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f,
char __user *buf,
{
struct amdgpu_device *adev = f->f_inode->i_private;
int r;
- ssize_t result = 0;
uint32_t offset, se, sh, cu, wave, simd, thread, bank, *data;
if (size > 4096 || size & 3 || *pos & 3)
@@ -1311,25 +1310,11 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f,
char __user *buf,
mutex_unlock(&adev->grbm_idx_mutex);
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
+ amdgpu_virt_disable_access_debugfs(adev);
- while (size) {
- uint32_t value;
-
- value = data[result >> 2];
- r = put_user(value, (uint32_t *)buf);
- if (r) {
- amdgpu_virt_disable_access_debugfs(adev);
- goto err;
- }
-
- result += 4;
- buf += 4;
- size -= 4;
- }
-
+ r = copy_to_user(buf, data, size) ? -EFAULT : size;
kfree(data);
- amdgpu_virt_disable_access_debugfs(adev);
- return result;
+ return r;
err:
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
--
2.50.1