[PATCH 01/42] drm/omap: fix suspend/resume handling
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Mon Mar 7 07:52:39 UTC 2016
Hi Tomi,
Thank you for the patch.
On Monday 22 February 2016 19:10:07 Tomi Valkeinen wrote:
> For legacy reasons omapdss handles system suspend/resume via PM notifier
> callback, where the driver disables/resumes all the outputs.
>
> This doesn't work well with omapdrm. What happens on suspend is that the
> omapdss disables the displays while omapdrm is still happily continuing
> its work, possibly waiting for an vsync irq, which will never come if
> the display output is disabled, leading to timeouts and errors sent to
> userspace.
>
> This patch moves the suspend/resume handling to omapdrm, and the
> suspend/resume is now done safely inside modeset lock.
>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen at ti.com>
> ---
> drivers/gpu/drm/omapdrm/dss/core.c | 29 -----------------------
> drivers/gpu/drm/omapdrm/dss/display.c | 36 ----------------------------
> drivers/gpu/drm/omapdrm/dss/dss.h | 2 --
> drivers/gpu/drm/omapdrm/omap_drv.c | 44 ++++++++++++++++++++++++++++++++
> 4 files changed, 44 insertions(+), 67 deletions(-)
>
> diff --git a/drivers/gpu/drm/omapdrm/dss/core.c
> b/drivers/gpu/drm/omapdrm/dss/core.c index 54eeb507f9b3..1f55d0aae03d
> 100644
> --- a/drivers/gpu/drm/omapdrm/dss/core.c
> +++ b/drivers/gpu/drm/omapdrm/dss/core.c
> @@ -165,31 +165,6 @@ int dss_debugfs_create_file(const char *name, void
> (*write)(struct seq_file *)) #endif /* CONFIG_OMAP2_DSS_DEBUGFS */
>
> /* PLATFORM DEVICE */
> -static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v,
> void *d) -{
> - DSSDBG("pm notif %lu\n", v);
> -
> - switch (v) {
> - case PM_SUSPEND_PREPARE:
> - case PM_HIBERNATION_PREPARE:
> - case PM_RESTORE_PREPARE:
> - DSSDBG("suspending displays\n");
> - return dss_suspend_all_devices();
> -
> - case PM_POST_SUSPEND:
> - case PM_POST_HIBERNATION:
> - case PM_POST_RESTORE:
> - DSSDBG("resuming displays\n");
> - return dss_resume_all_devices();
> -
> - default:
> - return 0;
> - }
> -}
> -
> -static struct notifier_block omap_dss_pm_notif_block = {
> - .notifier_call = omap_dss_pm_notif,
> -};
>
> static int __init omap_dss_probe(struct platform_device *pdev)
> {
> @@ -211,8 +186,6 @@ static int __init omap_dss_probe(struct platform_device
> *pdev) else if (pdata->default_device)
> core.default_display_name = pdata->default_device->name;
>
> - register_pm_notifier(&omap_dss_pm_notif_block);
> -
> return 0;
>
> err_debugfs:
> @@ -222,8 +195,6 @@ err_debugfs:
>
> static int omap_dss_remove(struct platform_device *pdev)
> {
> - unregister_pm_notifier(&omap_dss_pm_notif_block);
> -
> dss_uninitialize_debugfs();
>
> return 0;
> diff --git a/drivers/gpu/drm/omapdrm/dss/display.c
> b/drivers/gpu/drm/omapdrm/dss/display.c index ef5b9027985d..24c2bffa0036
> 100644
> --- a/drivers/gpu/drm/omapdrm/dss/display.c
> +++ b/drivers/gpu/drm/omapdrm/dss/display.c
> @@ -78,42 +78,6 @@ void omapdss_default_get_timings(struct omap_dss_device
> *dssdev, }
> EXPORT_SYMBOL(omapdss_default_get_timings);
>
> -int dss_suspend_all_devices(void)
> -{
> - struct omap_dss_device *dssdev = NULL;
> -
> - for_each_dss_dev(dssdev) {
> - if (!dssdev->driver)
> - continue;
> -
> - if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
> - dssdev->driver->disable(dssdev);
> - dssdev->activate_after_resume = true;
> - } else {
> - dssdev->activate_after_resume = false;
> - }
> - }
> -
> - return 0;
> -}
> -
> -int dss_resume_all_devices(void)
> -{
> - struct omap_dss_device *dssdev = NULL;
> -
> - for_each_dss_dev(dssdev) {
> - if (!dssdev->driver)
> - continue;
> -
> - if (dssdev->activate_after_resume) {
> - dssdev->driver->enable(dssdev);
> - dssdev->activate_after_resume = false;
> - }
> - }
> -
> - return 0;
> -}
> -
> void dss_disable_all_devices(void)
> {
> struct omap_dss_device *dssdev = NULL;
> diff --git a/drivers/gpu/drm/omapdrm/dss/dss.h
> b/drivers/gpu/drm/omapdrm/dss/dss.h index 9a6453235585..a974d46672db 100644
> --- a/drivers/gpu/drm/omapdrm/dss/dss.h
> +++ b/drivers/gpu/drm/omapdrm/dss/dss.h
> @@ -206,8 +206,6 @@ int dss_set_min_bus_tput(struct device *dev, unsigned
> long tput); int dss_debugfs_create_file(const char *name, void
> (*write)(struct seq_file *));
>
> /* display */
> -int dss_suspend_all_devices(void);
> -int dss_resume_all_devices(void);
> void dss_disable_all_devices(void);
>
> int display_init_sysfs(struct platform_device *pdev);
> diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c
> b/drivers/gpu/drm/omapdrm/omap_drv.c index dfafdb602ad2..e21433c3fda4
> 100644
> --- a/drivers/gpu/drm/omapdrm/omap_drv.c
> +++ b/drivers/gpu/drm/omapdrm/omap_drv.c
> @@ -900,12 +900,52 @@ static int pdev_remove(struct platform_device *device)
> }
>
> #ifdef CONFIG_PM_SLEEP
> +static int omap_drm_suspend_all_displays(void)
> +{
> + struct omap_dss_device *dssdev = NULL;
> +
> + for_each_dss_dev(dssdev) {
> + if (!dssdev->driver)
> + continue;
> +
> + if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
> + dssdev->driver->disable(dssdev);
> + dssdev->activate_after_resume = true;
> + } else {
> + dssdev->activate_after_resume = false;
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int omap_drm_resume_all_displays(void)
> +{
> + struct omap_dss_device *dssdev = NULL;
> +
> + for_each_dss_dev(dssdev) {
> + if (!dssdev->driver)
> + continue;
> +
> + if (dssdev->activate_after_resume) {
> + dssdev->driver->enable(dssdev);
> + dssdev->activate_after_resume = false;
> + }
> + }
> +
> + return 0;
> +}
> +
> static int omap_drm_suspend(struct device *dev)
> {
> struct drm_device *drm_dev = dev_get_drvdata(dev);
>
> drm_kms_helper_poll_disable(drm_dev);
>
> + drm_modeset_lock_all(drm_dev);
The omapdss implementation of the suspend and resume handlers didn't take the
modeset locks. I wonder what we're trying to protect against here, what other
concurrent task(s) could race us ?
> + omap_drm_suspend_all_displays();
> + drm_modeset_unlock_all(drm_dev);
> +
> return 0;
> }
>
> @@ -913,6 +953,10 @@ static int omap_drm_resume(struct device *dev)
> {
> struct drm_device *drm_dev = dev_get_drvdata(dev);
>
> + drm_modeset_lock_all(drm_dev);
> + omap_drm_resume_all_displays();
> + drm_modeset_unlock_all(drm_dev);
> +
> drm_kms_helper_poll_enable(drm_dev);
>
> return omap_gem_resume(dev);
--
Regards,
Laurent Pinchart
More information about the dri-devel
mailing list