drm: Convert idr spinlocks to lockmgr locks
authorFrançois Tigeot <ftigeot@wolfpond.org>
Thu, 5 Dec 2013 12:39:36 +0000 (13:39 +0100)
committerFrançois Tigeot <ftigeot@wolfpond.org>
Thu, 5 Dec 2013 13:53:17 +0000 (14:53 +0100)
* Since the idr code uses blocking calls in some code paths we can't
  hold spin locks accross idr calls

* This commit and the idr infinite loop one fix system freeze issues
  with some Xorg operations involving a huge number of pixmaps

sys/dev/drm/drm_crtc.c
sys/dev/drm/drm_gem.c
sys/dev/drm/include/drm/drmP.h
sys/dev/drm/include/drm/drm_crtc.h

index 6fe63f0..e8483cc 100644 (file)
@@ -228,9 +228,9 @@ again:
                return -ENOMEM;
        }
 
-       spin_lock(&dev->mode_config.idr_mutex);
+       lockmgr(&dev->mode_config.idr_mutex, LK_EXCLUSIVE);
        ret = idr_get_new_above(&dev->mode_config.crtc_idr, obj, 1, &new_id);
-       spin_unlock(&dev->mode_config.idr_mutex);
+       lockmgr(&dev->mode_config.idr_mutex, LK_RELEASE);
        if (ret == -EAGAIN)
                goto again;
        else if (ret)
@@ -254,9 +254,9 @@ again:
 static void drm_mode_object_put(struct drm_device *dev,
                                struct drm_mode_object *object)
 {
-       spin_lock(&dev->mode_config.idr_mutex);
+       lockmgr(&dev->mode_config.idr_mutex, LK_EXCLUSIVE);
        idr_remove(&dev->mode_config.crtc_idr, object->id);
-       spin_unlock(&dev->mode_config.idr_mutex);
+       lockmgr(&dev->mode_config.idr_mutex, LK_RELEASE);
 }
 
 struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
@@ -264,11 +264,11 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
 {
        struct drm_mode_object *obj = NULL;
 
-       spin_lock(&dev->mode_config.idr_mutex);
+       lockmgr(&dev->mode_config.idr_mutex, LK_EXCLUSIVE);
        obj = idr_find(&dev->mode_config.crtc_idr, id);
        if (!obj || (obj->type != type) || (obj->id != id))
                obj = NULL;
-       spin_unlock(&dev->mode_config.idr_mutex);
+       lockmgr(&dev->mode_config.idr_mutex, LK_RELEASE);
 
        return obj;
 }
@@ -894,7 +894,7 @@ int drm_mode_create_dirty_info_property(struct drm_device *dev)
 void drm_mode_config_init(struct drm_device *dev)
 {
        lockinit(&dev->mode_config.mutex, "kmslk", 0, LK_CANRECURSE);
-       spin_init(&dev->mode_config.idr_mutex);
+       lockinit(&dev->mode_config.idr_mutex, "mcfgidr", 0, LK_CANRECURSE);
        INIT_LIST_HEAD(&dev->mode_config.fb_list);
        INIT_LIST_HEAD(&dev->mode_config.crtc_list);
        INIT_LIST_HEAD(&dev->mode_config.connector_list);
index 7fabfda..6f62e49 100644 (file)
@@ -69,7 +69,7 @@ drm_gem_init(struct drm_device *dev)
 {
        struct drm_gem_mm *mm;
 
-       spin_init(&dev->object_name_lock);
+       lockinit(&dev->object_name_lock, "objnam", 0, LK_CANRECURSE);
        idr_init(&dev->object_name_idr);
 
        mm = kmalloc(sizeof(*mm), DRM_MEM_DRIVER, M_WAITOK);
@@ -199,11 +199,11 @@ void drm_gem_object_handle_free(struct drm_gem_object *obj)
        struct drm_device *dev = obj->dev;
 
        /* Remove any name for this object */
-       spin_lock(&dev->object_name_lock);
+       lockmgr(&dev->object_name_lock, LK_EXCLUSIVE);
        if (obj->name) {
                idr_remove(&dev->object_name_idr, obj->name);
                obj->name = 0;
-               spin_unlock(&dev->object_name_lock);
+               lockmgr(&dev->object_name_lock, LK_RELEASE);
                /*
                 * The object name held a reference to this object, drop
                 * that now.
@@ -212,7 +212,7 @@ void drm_gem_object_handle_free(struct drm_gem_object *obj)
                 */
                kref_put(&obj->refcount, drm_gem_object_ref_bug);
        } else
-               spin_unlock(&dev->object_name_lock);
+               lockmgr(&dev->object_name_lock, LK_RELEASE);
 
 }
 
@@ -234,19 +234,19 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle)
         * we may want to use ida for number allocation and a hash table
         * for the pointers, anyway.
         */
