diff options
Diffstat (limited to 'drivers/gpu/drm/drm_drv.c')
| -rw-r--r-- | drivers/gpu/drm/drm_drv.c | 48 |
1 files changed, 35 insertions, 13 deletions
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 985c283cf59f..c808958a2188 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -342,7 +342,9 @@ void drm_minor_release(struct drm_minor *minor) * * platform_set_drvdata(pdev, drm); * - * drm_mode_config_reset(drm); + * ret = drm_mode_config_create_initial_state(drm); + * if (ret) + * return ret; * * ret = drm_dev_register(drm); * if (ret) @@ -473,6 +475,22 @@ void drm_dev_exit(int idx) } EXPORT_SYMBOL(drm_dev_exit); +/* + * Mark the device as unplugged and wait for any in-flight drm_dev_enter() + * critical sections to complete. + */ +static void drm_dev_synchronize_unplug(struct drm_device *dev) +{ + /* + * After synchronizing any critical read section is guaranteed to see + * the new value of ->unplugged, and any critical section which might + * still have seen the old value of ->unplugged is guaranteed to have + * finished. + */ + dev->unplugged = true; + synchronize_srcu(&drm_unplug_srcu); +} + /** * drm_dev_unplug - unplug a DRM device * @dev: DRM device @@ -485,15 +503,7 @@ EXPORT_SYMBOL(drm_dev_exit); */ void drm_dev_unplug(struct drm_device *dev) { - /* - * After synchronizing any critical read section is guaranteed to see - * the new value of ->unplugged, and any critical section which might - * still have seen the old value of ->unplugged is guaranteed to have - * finished. - */ - dev->unplugged = true; - synchronize_srcu(&drm_unplug_srcu); - + drm_dev_synchronize_unplug(dev); drm_dev_unregister(dev); /* Clear all CPU mappings pointing to this device */ @@ -697,6 +707,7 @@ static void drm_dev_init_release(struct drm_device *dev, void *res) mutex_destroy(&dev->master_mutex); mutex_destroy(&dev->clientlist_mutex); mutex_destroy(&dev->filelist_mutex); + mutex_destroy(&dev->gem_lru_mutex); } static int drm_dev_init(struct drm_device *dev, @@ -738,6 +749,7 @@ static int drm_dev_init(struct drm_device *dev, INIT_LIST_HEAD(&dev->vblank_event_list); spin_lock_init(&dev->event_lock); + mutex_init(&dev->gem_lru_mutex); mutex_init(&dev->filelist_mutex); mutex_init(&dev->clientlist_mutex); mutex_init(&dev->master_mutex); @@ -956,17 +968,19 @@ static void drmm_cg_unregister_region(struct drm_device *dev, void *arg) * drmm_cgroup_register_region - Register a region of a DRM device to cgroups * @dev: device for region * @region_name: Region name for registering - * @size: Size of region in bytes + * @init: Initialization parameters for the region. * * This decreases the ref-count of @dev by one. The device is destroyed if the * ref-count drops to zero. */ -struct dmem_cgroup_region *drmm_cgroup_register_region(struct drm_device *dev, const char *region_name, u64 size) +struct dmem_cgroup_region * +drmm_cgroup_register_region(struct drm_device *dev, const char *region_name, + const struct dmem_cgroup_init *init) { struct dmem_cgroup_region *region; int ret; - region = dmem_cgroup_register_region(size, "drm/%s/%s", dev->unique, region_name); + region = dmem_cgroup_register_region(init, "drm/%s/%s", dev->unique, region_name); if (IS_ERR_OR_NULL(region)) return region; @@ -1089,6 +1103,7 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags) goto err_minors; dev->registered = true; + dev->unplugged = false; if (driver->load) { ret = driver->load(dev, flags); @@ -1116,6 +1131,13 @@ err_unload: if (dev->driver->unload) dev->driver->unload(dev); err_minors: + /* + * If a minor was registered before the failure, userspace could have + * opened it and entered a drm_dev_enter() critical section. Ensure all + * such sections complete before we clean up. + */ + drm_dev_synchronize_unplug(dev); + remove_compat_control_link(dev); drm_minor_unregister(dev, DRM_MINOR_ACCEL); drm_minor_unregister(dev, DRM_MINOR_PRIMARY); |
