drm: allocate minors early
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / gpu / drm / drm_stub.c
index ac33a74..57fffde 100644 (file)
@@ -260,21 +260,49 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
        return 0;
 }
 
+static struct drm_minor **drm_minor_get_slot(struct drm_device *dev,
+                                            unsigned int type)
+{
+       switch (type) {
+       case DRM_MINOR_LEGACY:
+               return &dev->primary;
+       case DRM_MINOR_RENDER:
+               return &dev->render;
+       case DRM_MINOR_CONTROL:
+               return &dev->control;
+       default:
+               return NULL;
+       }
+}
+
+static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
+{
+       struct drm_minor *minor;
+
+       minor = kzalloc(sizeof(*minor), GFP_KERNEL);
+       if (!minor)
+               return -ENOMEM;
+
+       minor->type = type;
+       minor->dev = dev;
+       INIT_LIST_HEAD(&minor->master_list);
+
+       *drm_minor_get_slot(dev, type) = minor;
+       return 0;
+}
+
 /**
- * drm_get_minor - Allocate and register new DRM minor
+ * drm_get_minor - Register DRM minor
  * @dev: DRM device
- * @minor: Pointer to where new minor is stored
  * @type: Type of minor
  *
- * Allocate a new minor of the given type and register it. A pointer to the new
- * minor is returned in @minor.
+ * Register minor of given type.
  * Caller must hold the global DRM mutex.
  *
  * RETURNS:
  * 0 on success, negative error code on failure.
  */
-static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor,
-                        int type)
+static int drm_get_minor(struct drm_device *dev, unsigned int type)
 {
        struct drm_minor *new_minor;
        int ret;
@@ -282,21 +310,16 @@ static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor,
 
        DRM_DEBUG("\n");
 
+       new_minor = *drm_minor_get_slot(dev, type);
+       if (!new_minor)
+               return 0;
+
        minor_id = drm_minor_get_id(dev, type);
        if (minor_id < 0)
                return minor_id;
 
-       new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL);
-       if (!new_minor) {
-               ret = -ENOMEM;
-               goto err_idr;
-       }
-
-       new_minor->type = type;
        new_minor->device = MKDEV(DRM_MAJOR, minor_id);
-       new_minor->dev = dev;
        new_minor->index = minor_id;
-       INIT_LIST_HEAD(&new_minor->master_list);
 
        idr_replace(&drm_minors_idr, new_minor, minor_id);
 
@@ -314,7 +337,6 @@ static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor,
                       "DRM: Error sysfs_device_add.\n");
                goto err_debugfs;
        }
-       *minor = new_minor;
 
        DRM_DEBUG("new minor assigned %d\n", minor_id);
        return 0;
@@ -325,10 +347,7 @@ err_debugfs:
        drm_debugfs_cleanup(new_minor);
 err_mem:
 #endif
-       kfree(new_minor);
-err_idr:
        idr_remove(&drm_minors_idr, minor_id);
-       *minor = NULL;
        return ret;
 }
 
@@ -491,11 +510,26 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver,
        mutex_init(&dev->struct_mutex);
        mutex_init(&dev->ctxlist_mutex);
 
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+               ret = drm_minor_alloc(dev, DRM_MINOR_CONTROL);
+               if (ret)
+                       goto err_minors;
+       }
+
+       if (drm_core_check_feature(dev, DRIVER_RENDER) && drm_rnodes) {
+               ret = drm_minor_alloc(dev, DRM_MINOR_RENDER);
+               if (ret)
+                       goto err_minors;
+       }
+       ret = drm_minor_alloc(dev, DRM_MINOR_LEGACY);
+       if (ret)
+               goto err_minors;
+
        dev->anon_inode = drm_fs_inode_new();
        if (IS_ERR(dev->anon_inode)) {
                ret = PTR_ERR(dev->anon_inode);
                DRM_ERROR("Cannot allocate anonymous inode: %d\n", ret);
-               goto err_free;
+               goto err_minors;
        }
 
        if (drm_ht_create(&dev->map_hash, 12))
@@ -523,7 +557,10 @@ err_ht:
        drm_ht_remove(&dev->map_hash);
 err_inode:
        drm_fs_inode_free(dev->anon_inode);
-err_free:
+err_minors:
+       drm_put_minor(dev->control);
+       drm_put_minor(dev->render);
+       drm_put_minor(dev->primary);
        kfree(dev);
        return NULL;
 }
@@ -576,26 +613,22 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
 
        mutex_lock(&drm_global_mutex);
 
-       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
-               if (ret)
-                       goto out_unlock;
-       }
+       ret = drm_get_minor(dev, DRM_MINOR_CONTROL);
+       if (ret)
+               goto err_minors;
 
-       if (drm_core_check_feature(dev, DRIVER_RENDER) && drm_rnodes) {
-               ret = drm_get_minor(dev, &dev->render, DRM_MINOR_RENDER);
-               if (ret)
-                       goto err_control_node;
-       }
+       ret = drm_get_minor(dev, DRM_MINOR_RENDER);
+       if (ret)
+               goto err_minors;
 
-       ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY);
+       ret = drm_get_minor(dev, DRM_MINOR_LEGACY);
        if (ret)
-               goto err_render_node;
+               goto err_minors;
 
        if (dev->driver->load) {
                ret = dev->driver->load(dev, flags);
                if (ret)
-                       goto err_primary_node;
+                       goto err_minors;
        }
 
        /* setup grouping for legacy outputs */
@@ -612,12 +645,10 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
 err_unload:
        if (dev->driver->unload)
                dev->driver->unload(dev);
-err_primary_node:
-       drm_unplug_minor(dev->primary);
-err_render_node:
-       drm_unplug_minor(dev->render);
-err_control_node:
+err_minors:
        drm_unplug_minor(dev->control);
+       drm_unplug_minor(dev->render);
+       drm_unplug_minor(dev->primary);
 out_unlock:
        mutex_unlock(&drm_global_mutex);
        return ret;