-       spin_lock(&filp->table_lock);
+       lockmgr(&filp->table_lock, LK_EXCLUSIVE);
 
        /* Check if we currently have a reference on the object */
        obj = idr_find(&filp->object_idr, handle);
        if (obj == NULL) {
-               spin_unlock(&filp->table_lock);
+               lockmgr(&filp->table_lock, LK_RELEASE);
                return -EINVAL;
        }
        dev = obj->dev;
 
        /* Release reference and decrement refcount. */
        idr_remove(&filp->object_idr, handle);
-       spin_unlock(&filp->table_lock);
+       lockmgr(&filp->table_lock, LK_RELEASE);
 
        if (dev->driver->gem_close_object)
                dev->driver->gem_close_object(obj, filp);
@@ -277,9 +277,9 @@ again:
                return -ENOMEM;
 
        /* do the allocation under our spinlock */
-       spin_lock(&file_priv->table_lock);
+       lockmgr(&file_priv->table_lock, LK_EXCLUSIVE);
        ret = idr_get_new_above(&file_priv->object_idr, obj, 1, (int *)handlep);
-       spin_unlock(&file_priv->table_lock);
+       lockmgr(&file_priv->table_lock, LK_RELEASE);
        if (ret == -EAGAIN)
                goto again;
        else if (ret)
@@ -305,18 +305,18 @@ drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,
 {
        struct drm_gem_object *obj;
 
-       spin_lock(&filp->table_lock);
+       lockmgr(&filp->table_lock, LK_EXCLUSIVE);
 
        /* Check if we currently have a reference on the object */
        obj = idr_find(&filp->object_idr, handle);
        if (obj == NULL) {
-               spin_unlock(&filp->table_lock);
+               lockmgr(&filp->table_lock, LK_RELEASE);
                return NULL;
        }
 
        drm_gem_object_reference(obj);
 
-       spin_unlock(&filp->table_lock);
+       lockmgr(&filp->table_lock, LK_RELEASE);
 
        return obj;
 }
@@ -361,12 +361,12 @@ again:
                goto err;
        }
 
-       spin_lock(&dev->object_name_lock);
+       lockmgr(&dev->object_name_lock, LK_EXCLUSIVE);
        if (!obj->name) {
                ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
                                        &obj->name);
                args->name = (uint64_t) obj->name;
-               spin_unlock(&dev->object_name_lock);
+               lockmgr(&dev->object_name_lock, LK_RELEASE);
 
                if (ret == -EAGAIN)
                        goto again;
@@ -377,7 +377,7 @@ again:
                drm_gem_object_reference(obj);
        } else {
                args->name = (uint64_t) obj->name;
-               spin_unlock(&dev->object_name_lock);
+               lockmgr(&dev->object_name_lock, LK_RELEASE);
                ret = 0;
        }
 
@@ -407,11 +407,11 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data,
        if (!(dev->driver->driver_features & DRIVER_GEM))
                return -ENODEV;
 
-       spin_lock(&dev->object_name_lock);
+       lockmgr(&dev->object_name_lock, LK_EXCLUSIVE);
        obj = idr_find(&dev->object_name_idr, (int) args->name);
        if (obj)
                drm_gem_object_reference(obj);
-       spin_unlock(&dev->object_name_lock);
+       lockmgr(&dev->object_name_lock, LK_RELEASE);
        if (!obj)
                return -ENOENT;
 
@@ -434,7 +434,7 @@ void
 drm_gem_open(struct drm_device *dev, struct drm_file *file_private)
 {
        idr_init(&file_private->object_idr);
-       spin_init(&file_private->table_lock);
+       lockinit(&file_private->table_lock, "fptab", 0, LK_CANRECURSE);
 }
 
 /**
index 5b0f582..e158e3b 100644 (file)
@@ -507,7 +507,7 @@ struct drm_file {
        /** Mapping of mm object handles to object pointers. */
        struct idr object_idr;
        /** Lock for synchronization of access to object_idr. */
-       struct spinlock table_lock;
+       struct lock table_lock;
 
        void             *driver_priv;
 
@@ -1020,7 +1020,7 @@ struct drm_device {
 
        /** \name GEM information */
        /*@{ */
-       struct spinlock object_name_lock;
+       struct lock object_name_lock;
        struct idr object_name_idr;
        /*@} */
        void             *mm_private;
index 0b53352..ce99b9f 100644 (file)
@@ -768,7 +768,7 @@ struct drm_mode_group {
  */
 struct drm_mode_config {
        struct lock mutex; /* protects configuration (mode lists etc.) */
-       struct spinlock idr_mutex; /* for IDR management */
+       struct lock idr_mutex; /* for IDR management */
        struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */
        /* this is limited to one for now */
        int num_fb;