@@ -98,16 +98,14 @@ void amdgpu_gem_force_release(struct amdgpu_device *adev)
list_for_each_entry(file, &ddev->filelist, lhead) {
struct drm_gem_object *gobj;
- int handle;
+ unsigned long handle;
WARN_ONCE(1, "Still active user space clients!\n");
- spin_lock(&file->table_lock);
- idr_for_each_entry(&file->object_idr, gobj, handle) {
+ xa_for_each(&file->objects, handle, gobj) {
WARN_ONCE(1, "And also active allocations!\n");
drm_gem_object_put_unlocked(gobj);
}
- idr_destroy(&file->object_idr);
- spin_unlock(&file->table_lock);
+ xa_destroy(&file->objects);
}
mutex_unlock(&ddev->filelist_mutex);
@@ -784,12 +782,10 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
seq_printf((m), " " #flag); \
}
-static int amdgpu_debugfs_gem_bo_info(int id, void *ptr, void *data)
+static int amdgpu_debugfs_gem_bo_info(unsigned int id,
+ struct drm_gem_object *gobj, struct seq_file *m)
{
- struct drm_gem_object *gobj = ptr;
struct amdgpu_bo *bo = gem_to_amdgpu_bo(gobj);
- struct seq_file *m = data;
-
struct dma_buf_attachment *attachment;
struct dma_buf *dma_buf;
unsigned domain;
@@ -851,6 +847,8 @@ static int amdgpu_debugfs_gem_info(struct seq_file *m, void *data)
list_for_each_entry(file, &dev->filelist, lhead) {
struct task_struct *task;
+ struct drm_gem_object *gobj;
+ unsigned long index;
/*
* Although we have a valid reference on file->pid, that does
@@ -864,9 +862,10 @@ static int amdgpu_debugfs_gem_info(struct seq_file *m, void *data)
task ? task->comm : "<unknown>");
rcu_read_unlock();
- spin_lock(&file->table_lock);
- idr_for_each(&file->object_idr, amdgpu_debugfs_gem_bo_info, m);
- spin_unlock(&file->table_lock);
+ xa_lock(&file->objects);
+ xa_for_each(&file->objects, index, gobj)
+ amdgpu_debugfs_gem_bo_info(index, gobj, m);
+ xa_unlock(&file->objects);
}
mutex_unlock(&dev->filelist_mutex);
@@ -251,10 +251,9 @@ drm_gem_object_handle_put_unlocked(struct drm_gem_object *obj)
* handle references on objects.
*/
static int
-drm_gem_object_release_handle(int id, void *ptr, void *data)
+drm_gem_object_release_handle(struct drm_gem_object *obj,
+ struct drm_file *file_priv)
{
- struct drm_file *file_priv = data;
- struct drm_gem_object *obj = ptr;
struct drm_device *dev = obj->dev;
if (obj->funcs && obj->funcs->close)
@@ -285,23 +284,17 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle)
{
struct drm_gem_object *obj;
- spin_lock(&filp->table_lock);
-
/* Check if we currently have a reference on the object */
- obj = idr_replace(&filp->object_idr, NULL, handle);
- spin_unlock(&filp->table_lock);
- if (IS_ERR_OR_NULL(obj))
- return -EINVAL;
-
- /* Release driver's reference and decrement refcount. */
- drm_gem_object_release_handle(handle, obj, filp);
+ obj = xa_store(&filp->objects, handle, NULL, 0);
+ if (obj) {
+ /* Release driver's reference and decrement refcount. */
+ drm_gem_object_release_handle(obj, filp);
+ }
/* And finally make the handle available for future allocations. */
- spin_lock(&filp->table_lock);
- idr_remove(&filp->object_idr, handle);
- spin_unlock(&filp->table_lock);
+ xa_erase(&filp->objects, handle);
- return 0;
+ return obj ? 0 : -EINVAL;
}
EXPORT_SYMBOL(drm_gem_handle_delete);
@@ -390,24 +383,14 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,
if (obj->handle_count++ == 0)
drm_gem_object_get(obj);
- /*
- * Get the user-visible handle using idr. Preload and perform
- * allocation under our spinlock.
- */
- idr_preload(GFP_KERNEL);
- spin_lock(&file_priv->table_lock);
-
- ret = idr_alloc(&file_priv->object_idr, obj, 1, 0, GFP_NOWAIT);
-
- spin_unlock(&file_priv->table_lock);
- idr_preload_end();
-
+ /* Get the user-visible handle */
+ ret = xa_alloc(&file_priv->objects, &handle, obj, xa_limit_31b,
+ GFP_KERNEL);
mutex_unlock(&dev->object_name_lock);
+
if (ret < 0)
goto err_unref;
- handle = ret;
-
ret = drm_vma_node_allow(&obj->vma_node, file_priv);
if (ret)
goto err_remove;
@@ -428,9 +411,7 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,
err_revoke:
drm_vma_node_revoke(&obj->vma_node, file_priv);
err_remove:
- spin_lock(&file_priv->table_lock);
- idr_remove(&file_priv->object_idr, handle);
- spin_unlock(&file_priv->table_lock);
+ xa_erase(&file_priv->objects, handle);
err_unref:
drm_gem_object_handle_put_unlocked(obj);
return ret;
@@ -644,14 +625,12 @@ drm_gem_object_lookup(struct drm_file *filp, u32 handle)
{
struct drm_gem_object *obj;
- spin_lock(&filp->table_lock);
-
+ xa_lock(&filp->objects);
/* Check if we currently have a reference on the object */
- obj = idr_find(&filp->object_idr, handle);
+ obj = xa_load(&filp->objects, handle);
if (obj)
drm_gem_object_get(obj);
-
- spin_unlock(&filp->table_lock);
+ xa_unlock(&filp->objects);
return obj;
}
@@ -784,8 +763,7 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data,
void
drm_gem_open(struct drm_device *dev, struct drm_file *file_private)
{
- idr_init_base(&file_private->object_idr, 1);
- spin_lock_init(&file_private->table_lock);
+ xa_init_flags(&file_private->objects, XA_FLAGS_ALLOC1);
}
/**
@@ -800,9 +778,12 @@ drm_gem_open(struct drm_device *dev, struct drm_file *file_private)
void
drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
{
- idr_for_each(&file_private->object_idr,
- &drm_gem_object_release_handle, file_private);
- idr_destroy(&file_private->object_idr);
+ unsigned long index;
+ struct drm_gem_object *obj;
+
+ xa_for_each(&file_private->objects, index, obj)
+ drm_gem_object_release_handle(obj, file_private);
+ xa_destroy(&file_private->objects);
}
/**
@@ -65,7 +65,7 @@ static int submit_lookup_objects(struct etnaviv_gem_submit *submit,
unsigned i;
int ret = 0;
- spin_lock(&file->table_lock);
+ xa_lock(&file->objects);
for (i = 0, bo = submit_bos; i < nr_bos; i++, bo++) {
struct drm_gem_object *obj;
@@ -79,9 +79,9 @@ static int submit_lookup_objects(struct etnaviv_gem_submit *submit,
submit->bos[i].flags = bo->flags;
/* normally use drm_gem_object_lookup(), but for bulk lookup
- * all under single table_lock just hit object_idr directly:
+ * all under the lock just hit objects directly:
*/
- obj = idr_find(&file->object_idr, bo->handle);
+ obj = xa_load(&file->objects, bo->handle);
if (!obj) {
DRM_ERROR("invalid handle %u at index %u\n",
bo->handle, i);
@@ -90,8 +90,8 @@ static int submit_lookup_objects(struct etnaviv_gem_submit *submit,
}
/*
- * Take a refcount on the object. The file table lock
- * prevents the object_idr's refcount on this being dropped.
+ * Take a refcount on the object. The lock
+ * prevents the objects' refcount on this being dropped.
*/
drm_gem_object_get(obj);
@@ -100,7 +100,7 @@ static int submit_lookup_objects(struct etnaviv_gem_submit *submit,
out_unlock:
submit->nr_bos = i;
- spin_unlock(&file->table_lock);
+ xa_unlock(&file->objects);
return ret;
}
@@ -304,10 +304,9 @@ struct file_stats {
u64 active, inactive;
};
-static int per_file_stats(int id, void *ptr, void *data)
+static
+int per_file_stats(struct drm_i915_gem_object *obj, struct file_stats *stats)
{
- struct drm_i915_gem_object *obj = ptr;
- struct file_stats *stats = data;
struct i915_vma *vma;
lockdep_assert_held(&obj->base.dev->struct_mutex);
@@ -370,7 +369,7 @@ static void print_batch_pool_stats(struct seq_file *m,
list_for_each_entry(obj,
&engine->batch_pool.cache_list[j],
batch_pool_link)
- per_file_stats(0, obj, &stats);
+ per_file_stats(obj, &stats);
}
}
@@ -387,9 +386,9 @@ static int per_file_ctx_stats(int idx, void *ptr, void *data)
struct intel_context *ce = to_intel_context(ctx, engine);
if (ce->state)
- per_file_stats(0, ce->state->obj, data);
+ per_file_stats(ce->state->obj, data);
if (ce->ring)
- per_file_stats(0, ce->ring->vma->obj, data);
+ per_file_stats(ce->ring->vma->obj, data);
}
return 0;
@@ -521,17 +520,20 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
print_context_stats(m, dev_priv);
list_for_each_entry_reverse(file, &dev->filelist, lhead) {
struct file_stats stats;
+ struct drm_i915_gem_object *obj;
struct drm_i915_file_private *file_priv = file->driver_priv;
struct i915_request *request;
struct task_struct *task;
+ unsigned long index;
mutex_lock(&dev->struct_mutex);
memset(&stats, 0, sizeof(stats));
stats.file_priv = file->driver_priv;
- spin_lock(&file->table_lock);
- idr_for_each(&file->object_idr, per_file_stats, &stats);
- spin_unlock(&file->table_lock);
+ xa_lock(&file->objects);
+ xa_for_each(&file->objects, index, obj)
+ per_file_stats(obj, &stats);
+ xa_unlock(&file->objects);
/*
* Although we have a valid reference on file->pid, that does
* not guarantee that the task_struct who called get_pid() is
@@ -310,7 +310,7 @@ i915_gem_object_lookup_rcu(struct drm_file *file, u32 handle)
#ifdef CONFIG_LOCKDEP
WARN_ON(debug_locks && !lock_is_held(&rcu_lock_map));
#endif
- return idr_find(&file->object_idr, handle);
+ return xa_load(&file->objects, handle);
}
static inline struct drm_i915_gem_object *
@@ -492,14 +492,15 @@ static int cpu_check(struct drm_i915_gem_object *obj, unsigned int max)
static int file_add_object(struct drm_file *file,
struct drm_i915_gem_object *obj)
{
- int err;
+ int err, id;
GEM_BUG_ON(obj->base.handle_count);
/* tie the object to the drm_file for easy reaping */
- err = idr_alloc(&file->object_idr, &obj->base, 1, 0, GFP_KERNEL);
+ err = xa_alloc(&file->objects, &id, &obj->base, xa_limit_32b,
+ GFP_KERNEL);
if (err < 0)
- return err;
+ return err;
i915_gem_object_get(obj);
obj->base.handle_count++;
@@ -88,7 +88,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
unsigned i;
int ret = 0;
- spin_lock(&file->table_lock);
+ xa_lock(&file->objects);
pagefault_disable();
for (i = 0; i < args->nr_bos; i++) {
@@ -105,12 +105,12 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
if (copy_from_user_inatomic(&submit_bo, userptr, sizeof(submit_bo))) {
pagefault_enable();
- spin_unlock(&file->table_lock);
+ xa_unlock(&file->objects);
if (copy_from_user(&submit_bo, userptr, sizeof(submit_bo))) {
ret = -EFAULT;
goto out;
}
- spin_lock(&file->table_lock);
+ xa_lock(&file->objects);
pagefault_disable();
}
@@ -129,9 +129,9 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
submit->bos[i].iova = submit_bo.presumed;
/* normally use drm_gem_object_lookup(), but for bulk lookup
- * all under single table_lock just hit object_idr directly:
+ * all under single lock just hit objects directly:
*/
- obj = idr_find(&file->object_idr, submit_bo.handle);
+ obj = xa_load(&file->objects, submit_bo.handle);
if (!obj) {
DRM_ERROR("invalid handle %u at index %u\n", submit_bo.handle, i);
ret = -EINVAL;
@@ -156,7 +156,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
out_unlock:
pagefault_enable();
- spin_unlock(&file->table_lock);
+ xa_unlock(&file->objects);
out:
submit->nr_bos = i;
@@ -362,21 +362,21 @@ v3d_cl_lookup_bos(struct drm_device *dev,
goto fail;
}
- spin_lock(&file_priv->table_lock);
+ xa_lock(&file_priv->objects);
for (i = 0; i < exec->bo_count; i++) {
- struct drm_gem_object *bo = idr_find(&file_priv->object_idr,
+ struct drm_gem_object *bo = xa_load(&file_priv->objects,
handles[i]);
if (!bo) {
DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
i, handles[i]);
ret = -ENOENT;
- spin_unlock(&file_priv->table_lock);
+ xa_unlock(&file_priv->objects);
goto fail;
}
drm_gem_object_get(bo);
exec->bo[i] = to_v3d_bo(bo);
}
- spin_unlock(&file_priv->table_lock);
+ xa_unlock(&file_priv->objects);
fail:
kvfree(handles);
@@ -671,26 +671,25 @@ v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
job->args = *args;
job->v3d = v3d;
- spin_lock(&file_priv->table_lock);
+ xa_lock(&file_priv->objects);
for (bo_count = 0; bo_count < ARRAY_SIZE(job->bo); bo_count++) {
struct drm_gem_object *bo;
if (!args->bo_handles[bo_count])
break;
- bo = idr_find(&file_priv->object_idr,
- args->bo_handles[bo_count]);
+ bo = xa_load(&file_priv->objects, args->bo_handles[bo_count]);
if (!bo) {
DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
bo_count, args->bo_handles[bo_count]);
ret = -ENOENT;
- spin_unlock(&file_priv->table_lock);
+ xa_unlock(&file_priv->objects);
goto fail;
}
drm_gem_object_get(bo);
job->bo[bo_count] = to_v3d_bo(bo);
}
- spin_unlock(&file_priv->table_lock);
+ xa_unlock(&file_priv->objects);
ret = v3d_lock_bo_reservations(job->bo, bo_count, &acquire_ctx);
if (ret)
@@ -759,9 +759,9 @@ vc4_cl_lookup_bos(struct drm_device *dev,
goto fail;
}
- spin_lock(&file_priv->table_lock);
+ xa_lock(&file_priv->objects);
for (i = 0; i < exec->bo_count; i++) {
- struct drm_gem_object *bo = idr_find(&file_priv->object_idr,
+ struct drm_gem_object *bo = xa_load(&file_priv->objects,
handles[i]);
if (!bo) {
DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
@@ -773,7 +773,7 @@ vc4_cl_lookup_bos(struct drm_device *dev,
drm_gem_object_get(bo);
exec->bo[i] = (struct drm_gem_cma_object *)bo;
}
- spin_unlock(&file_priv->table_lock);
+ xa_unlock(&file_priv->objects);
if (ret)
goto fail_put_bo;
@@ -240,15 +240,12 @@ struct drm_file {
struct drm_minor *minor;
/**
- * @object_idr:
+ * @objects:
*
* Mapping of mm object handles to object pointers. Used by the GEM
- * subsystem. Protected by @table_lock.
+ * subsystem.
*/
- struct idr object_idr;
-
- /** @table_lock: Protects @object_idr. */
- spinlock_t table_lock;
+ struct xarray objects;
/** @syncobj_idr: Mapping of sync object handles to object pointers. */
struct idr syncobj_idr;
Signed-off-by: Matthew Wilcox <willy@infradead.org> --- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 23 +++---- drivers/gpu/drm/drm_gem.c | 67 +++++++------------ drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 12 ++-- drivers/gpu/drm/i915/i915_debugfs.c | 20 +++--- drivers/gpu/drm/i915/i915_gem_object.h | 2 +- .../gpu/drm/i915/selftests/i915_gem_context.c | 7 +- drivers/gpu/drm/msm/msm_gem_submit.c | 12 ++-- drivers/gpu/drm/v3d/v3d_gem.c | 17 +++-- drivers/gpu/drm/vc4/vc4_gem.c | 6 +- include/drm/drm_file.h | 9 +-- 10 files changed, 77 insertions(+), 98 deletions(-)