diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 269048215e8260173b532892ad5d13b10382a9a2..b595b64291a2a8b38212aa4401457592e2307c4e 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -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 @@ static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, drm_debugfs_cleanup(new_minor); err_mem: #endif - kfree(new_minor); -err_idr: idr_remove(&drm_minors_idr, minor_id); - *minor = NULL; return ret; } @@ -495,8 +514,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) { @@ -518,7 +553,10 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver, 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; } @@ -594,26 +632,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 */ @@ -630,12 +664,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;