@@ -262,21 +262,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;
@@ -284,21 +312,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);
@@ -316,7 +339,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;
@@ -327,10 +349,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;
}
@@ -569,8 +588,24 @@ 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;
+
if (drm_ht_create(&dev->map_hash, 12))
- goto err_free;
+ goto err_minors;
ret = drm_ctxbitmap_init(dev);
if (ret) {
@@ -592,7 +627,10 @@ err_ctxbitmap:
drm_ctxbitmap_cleanup(dev);
err_ht:
drm_ht_remove(&dev->map_hash);
-err_free:
+err_minors:
+ drm_put_minor(dev->control);
+ drm_put_minor(dev->render);
+ drm_put_minor(dev->primary);
kfree(dev);
return NULL;
}
@@ -668,26 +706,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 */
@@ -704,12 +738,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;