OSDN Git Service

[gem] Hold dev->struct_mutex to protect structure data.
authorEric Anholt <eric@anholt.net>
Thu, 15 May 2008 18:21:11 +0000 (11:21 -0700)
committerEric Anholt <eric@anholt.net>
Fri, 16 May 2008 01:45:23 +0000 (18:45 -0700)
linux-core/drm_gem.c
linux-core/i915_drv.c
linux-core/i915_gem.c
shared-core/i915_drv.h

index ff1a38d..a8253bc 100644 (file)
@@ -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(&current->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);
 
index cc47ed6..a50ee53 100644 (file)
@@ -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,
index 00f5601..144667a 100644 (file)
@@ -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);
 }
index 51c6bb5..296e182 100644 (file)
@@ -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);