[PATCH 4/5] drm/imx: drop deprecated load/unload drm_driver ops

Ying Liu gnuiyl at gmail.com
Fri Jun 24 07:46:55 UTC 2016


On Fri, Jun 17, 2016 at 8:48 PM, Daniel Vetter <daniel at ffwll.ch> wrote:
> On Fri, Jun 17, 2016 at 12:13:41PM +0200, Lucas Stach wrote:
>> Drop the load/unload driver ops, as they are deprecated because of their
>> inherent races, with devices being visible to userspace before they are
>> fully initialized.
>>
>> Move this code into the driver bind/unbind routines bracketed by the
>> proper drm_dev_alloc/register and drm_dev_unregister/unref calls.
>>
>> Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
>> ---
>>  drivers/gpu/drm/imx/imx-drm-core.c | 247 ++++++++++++++++++-------------------
>>  1 file changed, 121 insertions(+), 126 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
>> index c63378661e11..799a68976590 100644
>> --- a/drivers/gpu/drm/imx/imx-drm-core.c
>> +++ b/drivers/gpu/drm/imx/imx-drm-core.c
>> @@ -78,25 +78,6 @@ static void imx_drm_driver_lastclose(struct drm_device *drm)
>>       }
>>  }
>>
>> -static int imx_drm_driver_unload(struct drm_device *drm)
>> -{
>> -     struct imx_drm_device *imxdrm = drm->dev_private;
>> -
>> -     drm_kms_helper_poll_fini(drm);
>> -
>> -     if (imxdrm->fbhelper)
>> -             drm_fbdev_cma_fini(imxdrm->fbhelper);
>> -
>> -     component_unbind_all(drm->dev, drm);
>> -
>> -     drm_vblank_cleanup(drm);
>> -     drm_mode_config_cleanup(drm);
>> -
>> -     platform_set_drvdata(drm->platformdev, NULL);
>> -
>> -     return 0;
>> -}
>> -
>>  static struct imx_drm_crtc *imx_drm_find_crtc(struct drm_crtc *crtc)
>>  {
>>       struct imx_drm_device *imxdrm = crtc->dev->dev_private;
>> @@ -223,109 +204,6 @@ static const struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
>>  };
>>
>>  /*
>> - * Main DRM initialisation. This binds, initialises and registers
>> - * with DRM the subcomponents of the driver.
>> - */
>> -static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
>> -{
>> -     struct imx_drm_device *imxdrm;
>> -     struct drm_connector *connector;
>> -     int ret;
>> -
>> -     imxdrm = devm_kzalloc(drm->dev, sizeof(*imxdrm), GFP_KERNEL);
>> -     if (!imxdrm)
>> -             return -ENOMEM;
>> -
>> -     imxdrm->drm = drm;
>> -
>> -     drm->dev_private = imxdrm;
>> -
>> -     /*
>> -      * enable drm irq mode.
>> -      * - with irq_enabled = true, we can use the vblank feature.
>> -      *
>> -      * P.S. note that we wouldn't use drm irq handler but
>> -      *      just specific driver own one instead because
>> -      *      drm framework supports only one irq handler and
>> -      *      drivers can well take care of their interrupts
>> -      */
>> -     drm->irq_enabled = true;
>> -
>> -     /*
>> -      * set max width and height as default value(4096x4096).
>> -      * this value would be used to check framebuffer size limitation
>> -      * at drm_mode_addfb().
>> -      */
>> -     drm->mode_config.min_width = 64;
>> -     drm->mode_config.min_height = 64;
>> -     drm->mode_config.max_width = 4096;
>> -     drm->mode_config.max_height = 4096;
>> -     drm->mode_config.funcs = &imx_drm_mode_config_funcs;
>> -
>> -     drm_mode_config_init(drm);
>> -
>> -     ret = drm_vblank_init(drm, MAX_CRTC);
>> -     if (ret)
>> -             goto err_kms;
>> -
>> -     platform_set_drvdata(drm->platformdev, drm);
>> -
>> -     /* Now try and bind all our sub-components */
>> -     ret = component_bind_all(drm->dev, drm);
>> -     if (ret)
>> -             goto err_vblank;
>> -
>> -     /*
>> -      * All components are now added, we can publish the connector sysfs
>> -      * entries to userspace.  This will generate hotplug events and so
>> -      * userspace will expect to be able to access DRM at this point.
>> -      */
>> -     list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
>> -             ret = drm_connector_register(connector);
>> -             if (ret) {
>> -                     dev_err(drm->dev,
>> -                             "[CONNECTOR:%d:%s] drm_connector_register failed: %d\n",
>> -                             connector->base.id,
>> -                             connector->name, ret);
>> -                     goto err_unbind;
>> -             }
>> -     }
>> -
>> -     /*
>> -      * All components are now initialised, so setup the fb helper.
>> -      * The fb helper takes copies of key hardware information, so the
>> -      * crtcs/connectors/encoders must not change after this point.
>> -      */
>> -#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION)
>> -     if (legacyfb_depth != 16 && legacyfb_depth != 32) {
>> -             dev_warn(drm->dev, "Invalid legacyfb_depth.  Defaulting to 16bpp\n");
>> -             legacyfb_depth = 16;
>> -     }
>> -     drm_helper_disable_unused_functions(drm);
>> -     imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth,
>> -                             drm->mode_config.num_crtc, MAX_CRTC);
>> -     if (IS_ERR(imxdrm->fbhelper)) {
>> -             ret = PTR_ERR(imxdrm->fbhelper);
>> -             imxdrm->fbhelper = NULL;
>> -             goto err_unbind;
>> -     }
>> -#endif
>> -
>> -     drm_kms_helper_poll_init(drm);
>> -
>> -     return 0;
>> -
>> -err_unbind:
>> -     component_unbind_all(drm->dev, drm);
>> -err_vblank:
>> -     drm_vblank_cleanup(drm);
>> -err_kms:
>> -     drm_mode_config_cleanup(drm);
>> -
>> -     return ret;
>> -}
>> -
>> -/*
>>   * imx_drm_add_crtc - add a new crtc
>>   */
>>  int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
>> @@ -416,8 +294,6 @@ static const struct drm_ioctl_desc imx_drm_ioctls[] = {
>>
>>  static struct drm_driver imx_drm_driver = {
>>       .driver_features        = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
>> -     .load                   = imx_drm_driver_load,
>> -     .unload                 = imx_drm_driver_unload,
>>       .lastclose              = imx_drm_driver_lastclose,
>>       .set_busid              = drm_platform_set_busid,
>>       .gem_free_object_unlocked = drm_gem_cma_free_object,
>> @@ -471,12 +347,131 @@ static int compare_of(struct device *dev, void *data)
>>
>>  static int imx_drm_bind(struct device *dev)
>>  {
>> -     return drm_platform_init(&imx_drm_driver, to_platform_device(dev));
>> +     struct drm_device *drm;
>> +     struct imx_drm_device *imxdrm;
>> +     int ret;
>> +
>> +     drm = drm_dev_alloc(&imx_drm_driver, dev);
>> +     if (!drm)
>> +             return -ENOMEM;
>> +
>> +     imxdrm = devm_kzalloc(dev, sizeof(*imxdrm), GFP_KERNEL);
>> +     if (!imxdrm) {
>> +             ret = -ENOMEM;
>> +             goto err_unref;
>> +     }
>> +
>> +     imxdrm->drm = drm;
>> +     drm->dev_private = imxdrm;
>> +
>> +     /*
>> +      * enable drm irq mode.
>> +      * - with irq_enabled = true, we can use the vblank feature.
>> +      *
>> +      * P.S. note that we wouldn't use drm irq handler but
>> +      *      just specific driver own one instead because
>> +      *      drm framework supports only one irq handler and
>> +      *      drivers can well take care of their interrupts
>> +      */
>> +     drm->irq_enabled = true;
>> +
>> +     /*
>> +      * set max width and height as default value(4096x4096).
>> +      * this value would be used to check framebuffer size limitation
>> +      * at drm_mode_addfb().
>> +      */
>> +     drm->mode_config.min_width = 64;
>> +     drm->mode_config.min_height = 64;
>> +     drm->mode_config.max_width = 4096;
>> +     drm->mode_config.max_height = 4096;
>> +     drm->mode_config.funcs = &imx_drm_mode_config_funcs;
>> +
>> +     drm_mode_config_init(drm);
>> +
>> +     ret = drm_vblank_init(drm, MAX_CRTC);
>> +     if (ret)
>> +             goto err_kms;
>> +
>> +     dev_set_drvdata(dev, drm);
>> +
>> +     /* Now try and bind all our sub-components */
>> +     ret = component_bind_all(dev, drm);
>> +     if (ret)
>> +             goto err_vblank;
>> +
>> +     ret = drm_dev_register(drm, 0);
>
> In principle this should be the last step in the init sequence, otherwise
> you might have userspace fighting with your init code over the hw. Please
> move down.
>
>> +     if (ret)
>> +             goto err_unbind;
>> +
>> +     /*
>> +      * All components are now added, we can publish the connector sysfs
>> +      * entries to userspace.  This will generate hotplug events and so
>> +      * userspace will expect to be able to access DRM at this point.
>> +      */
>> +     ret = drm_connector_register_all(drm);
>
> This (and connector_unregister_all) just became unecessary with the
> patches from Chris that I merged into drm-misc today. Please remove.
>
>> +     if (ret)
>> +             goto err_unregister;
>> +
>> +     /*
>> +      * All components are now initialised, so setup the fb helper.
>> +      * The fb helper takes copies of key hardware information, so the
>> +      * crtcs/connectors/encoders must not change after this point.
>> +      */
>> +#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION)
>> +     if (legacyfb_depth != 16 && legacyfb_depth != 32) {
>> +             dev_warn(dev, "Invalid legacyfb_depth.  Defaulting to 16bpp\n");
>> +             legacyfb_depth = 16;
>> +     }
>> +     drm_helper_disable_unused_functions(drm);
>
> fyi, you need to nuke this when switching to atomic.

I've got this done in my imx-drm atomic conversion v2 patch set.

Regards,
Liu Ying

>
>> +     imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth,
>> +                             drm->mode_config.num_crtc, MAX_CRTC);
>> +     if (IS_ERR(imxdrm->fbhelper)) {
>> +             ret = PTR_ERR(imxdrm->fbhelper);
>> +             imxdrm->fbhelper = NULL;
>> +             goto err_unregister;
>> +     }
>> +#endif
>> +
>> +     drm_kms_helper_poll_init(drm);
>> +
>> +     return 0;
>> +
>> +err_unregister:
>> +     drm_dev_unregister(drm);
>> +err_unbind:
>> +     component_unbind_all(drm->dev, drm);
>> +err_vblank:
>> +     drm_vblank_cleanup(drm);
>> +err_kms:
>> +     drm_mode_config_cleanup(drm);
>> +err_unref:
>> +     drm_dev_unref(drm);
>> +
>> +     return ret;
>>  }
>>
>>  static void imx_drm_unbind(struct device *dev)
>>  {
>> -     drm_put_dev(dev_get_drvdata(dev));
>> +     struct drm_device *drm = dev_get_drvdata(dev);
>> +     struct imx_drm_device *imxdrm = drm->dev_private;
>> +     struct drm_fbdev_cma *fbhelper = imxdrm->fbhelper;
>> +
>> +     drm_kms_helper_poll_fini(drm);
>> +     /* device is going down, so no need to restore fbdev modes */
>> +     imxdrm->fbhelper = NULL;
>> +
>> +     drm_connector_unregister_all(drm);
>> +     drm_dev_unregister(drm);
>
> Same here: unregister should be first, connector_unregister_all isn't
> needed any more.
> -Daniel
>
>> +
>> +     if (fbhelper)
>> +             drm_fbdev_cma_fini(fbhelper);
>> +
>> +     component_unbind_all(drm->dev, drm);
>> +     dev_set_drvdata(dev, NULL);
>> +
>> +     drm_mode_config_cleanup(drm);
>> +
>> +     drm_dev_unref(drm);
>>  }
>>
>>  static const struct component_master_ops imx_drm_ops = {
>> --
>> 2.8.1
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel at lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel


More information about the dri-devel mailing list