]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm: Call drm_atomic_helper_shutdown() at shutdown time for misc drivers
authorDouglas Anderson <dianders@chromium.org>
Fri, 1 Sep 2023 23:39:53 +0000 (16:39 -0700)
committerDouglas Anderson <dianders@chromium.org>
Thu, 21 Sep 2023 17:41:04 +0000 (10:41 -0700)
Based on grepping through the source code these drivers appear to be
missing a call to drm_atomic_helper_shutdown() at system shutdown
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 comes straight out of the kernel doc "driver
instance overview" in drm_drv.c.

All of the drivers in this patch were fairly straightforward to fix
since they already had a call to drm_atomic_helper_shutdown() at
remove/unbind time but were just lacking one at system shutdown. The
only hitch is that some of these drivers use the component model to
register/unregister their DRM devices. The shutdown callback is part
of the original device. The typical solution here, based on how other
DRM drivers do this, is to keep track of whether the device is bound
based on drvdata. In most cases the drvdata is the drm_device, so we
can just make sure it is NULL when the device is not bound. In some
drivers, this required minor code changes. To make things simpler,
drm_atomic_helper_shutdown() has been modified to consider a NULL
drm_device as a noop in the patch ("drm/atomic-helper:
drm_atomic_helper_shutdown(NULL) should be a noop").

Suggested-by: Maxime Ripard <mripard@kernel.org>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Tested-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Acked-by: Maxime Ripard <mripard@kernel.org>
Tested-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Reviewed-by: Sui Jingfeng <suijingfeng@loongson.cn>
Tested-by: Sui Jingfeng <suijingfeng@loongson.cn>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20230901163944.RFT.2.I9115e5d094a43e687978b0699cc1fe9f2a3452ea@changeid
19 files changed:
drivers/gpu/drm/arm/display/komeda/komeda_drv.c
drivers/gpu/drm/arm/display/komeda/komeda_kms.c
drivers/gpu/drm/arm/display/komeda/komeda_kms.h
drivers/gpu/drm/arm/hdlcd_drv.c
drivers/gpu/drm/arm/malidp_drv.c
drivers/gpu/drm/ast/ast_drv.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
drivers/gpu/drm/hyperv/hyperv_drm_drv.c
drivers/gpu/drm/logicvc/logicvc_drm.c
drivers/gpu/drm/loongson/lsdc_drv.c
drivers/gpu/drm/mcde/mcde_drv.c
drivers/gpu/drm/omapdrm/omap_drv.c
drivers/gpu/drm/qxl/qxl_drv.c
drivers/gpu/drm/sti/sti_drv.c
drivers/gpu/drm/sun4i/sun4i_drv.c
drivers/gpu/drm/tiny/bochs.c
drivers/gpu/drm/tiny/cirrus.c

index cb2a2be24c5fffe23edba1d142ac352026f29364..cc57ea4e13ae6ea0c337aad464e8889d5f9ab691 100644 (file)
@@ -45,6 +45,14 @@ static void komeda_platform_remove(struct platform_device *pdev)
        devm_kfree(dev, mdrv);
 }
 
+static void komeda_platform_shutdown(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct komeda_drv *mdrv = dev_get_drvdata(dev);
+
+       komeda_kms_shutdown(mdrv->kms);
+}
+
 static int komeda_platform_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -142,6 +150,7 @@ static const struct dev_pm_ops komeda_pm_ops = {
 static struct platform_driver komeda_platform_driver = {
        .probe  = komeda_platform_probe,
        .remove_new = komeda_platform_remove,
+       .shutdown = komeda_platform_shutdown,
        .driver = {
                .name = "komeda",
                .of_match_table = komeda_of_match,
index 9299026701f348dddcd99373d7036170cd95626c..fe46b0ebefea379f21c99a3809334c0aaadcdf43 100644 (file)
@@ -340,3 +340,10 @@ void komeda_kms_detach(struct komeda_kms_dev *kms)
        komeda_kms_cleanup_private_objs(kms);
        drm->dev_private = NULL;
 }
+
+void komeda_kms_shutdown(struct komeda_kms_dev *kms)
+{
+       struct drm_device *drm = &kms->base;
+
+       drm_atomic_helper_shutdown(drm);
+}
index 6ef65532635706a82e9de80e65f02fd20d5c9e29..a4048724564dbcfef1b0ed6ef25791cc84f6f6e8 100644 (file)
@@ -190,5 +190,6 @@ void komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc,
 
 struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev);
 void komeda_kms_detach(struct komeda_kms_dev *kms);
+void komeda_kms_shutdown(struct komeda_kms_dev *kms);
 
 #endif /*_KOMEDA_KMS_H_*/
index aa06f98380154a6d444576816cda8490ccbdc4d6..32be9e370049564f9adc99250495adb5366302c0 100644 (file)
@@ -372,6 +372,11 @@ static void hdlcd_remove(struct platform_device *pdev)
        component_master_del(&pdev->dev, &hdlcd_master_ops);
 }
 
