From 7dced2f33a952ad12aafb7a3e34747156020a3ae Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 15 May 2008 11:21:11 -0700 Subject: [PATCH] [gem] Hold dev->struct_mutex to protect structure data. --- linux-core/drm_gem.c | 26 ++++++++++++++++++++++++++ linux-core/i915_drv.c | 2 +- linux-core/i915_gem.c | 36 ++++++++++++++++++++++++++++++++---- shared-core/i915_drv.h | 6 +++--- 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/linux-core/drm_gem.c b/linux-core/drm_gem.c index ff1a38dc..a8253bc5 100644 --- a/linux-core/drm_gem.c +++ b/linux-core/drm_gem.c @@ -116,6 +116,7 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size) static int drm_gem_handle_delete(struct drm_file *filp, int handle) { + struct drm_device *dev; struct drm_gem_object *obj; /* This is gross. The idr system doesn't let us try a delete and @@ -135,12 +136,15 @@ drm_gem_handle_delete(struct drm_file *filp, int handle) spin_unlock(&filp->table_lock); return -EINVAL; } + dev = obj->dev; /* Release reference and decrement refcount. */ idr_remove(&filp->object_idr, handle); spin_unlock(&filp->table_lock); + mutex_lock(&dev->struct_mutex); drm_gem_object_handle_unreference(obj); + mutex_unlock(&dev->struct_mutex); return 0; } @@ -225,7 +229,9 @@ drm_gem_create_ioctl(struct drm_device *dev, void *data, return -ENOMEM; ret = drm_gem_handle_create(file_priv, obj, &handle); + mutex_lock(&dev->struct_mutex); drm_gem_object_handle_unreference(obj); + mutex_unlock(&dev->struct_mutex); if (ret) return ret; @@ -275,12 +281,14 @@ drm_gem_pread_ioctl(struct drm_device *dev, void *data, if (obj == NULL) return -EINVAL; + mutex_lock(&dev->struct_mutex); if (dev->driver->gem_set_domain) { ret = dev->driver->gem_set_domain(obj, DRM_GEM_DOMAIN_CPU, 0); if (ret) { drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); return ret; } } @@ -290,6 +298,7 @@ drm_gem_pread_ioctl(struct drm_device *dev, void *data, args->size, &offset); if (read != args->size) { drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); if (read < 0) return read; else @@ -297,6 +306,7 @@ drm_gem_pread_ioctl(struct drm_device *dev, void *data, } drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); return 0; } @@ -331,7 +341,9 @@ drm_gem_mmap_ioctl(struct drm_device *dev, void *data, PROT_READ | PROT_WRITE, MAP_SHARED, args->offset); up_write(¤t->mm->mmap_sem); + mutex_lock(&dev->struct_mutex); drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); if (IS_ERR((void *)addr)) return addr; @@ -362,12 +374,14 @@ drm_gem_pwrite_ioctl(struct drm_device *dev, void *data, if (obj == NULL) return -EINVAL; + mutex_lock(&dev->struct_mutex); if (dev->driver->gem_set_domain) { ret = dev->driver->gem_set_domain(obj, DRM_GEM_DOMAIN_CPU, DRM_GEM_DOMAIN_CPU); if (ret) { drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); return ret; } } @@ -379,6 +393,7 @@ drm_gem_pwrite_ioctl(struct drm_device *dev, void *data, if (written != args->size) { drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); if (written < 0) return written; else @@ -391,6 +406,7 @@ drm_gem_pwrite_ioctl(struct drm_device *dev, void *data, args->size); drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); return 0; } @@ -432,7 +448,9 @@ again: goto again; if (ret != 0) { + mutex_lock(&dev->struct_mutex); drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); return ret; } @@ -472,7 +490,9 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data, return -ENOENT; ret = drm_gem_handle_create(file_priv, obj, &handle); + mutex_lock(&dev->struct_mutex); drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); if (ret) return ret; @@ -500,6 +520,7 @@ drm_gem_set_domain_ioctl(struct drm_device *dev, void *data, if (obj == NULL) return -EINVAL; + mutex_lock(&dev->struct_mutex); if (dev->driver->gem_set_domain) { ret = dev->driver->gem_set_domain(obj, args->read_domains, @@ -510,6 +531,7 @@ drm_gem_set_domain_ioctl(struct drm_device *dev, void *data, ret = 0; } drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); return ret; } @@ -546,10 +568,12 @@ drm_gem_object_release_handle(int id, void *ptr, void *data) void drm_gem_release(struct drm_device *dev, struct drm_file *file_private) { + mutex_lock(&dev->struct_mutex); idr_for_each(&file_private->object_idr, &drm_gem_object_release_handle, NULL); idr_destroy(&file_private->object_idr); + mutex_unlock(&dev->struct_mutex); } /** @@ -563,6 +587,8 @@ drm_gem_object_free(struct kref *kref) struct drm_gem_object *obj = (struct drm_gem_object *) kref; struct drm_device *dev = obj->dev; + BUG_ON(!mutex_is_locked(&dev->struct_mutex)); + if (dev->driver->gem_free_object != NULL) dev->driver->gem_free_object(obj); diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index cc47ed64..a50ee53c 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -588,7 +588,7 @@ static struct drm_driver driver = { .ioctls = i915_ioctls, .gem_init_object = i915_gem_init_object, .gem_free_object = i915_gem_free_object, - .gem_set_domain = i915_gem_set_domain_ioctl, + .gem_set_domain = i915_gem_set_domain, .gem_flush_pwrite = i915_gem_flush_pwrite, .fops = { .owner = THIS_MODULE, diff --git a/linux-core/i915_gem.c b/linux-core/i915_gem.c index 00f56013..144667a3 100644 --- a/linux-core/i915_gem.c +++ b/linux-core/i915_gem.c @@ -42,14 +42,20 @@ i915_gem_init_ioctl(struct drm_device *dev, void *data, drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_gem_init *args = data; + mutex_lock(&dev->struct_mutex); + if (args->gtt_start >= args->gtt_end || (args->gtt_start & (PAGE_SIZE - 1)) != 0 || - (args->gtt_end & (PAGE_SIZE - 1)) != 0) + (args->gtt_end & (PAGE_SIZE - 1)) != 0) { + mutex_unlock(&dev->struct_mutex); return -EINVAL; + } drm_memrange_init(&dev_priv->mm.gtt_space, args->gtt_start, args->gtt_end - args->gtt_start); + mutex_unlock(&dev->struct_mutex); + return 0; } @@ -834,6 +840,7 @@ i915_gem_wait_space(struct drm_device *dev) struct drm_i915_gem_object *obj_priv, *last_priv = NULL; int ret = 0; + mutex_lock(&dev->struct_mutex); while (ring->space + 1024 < dev_priv->ring.Size && !list_empty(&dev_priv->mm.active_list)) { obj_priv = list_first_entry(&dev_priv->mm.active_list, @@ -847,6 +854,7 @@ i915_gem_wait_space(struct drm_device *dev) last_priv = obj_priv; i915_kernel_lost_context(dev); } + mutex_unlock(&dev->struct_mutex); return ret; } @@ -897,6 +905,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, goto err; } + mutex_lock(&dev->struct_mutex); /* Look up object handles and perform the relocations */ for (i = 0; i < args->buffer_count; i++) { object_list[i] = drm_gem_object_lookup(dev, file_priv, @@ -1008,6 +1017,8 @@ err: for (i = 0; i < args->buffer_count; i++) drm_gem_object_unreference(object_list[i]); } + mutex_unlock(&dev->struct_mutex); + drm_free(object_list, sizeof(*object_list) * args->buffer_count, DRM_MEM_DRIVER); drm_free(validate_list, sizeof(*validate_list) * args->buffer_count, @@ -1025,10 +1036,13 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, struct drm_i915_gem_object *obj_priv; int ret; + mutex_lock(&dev->struct_mutex); + obj = drm_gem_object_lookup(dev, file_priv, args->handle); if (obj == NULL) { DRM_ERROR("Bad handle in i915_gem_pin_ioctl(): %d\n", args->handle); + mutex_unlock(&dev->struct_mutex); return -EINVAL; } @@ -1041,6 +1055,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, "i915_gem_pin_ioctl(): %d\n", ret); drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); return ret; } } @@ -1048,6 +1063,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, obj_priv->pin_count++; args->offset = obj_priv->gtt_offset; drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); return 0; } @@ -1060,16 +1076,19 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data, struct drm_gem_object *obj; struct drm_i915_gem_object *obj_priv; + mutex_lock(&dev->struct_mutex); obj = drm_gem_object_lookup(dev, file_priv, args->handle); if (obj == NULL) { DRM_ERROR("Bad handle in i915_gem_unpin_ioctl(): %d\n", args->handle); + mutex_unlock(&dev->struct_mutex); return -EINVAL; } obj_priv = obj->driver_private; obj_priv->pin_count--; drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); return 0; } @@ -1095,12 +1114,17 @@ void i915_gem_free_object(struct drm_gem_object *obj) } int -i915_gem_set_domain_ioctl(struct drm_gem_object *obj, - uint32_t read_domains, - uint32_t write_domain) +i915_gem_set_domain(struct drm_gem_object *obj, + uint32_t read_domains, + uint32_t write_domain) { + struct drm_device *dev = obj->dev; + + BUG_ON(!mutex_is_locked(&dev->struct_mutex)); + i915_gem_object_set_domain(obj, read_domains, write_domain); i915_gem_dev_set_domain(obj->dev); + return 0; } @@ -1133,6 +1157,8 @@ i915_gem_lastclose(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; + mutex_lock(&dev->struct_mutex); + /* Assume that the chip has been idled at this point. Just pull them * off the execution list and unref them. Since this is the last * close, this is also the last ref and they'll go away. @@ -1150,4 +1176,6 @@ i915_gem_lastclose(struct drm_device *dev) obj_priv->obj->write_domain = 0; drm_gem_object_unreference(obj_priv->obj); } + + mutex_unlock(&dev->struct_mutex); } diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 51c6bb59..296e1823 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -388,9 +388,9 @@ int i915_gem_unpin_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_init_object(struct drm_gem_object *obj); void i915_gem_free_object(struct drm_gem_object *obj); -int i915_gem_set_domain_ioctl (struct drm_gem_object *obj, - uint32_t read_domains, - uint32_t write_domain); +int i915_gem_set_domain(struct drm_gem_object *obj, + uint32_t read_domains, + uint32_t write_domain); int i915_gem_flush_pwrite(struct drm_gem_object *obj, uint64_t offset, uint64_t size); void i915_gem_lastclose(struct drm_device *dev); -- 2.11.0