On 21.09.2023 21:26, Douglas Anderson wrote: > Based on grepping through the source code this driver appears to be > missing a call to drm_atomic_helper_shutdown() at system shutdown time > and at driver unbind time. Among other things, this means that if a > panel is in use that it won't be cleanly powered off at system > shutdown time. > > The fact that we should call drm_atomic_helper_shutdown() in the case > of OS shutdown/restart and at driver remove (or unbind) time comes > straight out of the kernel doc "driver instance overview" in > drm_drv.c. > > A few notes about this fix: > - When adding drm_atomic_helper_shutdown() to the unbind path, I added > it after drm_kms_helper_poll_fini() since that's when other drivers > seemed to have it. > - Technically with a previous patch, ("drm/atomic-helper: > drm_atomic_helper_shutdown(NULL) should be a noop"), we don't > actually need to check to see if our "drm" pointer is NULL before > calling drm_atomic_helper_shutdown(). We'll leave the "if" test in, > though, so that this patch can land without any dependencies. It > could potentially be removed later. > - This patch also makes sure to set the drvdata to NULL in the case of > bind errors to make sure that shutdown can't access freed data. > > Suggested-by: Maxime Ripard <mripard@xxxxxxxxxx> > Reviewed-by: Maxime Ripard <mripard@xxxxxxxxxx> > Signed-off-by: Douglas Anderson <dianders@xxxxxxxxxxxx> Seems to be working fine on all my test Exynos-based boards with display. Tested-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx> Reviewed-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx> > --- > This commit is only compile-time tested. > > (no changes since v1) > > drivers/gpu/drm/exynos/exynos_drm_drv.c | 11 +++++++++++ > 1 file changed, 11 insertions(+) > > diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c > index 8399256cb5c9..5380fb6c55ae 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c > @@ -300,6 +300,7 @@ static int exynos_drm_bind(struct device *dev) > drm_mode_config_cleanup(drm); > exynos_drm_cleanup_dma(drm); > kfree(private); > + dev_set_drvdata(dev, NULL); > err_free_drm: > drm_dev_put(drm); > > @@ -313,6 +314,7 @@ static void exynos_drm_unbind(struct device *dev) > drm_dev_unregister(drm); > > drm_kms_helper_poll_fini(drm); > + drm_atomic_helper_shutdown(drm); > > component_unbind_all(drm->dev, drm); > drm_mode_config_cleanup(drm); > @@ -350,9 +352,18 @@ static int exynos_drm_platform_remove(struct platform_device *pdev) > return 0; > } > > +static void exynos_drm_platform_shutdown(struct platform_device *pdev) > +{ > + struct drm_device *drm = platform_get_drvdata(pdev); > + > + if (drm) > + drm_atomic_helper_shutdown(drm); > +} > + > static struct platform_driver exynos_drm_platform_driver = { > .probe = exynos_drm_platform_probe, > .remove = exynos_drm_platform_remove, > + .shutdown = exynos_drm_platform_shutdown, > .driver = { > .name = "exynos-drm", > .pm = &exynos_drm_pm_ops, Best regards -- Marek Szyprowski, PhD Samsung R&D Institute Poland