diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2016-04-26 13:29:41 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2016-04-27 04:16:17 -0400 |
commit | 1d2ac403ae3bfde7c50328ee0d39d3fb3d8d9823 (patch) | |
tree | ebdb7a84d3399feeb2e06b855f5ee04550101ea4 | |
parent | f47dbdd75bf3388ce8107c2e7e5a1eebd3700dd5 (diff) |
drm: Protect dev->filelist with its own mutex
amdgpu gained dev->struct_mutex usage, and that's because it's walking
the dev->filelist list. Protect that list with it's own lock to take
one more step towards getting rid of struct_mutex usage in drivers
once and for all.
While doing the conversion I noticed that 2 debugfs files in i915
completely lacked appropriate locking. Fix that up too.
v2: don't forget to switch to drm_gem_object_unreference_unlocked.
Cc: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1461691808-12414-9-git-send-email-daniel.vetter@ffwll.ch
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_drv.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_fops.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_info.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 12 | ||||
-rw-r--r-- | include/drm/drmP.h | 1 |
6 files changed, 25 insertions, 12 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index fa6a27bff298..a087b9638cde 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | |||
@@ -93,7 +93,7 @@ void amdgpu_gem_force_release(struct amdgpu_device *adev) | |||
93 | struct drm_device *ddev = adev->ddev; | 93 | struct drm_device *ddev = adev->ddev; |
94 | struct drm_file *file; | 94 | struct drm_file *file; |
95 | 95 | ||
96 | mutex_lock(&ddev->struct_mutex); | 96 | mutex_lock(&ddev->filelist_mutex); |
97 | 97 | ||
98 | list_for_each_entry(file, &ddev->filelist, lhead) { | 98 | list_for_each_entry(file, &ddev->filelist, lhead) { |
99 | struct drm_gem_object *gobj; | 99 | struct drm_gem_object *gobj; |
@@ -103,13 +103,13 @@ void amdgpu_gem_force_release(struct amdgpu_device *adev) | |||
103 | spin_lock(&file->table_lock); | 103 | spin_lock(&file->table_lock); |
104 | idr_for_each_entry(&file->object_idr, gobj, handle) { | 104 | idr_for_each_entry(&file->object_idr, gobj, handle) { |
105 | WARN_ONCE(1, "And also active allocations!\n"); | 105 | WARN_ONCE(1, "And also active allocations!\n"); |
106 | drm_gem_object_unreference(gobj); | 106 | drm_gem_object_unreference_unlocked(gobj); |
107 | } | 107 | } |
108 | idr_destroy(&file->object_idr); | 108 | idr_destroy(&file->object_idr); |
109 | spin_unlock(&file->table_lock); | 109 | spin_unlock(&file->table_lock); |
110 | } | 110 | } |
111 | 111 | ||
112 | mutex_unlock(&ddev->struct_mutex); | 112 | mutex_unlock(&ddev->filelist_mutex); |
113 | } | 113 | } |
114 | 114 | ||
115 | /* | 115 | /* |
@@ -769,7 +769,7 @@ static int amdgpu_debugfs_gem_info(struct seq_file *m, void *data) | |||
769 | struct drm_file *file; | 769 | struct drm_file *file; |
770 | int r; | 770 | int r; |
771 | 771 | ||
772 | r = mutex_lock_interruptible(&dev->struct_mutex); | 772 | r = mutex_lock_interruptible(&dev->filelist_mutex); |
773 | if (r) | 773 | if (r) |
774 | return r; | 774 | return r; |
775 | 775 | ||
@@ -793,7 +793,7 @@ static int amdgpu_debugfs_gem_info(struct seq_file *m, void *data) | |||
793 | spin_unlock(&file->table_lock); | 793 | spin_unlock(&file->table_lock); |
794 | } | 794 | } |
795 | 795 | ||
796 | mutex_unlock(&dev->struct_mutex); | 796 | mutex_unlock(&dev->filelist_mutex); |
797 | return 0; | 797 | return 0; |
798 | } | 798 | } |
799 | 799 | ||
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index e1fb52d4f72c..bff89226a344 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c | |||
@@ -590,6 +590,7 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver, | |||
590 | spin_lock_init(&dev->buf_lock); | 590 | spin_lock_init(&dev->buf_lock); |
591 | spin_lock_init(&dev->event_lock); | 591 | spin_lock_init(&dev->event_lock); |
592 | mutex_init(&dev->struct_mutex); | 592 | mutex_init(&dev->struct_mutex); |
593 | mutex_init(&dev->filelist_mutex); | ||
593 | mutex_init(&dev->ctxlist_mutex); | 594 | mutex_init(&dev->ctxlist_mutex); |
594 | mutex_init(&dev->master_mutex); | 595 | mutex_init(&dev->master_mutex); |
595 | 596 | ||
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index c3d0aaac0669..7af7f8bcb355 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c | |||
@@ -297,9 +297,9 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor) | |||
297 | } | 297 | } |
298 | mutex_unlock(&dev->master_mutex); | 298 | mutex_unlock(&dev->master_mutex); |
299 | 299 | ||
300 | mutex_lock(&dev->struct_mutex); | 300 | mutex_lock(&dev->filelist_mutex); |
301 | list_add(&priv->lhead, &dev->filelist); | 301 | list_add(&priv->lhead, &dev->filelist); |
302 | mutex_unlock(&dev->struct_mutex); | 302 | mutex_unlock(&dev->filelist_mutex); |
303 | 303 | ||
304 | #ifdef __alpha__ | 304 | #ifdef __alpha__ |
305 | /* | 305 | /* |
@@ -447,8 +447,11 @@ int drm_release(struct inode *inode, struct file *filp) | |||
447 | 447 | ||
448 | DRM_DEBUG("open_count = %d\n", dev->open_count); | 448 | DRM_DEBUG("open_count = %d\n", dev->open_count); |
449 | 449 | ||
450 | mutex_lock(&dev->struct_mutex); | 450 | mutex_lock(&dev->filelist_mutex); |
451 | list_del(&file_priv->lhead); | 451 | list_del(&file_priv->lhead); |
452 | mutex_unlock(&dev->filelist_mutex); | ||
453 | |||
454 | mutex_lock(&dev->struct_mutex); | ||
452 | if (file_priv->magic) | 455 | if (file_priv->magic) |
453 | idr_remove(&file_priv->master->magic_map, file_priv->magic); | 456 | idr_remove(&file_priv->master->magic_map, file_priv->magic); |
454 | mutex_unlock(&dev->struct_mutex); | 457 | mutex_unlock(&dev->struct_mutex); |
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index cbb4fc0fc969..5d469b2f26f4 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c | |||
@@ -174,7 +174,7 @@ int drm_clients_info(struct seq_file *m, void *data) | |||
174 | /* dev->filelist is sorted youngest first, but we want to present | 174 | /* dev->filelist is sorted youngest first, but we want to present |
175 | * oldest first (i.e. kernel, servers, clients), so walk backwardss. | 175 | * oldest first (i.e. kernel, servers, clients), so walk backwardss. |
176 | */ | 176 | */ |
177 | mutex_lock(&dev->struct_mutex); | 177 | mutex_lock(&dev->filelist_mutex); |
178 | list_for_each_entry_reverse(priv, &dev->filelist, lhead) { | 178 | list_for_each_entry_reverse(priv, &dev->filelist, lhead) { |
179 | struct task_struct *task; | 179 | struct task_struct *task; |
180 | 180 | ||
@@ -190,7 +190,7 @@ int drm_clients_info(struct seq_file *m, void *data) | |||
190 | priv->magic); | 190 | priv->magic); |
191 | rcu_read_unlock(); | 191 | rcu_read_unlock(); |
192 | } | 192 | } |
193 | mutex_unlock(&dev->struct_mutex); | 193 | mutex_unlock(&dev->filelist_mutex); |
194 | return 0; | 194 | return 0; |
195 | } | 195 | } |
196 | 196 | ||
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 85933940fe9c..c298312f83f6 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -498,6 +498,10 @@ static int i915_gem_object_info(struct seq_file *m, void* data) | |||
498 | 498 | ||
499 | seq_putc(m, '\n'); | 499 | seq_putc(m, '\n'); |
500 | print_batch_pool_stats(m, dev_priv); | 500 | print_batch_pool_stats(m, dev_priv); |
501 | |||
502 | mutex_unlock(&dev->struct_mutex); | ||
503 | |||
504 | mutex_lock(&dev->filelist_mutex); | ||
501 | list_for_each_entry_reverse(file, &dev->filelist, lhead) { | 505 | list_for_each_entry_reverse(file, &dev->filelist, lhead) { |
502 | struct file_stats stats; | 506 | struct file_stats stats; |
503 | struct task_struct *task; | 507 | struct task_struct *task; |
@@ -518,8 +522,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data) | |||
518 | print_file_stats(m, task ? task->comm : "<unknown>", stats); | 522 | print_file_stats(m, task ? task->comm : "<unknown>", stats); |
519 | rcu_read_unlock(); | 523 | rcu_read_unlock(); |
520 | } | 524 | } |
521 | 525 | mutex_unlock(&dev->filelist_mutex); | |
522 | mutex_unlock(&dev->struct_mutex); | ||
523 | 526 | ||
524 | return 0; | 527 | return 0; |
525 | } | 528 | } |
@@ -2325,6 +2328,7 @@ static int i915_ppgtt_info(struct seq_file *m, void *data) | |||
2325 | else if (INTEL_INFO(dev)->gen >= 6) | 2328 | else if (INTEL_INFO(dev)->gen >= 6) |
2326 | gen6_ppgtt_info(m, dev); | 2329 | gen6_ppgtt_info(m, dev); |
2327 | 2330 | ||
2331 | mutex_lock(&dev->filelist_mutex); | ||
2328 | list_for_each_entry_reverse(file, &dev->filelist, lhead) { | 2332 | list_for_each_entry_reverse(file, &dev->filelist, lhead) { |
2329 | struct drm_i915_file_private *file_priv = file->driver_priv; | 2333 | struct drm_i915_file_private *file_priv = file->driver_priv; |
2330 | struct task_struct *task; | 2334 | struct task_struct *task; |
@@ -2339,6 +2343,7 @@ static int i915_ppgtt_info(struct seq_file *m, void *data) | |||
2339 | idr_for_each(&file_priv->context_idr, per_file_ctx, | 2343 | idr_for_each(&file_priv->context_idr, per_file_ctx, |
2340 | (void *)(unsigned long)m); | 2344 | (void *)(unsigned long)m); |
2341 | } | 2345 | } |
2346 | mutex_unlock(&dev->filelist_mutex); | ||
2342 | 2347 | ||
2343 | out_put: | 2348 | out_put: |
2344 | intel_runtime_pm_put(dev_priv); | 2349 | intel_runtime_pm_put(dev_priv); |
@@ -2374,6 +2379,8 @@ static int i915_rps_boost_info(struct seq_file *m, void *data) | |||
2374 | intel_gpu_freq(dev_priv, dev_priv->rps.min_freq_softlimit), | 2379 | intel_gpu_freq(dev_priv, dev_priv->rps.min_freq_softlimit), |
2375 | intel_gpu_freq(dev_priv, dev_priv->rps.max_freq_softlimit), | 2380 | intel_gpu_freq(dev_priv, dev_priv->rps.max_freq_softlimit), |
2376 | intel_gpu_freq(dev_priv, dev_priv->rps.max_freq)); | 2381 | intel_gpu_freq(dev_priv, dev_priv->rps.max_freq)); |
2382 | |||
2383 | mutex_lock(&dev->filelist_mutex); | ||
2377 | spin_lock(&dev_priv->rps.client_lock); | 2384 | spin_lock(&dev_priv->rps.client_lock); |
2378 | list_for_each_entry_reverse(file, &dev->filelist, lhead) { | 2385 | list_for_each_entry_reverse(file, &dev->filelist, lhead) { |
2379 | struct drm_i915_file_private *file_priv = file->driver_priv; | 2386 | struct drm_i915_file_private *file_priv = file->driver_priv; |
@@ -2396,6 +2403,7 @@ static int i915_rps_boost_info(struct seq_file *m, void *data) | |||
2396 | list_empty(&dev_priv->rps.mmioflips.link) ? "" : ", active"); | 2403 | list_empty(&dev_priv->rps.mmioflips.link) ? "" : ", active"); |
2397 | seq_printf(m, "Kernel boosts: %d\n", dev_priv->rps.boosts); | 2404 | seq_printf(m, "Kernel boosts: %d\n", dev_priv->rps.boosts); |
2398 | spin_unlock(&dev_priv->rps.client_lock); | 2405 | spin_unlock(&dev_priv->rps.client_lock); |
2406 | mutex_unlock(&dev->filelist_mutex); | ||
2399 | 2407 | ||
2400 | return 0; | 2408 | return 0; |
2401 | } | 2409 | } |
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 5de4cff05ac9..7901768bb47c 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
@@ -769,6 +769,7 @@ struct drm_device { | |||
769 | atomic_t buf_alloc; /**< Buffer allocation in progress */ | 769 | atomic_t buf_alloc; /**< Buffer allocation in progress */ |
770 | /*@} */ | 770 | /*@} */ |
771 | 771 | ||
772 | struct mutex filelist_mutex; | ||
772 | struct list_head filelist; | 773 | struct list_head filelist; |
773 | 774 | ||
774 | /** \name Memory management */ | 775 | /** \name Memory management */ |