+static void hdlcd_shutdown(struct platform_device *pdev)
+{
+       drm_atomic_helper_shutdown(platform_get_drvdata(pdev));
+}
+
 static const struct of_device_id  hdlcd_of_match[] = {
        { .compatible   = "arm,hdlcd" },
        {},
@@ -399,6 +404,7 @@ static SIMPLE_DEV_PM_OPS(hdlcd_pm_ops, hdlcd_pm_suspend, hdlcd_pm_resume);
 static struct platform_driver hdlcd_platform_driver = {
        .probe          = hdlcd_probe,
        .remove_new     = hdlcd_remove,
+       .shutdown       = hdlcd_shutdown,
        .driver = {
                .name = "hdlcd",
                .pm = &hdlcd_pm_ops,
index 62329d5dd992ed749a65411009c032488c580f8b..6682131d29104464a30f66d512782d785b4e4120 100644 (file)
@@ -941,6 +941,11 @@ static void malidp_platform_remove(struct platform_device *pdev)
        component_master_del(&pdev->dev, &malidp_master_ops);
 }
 
+static void malidp_platform_shutdown(struct platform_device *pdev)
+{
+       drm_atomic_helper_shutdown(platform_get_drvdata(pdev));
+}
+
 static int __maybe_unused malidp_pm_suspend(struct device *dev)
 {
        struct drm_device *drm = dev_get_drvdata(dev);
@@ -982,6 +987,7 @@ static const struct dev_pm_ops malidp_pm_ops = {
 static struct platform_driver malidp_platform_driver = {
        .probe          = malidp_platform_probe,
        .remove_new     = malidp_platform_remove,
+       .shutdown       = malidp_platform_shutdown,
        .driver = {
                .name = "mali-dp",
                .pm = &malidp_pm_ops,
index e1224ef4ad83d4d41d70cba06d0d60bbf159643a..cf5b754f044c76ecb554883c22fd5db443f41720 100644 (file)
@@ -125,6 +125,11 @@ static void ast_pci_remove(struct pci_dev *pdev)
        drm_atomic_helper_shutdown(dev);
 }
 
+static void ast_pci_shutdown(struct pci_dev *pdev)
+{
+       drm_atomic_helper_shutdown(pci_get_drvdata(pdev));
+}
+
 static int ast_drm_freeze(struct drm_device *dev)
 {
        int error;
@@ -209,6 +214,7 @@ static struct pci_driver ast_pci_driver = {
        .id_table = ast_pciidlist,
        .probe = ast_pci_probe,
        .remove = ast_pci_remove,
+       .shutdown = ast_pci_shutdown,
        .driver.pm = &ast_pm_ops,
 };
 
index fa0f9a93d50d937e26a1be6d2e26b116655a505d..84c54e8622d1d428d15c6b4811f364aabc3ed82a 100644 (file)
@@ -782,6 +782,11 @@ static void atmel_hlcdc_dc_drm_remove(struct platform_device *pdev)
        drm_dev_put(ddev);
 }
 
+static void atmel_hlcdc_dc_drm_shutdown(struct platform_device *pdev)
+{
+       drm_atomic_helper_shutdown(platform_get_drvdata(pdev));
+}
+
 static int atmel_hlcdc_dc_drm_suspend(struct device *dev)
 {
        struct drm_device *drm_dev = dev_get_drvdata(dev);
@@ -825,6 +830,7 @@ static const struct of_device_id atmel_hlcdc_dc_of_match[] = {
 static struct platform_driver atmel_hlcdc_dc_platform_driver = {
        .probe  = atmel_hlcdc_dc_drm_probe,
        .remove_new = atmel_hlcdc_dc_drm_remove,
+       .shutdown = atmel_hlcdc_dc_drm_shutdown,
        .driver = {
                .name   = "atmel-hlcdc-display-controller",
                .pm     = pm_sleep_ptr(&atmel_hlcdc_dc_drm_pm_ops),
index a395f93449f36813bef8433f16583e04f451d0cb..ab6c0c6cd0e2e39bb2f8b10a5ce9d8de527c6ee5 100644 (file)
@@ -356,9 +356,17 @@ static void fsl_dcu_drm_remove(struct platform_device *pdev)
        clk_unregister(fsl_dev->pix_clk);
 }
 
+static void fsl_dcu_drm_shutdown(struct platform_device *pdev)
+{
+       struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);
+
+       drm_atomic_helper_shutdown(fsl_dev->drm);
+}
+
 static struct platform_driver fsl_dcu_drm_platform_driver = {
        .probe          = fsl_dcu_drm_probe,
        .remove_new     = fsl_dcu_drm_remove,
+       .shutdown       = fsl_dcu_drm_shutdown,
        .driver         = {
                .name   = "fsl-dcu",
                .pm     = &fsl_dcu_drm_pm_ops,
index 8a98fa276e8a9d9d21d05ed087ac51a1da5d3cfa..57c21ec452b707b26a2f686cda540ca6baecca47 100644 (file)
@@ -357,6 +357,11 @@ static void hibmc_pci_remove(struct pci_dev *pdev)
        hibmc_unload(dev);
 }
 
+static void hibmc_pci_shutdown(struct pci_dev *pdev)
+{
+       drm_atomic_helper_shutdown(pci_get_drvdata(pdev));
+}
+
 static const struct pci_device_id hibmc_pci_table[] = {
        { PCI_VDEVICE(HUAWEI, 0x1711) },
        {0,}
@@ -367,6 +372,7 @@ static struct pci_driver hibmc_pci_driver = {
        .id_table =     hibmc_pci_table,
        .probe =        hibmc_pci_probe,
        .remove =       hibmc_pci_remove,
+       .shutdown =     hibmc_pci_shutdown,
        .driver.pm =    &hibmc_pm_ops,
 };
 
index 8026118c6e0330f49fa3851cfaf0b2dd6ec37349..58b0b46a21e6864dc92833a4126a6cd77f8e06af 100644 (file)
@@ -178,6 +178,11 @@ static void hyperv_vmbus_remove(struct hv_device *hdev)
        vmbus_free_mmio(hv->mem->start, hv->fb_size);
 }
 
+static void hyperv_vmbus_shutdown(struct hv_device *hdev)
+{
+       drm_atomic_helper_shutdown(hv_get_drvdata(hdev));
+}
+
 static int hyperv_vmbus_suspend(struct hv_device *hdev)
 {
        struct drm_device *dev = hv_get_drvdata(hdev);
@@ -220,6 +225,7 @@ static struct hv_driver hyperv_hv_driver = {
        .id_table = hyperv_vmbus_tbl,
        .probe = hyperv_vmbus_probe,
        .remove = hyperv_vmbus_remove,
+       .shutdown = hyperv_vmbus_shutdown,
        .suspend = hyperv_vmbus_suspend,
        .resume = hyperv_vmbus_resume,
        .driver = {
index 749debd3d6a5772cf45c4b3a15212cb59b0e6988..01a37e28c0803abd168f812aed05070eb065e2d2 100644 (file)
@@ -482,6 +482,14 @@ static void logicvc_drm_remove(struct platform_device *pdev)
        of_reserved_mem_device_release(dev);
 }
 
+static void logicvc_drm_shutdown(struct platform_device *pdev)
+{
+       struct logicvc_drm *logicvc = platform_get_drvdata(pdev);
+       struct drm_device *drm_dev = &logicvc->drm_dev;
+
+       drm_atomic_helper_shutdown(drm_dev);
+}
+
 static const struct of_device_id logicvc_drm_of_table[] = {
        { .compatible = "xylon,logicvc-3.02.a-display" },
        { .compatible = "xylon,logicvc-4.01.a-display" },
@@ -492,6 +500,7 @@ MODULE_DEVICE_TABLE(of, logicvc_drm_of_table);
 static struct platform_driver logicvc_drm_platform_driver = {
        .probe          = logicvc_drm_probe,
        .remove_new     = logicvc_drm_remove,
+       .shutdown       = logicvc_drm_shutdown,
        .driver         = {
                .name           = "logicvc-drm",
                .of_match_table = logicvc_drm_of_table,
index 188ec82afcfbcbc711e351d43afdd473a054ec19..89ccc0c431690f7d458e999b464924b0af1b8107 100644 (file)
@@ -327,6 +327,11 @@ static void lsdc_pci_remove(struct pci_dev *pdev)
        drm_atomic_helper_shutdown(ddev);
 }
 
+static void lsdc_pci_shutdown(struct pci_dev *pdev)
+{
+       drm_atomic_helper_shutdown(pci_get_drvdata(pdev));
+}
+
 static int lsdc_drm_freeze(struct drm_device *ddev)
 {
        struct lsdc_device *ldev = to_lsdc(ddev);
@@ -447,6 +452,7 @@ struct pci_driver lsdc_pci_driver = {
        .id_table = lsdc_pciid_list,
        .probe = lsdc_pci_probe,
        .remove = lsdc_pci_remove,
+       .shutdown = lsdc_pci_shutdown,
        .driver.pm = &lsdc_pm_ops,
 };
 
index a2572fb311f08277d5bad24069e3839bbaf3334c..10c06440c7e73e859f84caa86b8afb204cdca177 100644 (file)
@@ -459,6 +459,14 @@ static void mcde_remove(struct platform_device *pdev)
        regulator_disable(mcde->epod);
 }
 
+static void mcde_shutdown(struct platform_device *pdev)
+{
+       struct drm_device *drm = platform_get_drvdata(pdev);
+
+       if (drm->registered)
+               drm_atomic_helper_shutdown(drm);
+}
+
 static const struct of_device_id mcde_of_match[] = {
        {
                .compatible = "ste,mcde",
@@ -473,6 +481,7 @@ static struct platform_driver mcde_driver = {
        },
        .probe = mcde_probe,
        .remove_new = mcde_remove,
+       .shutdown = mcde_shutdown,
 };
 
 static struct platform_driver *const component_drivers[] = {
index afeeb773755252cb5d34bbd63ad0106234a5d267..b2835b3ea6f58b8513bd9dda5c6829d49e636b2e 100644 (file)
@@ -817,6 +817,13 @@ static void pdev_remove(struct platform_device *pdev)
        kfree(priv);
 }
 
+static void pdev_shutdown(struct platform_device *pdev)
+{
+       struct omap_drm_private *priv = platform_get_drvdata(pdev);
+
+       drm_atomic_helper_shutdown(priv->ddev);
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int omap_drm_suspend(struct device *dev)
 {
@@ -846,6 +853,7 @@ static struct platform_driver pdev = {
        },
        .probe = pdev_probe,
        .remove_new = pdev_remove,
+       .shutdown = pdev_shutdown,
 };
 
 static struct platform_driver * const drivers[] = {
index b30ede1cf62d329389c2becc03836b9856082e4f..a4144c62ca93909edb20d056a21ed48038ac73fd 100644 (file)
@@ -163,6 +163,12 @@ qxl_pci_remove(struct pci_dev *pdev)
                vga_put(pdev, VGA_RSRC_LEGACY_IO);
 }
 
+static void
+qxl_pci_shutdown(struct pci_dev *pdev)
+{
+       drm_atomic_helper_shutdown(pci_get_drvdata(pdev));
+}
+
 DEFINE_DRM_GEM_FOPS(qxl_fops);
 
 static int qxl_drm_freeze(struct drm_device *dev)
@@ -269,6 +275,7 @@ static struct pci_driver qxl_pci_driver = {
         .id_table = pciidlist,
         .probe = qxl_pci_probe,
         .remove = qxl_pci_remove,
+        .shutdown = qxl_pci_shutdown,
         .driver.pm = &qxl_pm_ops,
 };
 
index 2390c1bb6596f0f0a00e436b42a66ff60aee3fca..4bab93c4fefd28f71fa0c1896ce60da180a4f3a2 100644 (file)
@@ -174,6 +174,7 @@ static void sti_cleanup(struct drm_device *ddev)
        drm_atomic_helper_shutdown(ddev);
        drm_mode_config_cleanup(ddev);
        component_unbind_all(ddev->dev, ddev);
+       dev_set_drvdata(ddev->dev, NULL);
        kfree(private);
        ddev->dev_private = NULL;
 }
@@ -253,6 +254,11 @@ static void sti_platform_remove(struct platform_device *pdev)
        component_master_del(&pdev->dev, &sti_ops);
 }
 
+static void sti_platform_shutdown(struct platform_device *pdev)
+{
+       drm_atomic_helper_shutdown(platform_get_drvdata(pdev));
+}
+
 static const struct of_device_id sti_dt_ids[] = {
        { .compatible = "st,sti-display-subsystem", },
        { /* end node */ },
@@ -262,6 +268,7 @@ MODULE_DEVICE_TABLE(of, sti_dt_ids);
 static struct platform_driver sti_platform_driver = {
        .probe = sti_platform_probe,
        .remove_new = sti_platform_remove,
+       .shutdown = sti_platform_shutdown,
        .driver = {
                .name = DRIVER_NAME,
                .of_match_table = sti_dt_ids,
index 6a8dfc022d3c1cc21e1ac48fba28a96eacb70a87..35d7a7ffd208c045305bf6dbb6c87e1f245364df 100644 (file)
@@ -413,6 +413,11 @@ static void sun4i_drv_remove(struct platform_device *pdev)
        component_master_del(&pdev->dev, &sun4i_drv_master_ops);
 }
 
+static void sun4i_drv_shutdown(struct platform_device *pdev)
+{
+       drm_atomic_helper_shutdown(platform_get_drvdata(pdev));
+}
+
 static const struct of_device_id sun4i_drv_of_table[] = {
        { .compatible = "allwinner,sun4i-a10-display-engine" },
        { .compatible = "allwinner,sun5i-a10s-display-engine" },
@@ -437,6 +442,7 @@ MODULE_DEVICE_TABLE(of, sun4i_drv_of_table);
 static struct platform_driver sun4i_drv_platform_driver = {
        .probe          = sun4i_drv_probe,
        .remove_new     = sun4i_drv_remove,
+       .shutdown       = sun4i_drv_shutdown,
        .driver         = {
                .name           = "sun4i-drm",
                .of_match_table = sun4i_drv_of_table,
index d254679a136e67ac10af0753572889329fce91db..c23c9f0cf49cb9f226c9dba56b215d9d2e2f519c 100644 (file)
@@ -690,6 +690,11 @@ static void bochs_pci_remove(struct pci_dev *pdev)
        drm_dev_put(dev);
 }
 
+static void bochs_pci_shutdown(struct pci_dev *pdev)
+{
+       drm_atomic_helper_shutdown(pci_get_drvdata(pdev));
+}
+
 static const struct pci_device_id bochs_pci_tbl[] = {
        {
                .vendor      = 0x1234,
@@ -720,6 +725,7 @@ static struct pci_driver bochs_pci_driver = {
        .id_table =     bochs_pci_tbl,
        .probe =        bochs_pci_probe,
        .remove =       bochs_pci_remove,
+       .shutdown =     bochs_pci_shutdown,
        .driver.pm =    &bochs_pm_ops,
 };
 
index 594bc472862fe674a267507ec670501986252a7c..c5c34cd2edc1f825ea1abcde55bfe0d730827345 100644 (file)
@@ -727,6 +727,11 @@ static void cirrus_pci_remove(struct pci_dev *pdev)
        drm_atomic_helper_shutdown(dev);
 }
 
+static void cirrus_pci_shutdown(struct pci_dev *pdev)
+{
+       drm_atomic_helper_shutdown(pci_get_drvdata(pdev));
+}
+
 static const struct pci_device_id pciidlist[] = {
        {
                .vendor    = PCI_VENDOR_ID_CIRRUS,
@@ -748,6 +753,7 @@ static struct pci_driver cirrus_pci_driver = {
        .id_table = pciidlist,
        .probe = cirrus_pci_probe,
        .remove = cirrus_pci_remove,
+       .shutdown = cirrus_pci_shutdown,
 };
 
 drm_module_pci_driver(cirrus_pci_driver)