Commit 1d2ac403 authored by Daniel Vetter's avatar Daniel Vetter

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: default avatarAlex Deucher <alexander.deucher@amd.com>
Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1461691808-12414-9-git-send-email-daniel.vetter@ffwll.ch
parent f47dbdd7
...@@ -93,7 +93,7 @@ void amdgpu_gem_force_release(struct amdgpu_device *adev) ...@@ -93,7 +93,7 @@ void amdgpu_gem_force_release(struct amdgpu_device *adev)
struct drm_device *ddev = adev->ddev; struct drm_device *ddev = adev->ddev;
struct drm_file *file; struct drm_file *file;
mutex_lock(&ddev->struct_mutex); mutex_lock(&ddev->filelist_mutex);
list_for_each_entry(file, &ddev->filelist, lhead) { list_for_each_entry(file, &ddev->filelist, lhead) {
struct drm_gem_object *gobj; struct drm_gem_object *gobj;
...@@ -103,13 +103,13 @@ void amdgpu_gem_force_release(struct amdgpu_device *adev) ...@@ -103,13 +103,13 @@ void amdgpu_gem_force_release(struct amdgpu_device *adev)
spin_lock(&file->table_lock); spin_lock(&file->table_lock);
idr_for_each_entry(&file->object_idr, gobj, handle) { idr_for_each_entry(&file->object_idr, gobj, handle) {
WARN_ONCE(1, "And also active allocations!\n"); WARN_ONCE(1, "And also active allocations!\n");
drm_gem_object_unreference(gobj); drm_gem_object_unreference_unlocked(gobj);
} }
idr_destroy(&file->object_idr); idr_destroy(&file->object_idr);
spin_unlock(&file->table_lock); spin_unlock(&file->table_lock);
} }
mutex_unlock(&ddev->struct_mutex); mutex_unlock(&ddev->filelist_mutex);
} }
/* /*
...@@ -769,7 +769,7 @@ static int amdgpu_debugfs_gem_info(struct seq_file *m, void *data) ...@@ -769,7 +769,7 @@ static int amdgpu_debugfs_gem_info(struct seq_file *m, void *data)
struct drm_file *file; struct drm_file *file;
int r; int r;
r = mutex_lock_interruptible(&dev->struct_mutex); r = mutex_lock_interruptible(&dev->filelist_mutex);
if (r) if (r)
return r; return r;
...@@ -793,7 +793,7 @@ static int amdgpu_debugfs_gem_info(struct seq_file *m, void *data) ...@@ -793,7 +793,7 @@ static int amdgpu_debugfs_gem_info(struct seq_file *m, void *data)
spin_unlock(&file->table_lock); spin_unlock(&file->table_lock);
} }
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->filelist_mutex);
return 0; return 0;
} }
......
...@@ -590,6 +590,7 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver, ...@@ -590,6 +590,7 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver,
spin_lock_init(&dev->buf_lock); spin_lock_init(&dev->buf_lock);
spin_lock_init(&dev->event_lock); spin_lock_init(&dev->event_lock);
mutex_init(&dev->struct_mutex); mutex_init(&dev->struct_mutex);
mutex_init(&dev->filelist_mutex);
mutex_init(&dev->ctxlist_mutex); mutex_init(&dev->ctxlist_mutex);
mutex_init(&dev->master_mutex); mutex_init(&dev->master_mutex);
......
...@@ -297,9 +297,9 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor) ...@@ -297,9 +297,9 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
} }
mutex_unlock(&dev->master_mutex); mutex_unlock(&dev->master_mutex);
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->filelist_mutex);
list_add(&priv->lhead, &dev->filelist); list_add(&priv->lhead, &dev->filelist);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->filelist_mutex);
#ifdef __alpha__ #ifdef __alpha__
/* /*
...@@ -447,8 +447,11 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -447,8 +447,11 @@ int drm_release(struct inode *inode, struct file *filp)
DRM_DEBUG("open_count = %d\n", dev->open_count); DRM_DEBUG("open_count = %d\n", dev->open_count);
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->filelist_mutex);
list_del(&file_priv->lhead); list_del(&file_priv->lhead);
mutex_unlock(&dev->filelist_mutex);
mutex_lock(&dev->struct_mutex);
if (file_priv->magic) if (file_priv->magic)
idr_remove(&file_priv->master->magic_map, file_priv->magic); idr_remove(&file_priv->master->magic_map, file_priv->magic);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
......
...@@ -174,7 +174,7 @@ int drm_clients_info(struct seq_file *m, void *data) ...@@ -174,7 +174,7 @@ int drm_clients_info(struct seq_file *m, void *data)
/* dev->filelist is sorted youngest first, but we want to present /* dev->filelist is sorted youngest first, but we want to present
* oldest first (i.e. kernel, servers, clients), so walk backwardss. * oldest first (i.e. kernel, servers, clients), so walk backwardss.
*/ */
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->filelist_mutex);
list_for_each_entry_reverse(priv, &dev->filelist, lhead) { list_for_each_entry_reverse(priv, &dev->filelist, lhead) {
struct task_struct *task; struct task_struct *task;
...@@ -190,7 +190,7 @@ int drm_clients_info(struct seq_file *m, void *data) ...@@ -190,7 +190,7 @@ int drm_clients_info(struct seq_file *m, void *data)
priv->magic); priv->magic);
rcu_read_unlock(); rcu_read_unlock();
} }
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->filelist_mutex);
return 0; return 0;
} }
......
...@@ -498,6 +498,10 @@ static int i915_gem_object_info(struct seq_file *m, void* data) ...@@ -498,6 +498,10 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
seq_putc(m, '\n'); seq_putc(m, '\n');
print_batch_pool_stats(m, dev_priv); print_batch_pool_stats(m, dev_priv);
mutex_unlock(&dev->struct_mutex);
mutex_lock(&dev->filelist_mutex);
list_for_each_entry_reverse(file, &dev->filelist, lhead) { list_for_each_entry_reverse(file, &dev->filelist, lhead) {
struct file_stats stats; struct file_stats stats;
struct task_struct *task; struct task_struct *task;
...@@ -518,8 +522,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data) ...@@ -518,8 +522,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
print_file_stats(m, task ? task->comm : "<unknown>", stats); print_file_stats(m, task ? task->comm : "<unknown>", stats);
rcu_read_unlock(); rcu_read_unlock();
} }
mutex_unlock(&dev->filelist_mutex);
mutex_unlock(&dev->struct_mutex);
return 0; return 0;
} }
...@@ -2325,6 +2328,7 @@ static int i915_ppgtt_info(struct seq_file *m, void *data) ...@@ -2325,6 +2328,7 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
else if (INTEL_INFO(dev)->gen >= 6) else if (INTEL_INFO(dev)->gen >= 6)
gen6_ppgtt_info(m, dev); gen6_ppgtt_info(m, dev);
mutex_lock(&dev->filelist_mutex);
list_for_each_entry_reverse(file, &dev->filelist, lhead) { list_for_each_entry_reverse(file, &dev->filelist, lhead) {
struct drm_i915_file_private *file_priv = file->driver_priv; struct drm_i915_file_private *file_priv = file->driver_priv;
struct task_struct *task; struct task_struct *task;
...@@ -2339,6 +2343,7 @@ static int i915_ppgtt_info(struct seq_file *m, void *data) ...@@ -2339,6 +2343,7 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
idr_for_each(&file_priv->context_idr, per_file_ctx, idr_for_each(&file_priv->context_idr, per_file_ctx,
(void *)(unsigned long)m); (void *)(unsigned long)m);
} }
mutex_unlock(&dev->filelist_mutex);
out_put: out_put:
intel_runtime_pm_put(dev_priv); intel_runtime_pm_put(dev_priv);
...@@ -2374,6 +2379,8 @@ static int i915_rps_boost_info(struct seq_file *m, void *data) ...@@ -2374,6 +2379,8 @@ static int i915_rps_boost_info(struct seq_file *m, void *data)
intel_gpu_freq(dev_priv, dev_priv->rps.min_freq_softlimit), intel_gpu_freq(dev_priv, dev_priv->rps.min_freq_softlimit),
intel_gpu_freq(dev_priv, dev_priv->rps.max_freq_softlimit), intel_gpu_freq(dev_priv, dev_priv->rps.max_freq_softlimit),
intel_gpu_freq(dev_priv, dev_priv->rps.max_freq)); intel_gpu_freq(dev_priv, dev_priv->rps.max_freq));
mutex_lock(&dev->filelist_mutex);
spin_lock(&dev_priv->rps.client_lock); spin_lock(&dev_priv->rps.client_lock);
list_for_each_entry_reverse(file, &dev->filelist, lhead) { list_for_each_entry_reverse(file, &dev->filelist, lhead) {
struct drm_i915_file_private *file_priv = file->driver_priv; 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,6 +2403,7 @@ static int i915_rps_boost_info(struct seq_file *m, void *data)
list_empty(&dev_priv->rps.mmioflips.link) ? "" : ", active"); list_empty(&dev_priv->rps.mmioflips.link) ? "" : ", active");
seq_printf(m, "Kernel boosts: %d\n", dev_priv->rps.boosts); seq_printf(m, "Kernel boosts: %d\n", dev_priv->rps.boosts);
spin_unlock(&dev_priv->rps.client_lock); spin_unlock(&dev_priv->rps.client_lock);
mutex_unlock(&dev->filelist_mutex);
return 0; return 0;
} }
......
...@@ -769,6 +769,7 @@ struct drm_device { ...@@ -769,6 +769,7 @@ struct drm_device {
atomic_t buf_alloc; /**< Buffer allocation in progress */ atomic_t buf_alloc; /**< Buffer allocation in progress */
/*@} */ /*@} */
struct mutex filelist_mutex;
struct list_head filelist; struct list_head filelist;
/** \name Memory management */ /** \name Memory management */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment