diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index 906771e03103..e1f685015807 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst @@ -3,7 +3,7 @@ Kernel Mode Setting (KMS) ========================= Drivers must initialize the mode setting core by calling -drm_mode_config_init() on the DRM device. The function +drmm_mode_config_init() on the DRM device. The function initializes the :c:type:`struct drm_device ` mode_config field and never fails. Once done, mode configuration must be setup by initializing the following fields. diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index c36687840f4e..158fea71371b 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -98,6 +98,8 @@ static void drm_minor_alloc_release(struct drm_device *dev, void *data) struct drm_minor *minor = data; unsigned long flags; + WARN_ON(dev != minor->dev); + put_device(minor->kdev); spin_lock_irqsave(&drm_minor_lock, flags); @@ -266,8 +268,7 @@ void drm_minor_release(struct drm_minor *minor) * * The following example shows a typical structure of a DRM display driver. * The example focus on the probe() function and the other functions that is - * almost always present and serves as a demonstration of devm_drm_dev_init() - * usage with its accompanying drm_driver->release callback. + * almost always present and serves as a demonstration of devm_drm_dev_init(). * * .. code-block:: c * @@ -277,16 +278,8 @@ void drm_minor_release(struct drm_minor *minor) * struct clk *pclk; * }; * - * static void driver_drm_release(struct drm_device *drm) - * { - * struct driver_device *priv = container_of(...); - * - * drm_mode_config_cleanup(drm); - * } - * * static struct drm_driver driver_drm_driver = { * [...] - * .release = driver_drm_release, * }; * * static int driver_probe(struct platform_device *pdev) @@ -311,7 +304,9 @@ void drm_minor_release(struct drm_minor *minor) * } * drmm_add_final_kfree(drm, priv); * - * drm_mode_config_init(drm); + * ret = drmm_mode_config_init(drm); + * if (ret) + * return ret; * * priv->userspace_facing = drmm_kzalloc(..., GFP_KERNEL); * if (!priv->userspace_facing) @@ -709,8 +704,7 @@ static void devm_drm_dev_init_release(void *data) * @driver: DRM driver * * Managed drm_dev_init(). The DRM device initialized with this function is - * automatically put on driver detach using drm_dev_put(). You must supply a - * &drm_driver.release callback to control the finalization explicitly. + * automatically put on driver detach using drm_dev_put(). * * RETURNS: * 0 on success, or error code on failure. @@ -721,9 +715,6 @@ int devm_drm_dev_init(struct device *parent, { int ret; - if (WARN_ON(!driver->release)) - return -EINVAL; - ret = drm_dev_init(dev, driver, parent); if (ret) return ret; diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index e1ec1bb7068d..5761f838a057 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -373,8 +374,14 @@ static int drm_mode_create_standard_properties(struct drm_device *dev) return 0; } +static void drm_mode_config_init_release(struct drm_device *dev, void *ptr) +{ + drm_mode_config_cleanup(dev); +} + /** - * drm_mode_config_init - initialize DRM mode_configuration structure + * drmm_mode_config_init - managed DRM mode_configuration structure + * initialization * @dev: DRM device * * Initialize @dev's mode_config structure, used for tracking the graphics @@ -384,8 +391,12 @@ static int drm_mode_create_standard_properties(struct drm_device *dev) * problem, since this should happen single threaded at init time. It is the * driver's problem to ensure this guarantee. * + * Cleanup is automatically handled through registering drm_mode_config_cleanup + * with drmm_add_action(). + * + * Returns: 0 on success, negative error value on failure. */ -void drm_mode_config_init(struct drm_device *dev) +int drmm_mode_config_init(struct drm_device *dev) { mutex_init(&dev->mode_config.mutex); drm_modeset_lock_init(&dev->mode_config.connection_mutex); @@ -443,8 +454,11 @@ void drm_mode_config_init(struct drm_device *dev) drm_modeset_acquire_fini(&modeset_ctx); dma_resv_fini(&resv); } + + return drmm_add_action_or_reset(dev, drm_mode_config_init_release, + NULL); } -EXPORT_SYMBOL(drm_mode_config_init); +EXPORT_SYMBOL(drmm_mode_config_init); /** * drm_mode_config_cleanup - free up DRM mode_config info @@ -456,6 +470,9 @@ EXPORT_SYMBOL(drm_mode_config_init); * Note that since this /should/ happen single-threaded at driver/device * teardown time, no locking is required. It's the driver's job to ensure that * this guarantee actually holds true. + * + * FIXME: With the managed drmm_mode_config_init() it is no longer necessary for + * drivers to explicitly call this function. */ void drm_mode_config_cleanup(struct drm_device *dev) { diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index 3bcbe30339f0..6c3ef49b46b3 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -929,7 +929,23 @@ struct drm_mode_config { const struct drm_mode_config_helper_funcs *helper_private; }; -void drm_mode_config_init(struct drm_device *dev); +int __must_check drmm_mode_config_init(struct drm_device *dev); + +/** + * drm_mode_config_init - DRM mode_configuration structure initialization + * @dev: DRM device + * + * This is the unmanaged version of drmm_mode_config_init() for drivers which + * still explicitly call drm_mode_config_cleanup(). + * + * FIXME: This function is deprecated and drivers should be converted over to + * drmm_mode_config_init(). + */ +static inline int drm_mode_config_init(struct drm_device *dev) +{ + return drmm_mode_config_init(dev); +} + void drm_mode_config_reset(struct drm_device *dev); void drm_mode_config_cleanup(struct drm_device *dev);