Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+5 −5
Original line number Original line Diff line number Diff line
@@ -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)
		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)
	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)
		spin_unlock(&file->table_lock);
		spin_unlock(&file->table_lock);
	}
	}


	mutex_unlock(&dev->struct_mutex);
	mutex_unlock(&dev->filelist_mutex);
	return 0;
	return 0;
}
}


+1 −0
Original line number Original line Diff line number Diff line
@@ -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);


+6 −3
Original line number Original line Diff line number Diff line
@@ -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)


	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);
+2 −2
Original line number Original line Diff line number Diff line
@@ -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)
			   priv->magic);
			   priv->magic);
		rcu_read_unlock();
		rcu_read_unlock();
	}
	}
	mutex_unlock(&dev->struct_mutex);
	mutex_unlock(&dev->filelist_mutex);
	return 0;
	return 0;
}
}


+10 −2
Original line number Original line Diff line number Diff line
@@ -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)
		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)
	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)
		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)
		   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)
		   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;
}
}
Loading