Douglas Anderson
2024-Jun-12 22:23 UTC
[PATCH v2 0/8] drm: make leftover drivers call drm_atomic_helper_shutdown() at the right times
This patch series is the leftovers of a patch series sent in September 2023 [1] in an attempt to get some of the patches landed finally. This patch series originally came about after a _long_ discussion between me and Maxime Ripard in response to a different patch I sent out [2]. As part of that discussion, we realized that it would be good if DRM drivers consistently called drm_atomic_helper_shutdown() properly at shutdown and driver remove time as it's documented that they should do. The eventual goal of this would be to enable removing some hacky code from panel drivers where they had to hook into shutdown themselves because the DRM driver wasn't calling them. It turns out that quite a lot of drivers seemed to be missing drm_atomic_helper_shutdown() in one or both places that it was supposed to be. This patch series attempts to fix all the drivers that I was able to identify. NOTE: fixing this wasn't exactly cookie cutter. Each driver has its own unique way of setting itself up and tearing itself down. Some drivers also use the component model, which adds extra fun. I've made my best guess at solving this and I've run a bunch of compile tests (specifically, allmodconfig for amd64, arm64, and powerpc). That being said, these code changes are not totally trivial and I've done zero real testing on them. Making these patches was also a little mind numbing and I'm certain my eyes glazed over at several points when writing them. What I'm trying to say is to please double-check that I didn't do anything too silly, like cast your driver's drvdata to the wrong type. Even better, test these patches! Apparently most of these drivers now land through drm-misc [3], so hopefully they can land. The two that don't (amdgpu and radeon) are the ones I'm most ucertain about anyway so I've stuck them at the end. If I've totally buggered those up feel free to take my patch as a bug report and submit your own proper fix. ...or if there's some reason that we don't need to do anything for those drivers then let me know and we can drop them. I'd like to call out a few drivers that I _didn't_ fix in this series and why. If any of these drivers should be fixed then please yell. - DRM drivers backed by usb_driver (like gud, gm12u320, udl): I didn't add the call to drm_atomic_helper_shutdown() at shutdown time because there's no ".shutdown" callback for them USB drivers. Given that USB is hotpluggable, I'm assuming that they are robust against this and the special shutdown callback isn't needed. - ofdrm and simpledrm: These didn't have drm_atomic_helper_shutdown() in either shutdown or remove, but I didn't add it. I think that's OK since they're sorta special and not really directly controlling hardware power sequencing. - virtio, vkms, vmwgfx, xen: I believe these are all virtual (thus they wouldn't directly drive a panel) and adding the shutdown didn't look straightforward, so I skipped them. I've let each patch in the series get CCed straight from get_maintainer. That means not everyone will have received every patch but everyone should be on the cover letter. I know some people dislike this but when touching this many drivers there's not much choice. dri-devel and lkml have been CCed and lore/lei exist, so hopefully that's enough for folks. I'm happy to add people to the whole series for future posts. [1] https://lore.kernel.org/r/20230901234202.566951-1-dianders at chromium.org [2] https://lore.kernel.org/r/20230804140605.RFC.4.I930069a32baab6faf46d6b234f89613b5cec0f14 at changeid [3] https://lore.kernel.org/r/Zmm6_27GikpmT3HQ at phenom.ffwll.local Changes in v2: - Gathered whatever hadn't landed, rebased, and reposted. Douglas Anderson (8): drm/kmb: Call drm_atomic_helper_shutdown() at shutdown time drm/nouveau: Call drm_atomic_helper_shutdown() or equiv at shutdown time drm/tegra: Call drm_atomic_helper_shutdown() at shutdown time drm/arcpgu: Call drm_atomic_helper_shutdown() at shutdown time drm/sprd: Call drm_atomic_helper_shutdown() at remove time drm/gma500: Call drm_helper_force_disable_all() at shutdown/remove time drm/radeon: Call drm_helper_force_disable_all() at shutdown/remove time drm/amdgpu: Call drm_atomic_helper_shutdown() at shutdown time drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 10 ++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 2 ++ drivers/gpu/drm/gma500/psb_drv.c | 8 ++++++++ drivers/gpu/drm/kmb/kmb_drv.c | 6 ++++++ drivers/gpu/drm/nouveau/nouveau_display.c | 9 +++++++++ drivers/gpu/drm/nouveau/nouveau_display.h | 1 + drivers/gpu/drm/nouveau/nouveau_drm.c | 13 +++++++++++++ drivers/gpu/drm/nouveau/nouveau_drv.h | 1 + drivers/gpu/drm/nouveau/nouveau_platform.c | 6 ++++++ drivers/gpu/drm/radeon/radeon_drv.c | 7 ++++++- drivers/gpu/drm/sprd/sprd_drm.c | 4 +++- drivers/gpu/drm/tegra/drm.c | 6 ++++++ drivers/gpu/drm/tiny/arcpgu.c | 6 ++++++ 14 files changed, 78 insertions(+), 2 deletions(-) -- 2.45.2.505.gda0bf45e8d-goog
Douglas Anderson
2024-Jun-12 22:23 UTC
[PATCH v2 2/8] drm/nouveau: Call drm_atomic_helper_shutdown() or equiv at shutdown time
Based on grepping through the source code this driver appears to be missing a call to drm_atomic_helper_shutdown() (or drm_helper_force_disable_all() if not using atomic) 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. Suggested-by: Maxime Ripard <mripard at kernel.org> Reviewed-by: Maxime Ripard <mripard at kernel.org> Signed-off-by: Douglas Anderson <dianders at chromium.org> --- This commit is only compile-time tested. I made my best guess about how to fit this into the existing code. If someone wishes a different style, please yell. (no changes since v1) drivers/gpu/drm/nouveau/nouveau_display.c | 9 +++++++++ drivers/gpu/drm/nouveau/nouveau_display.h | 1 + drivers/gpu/drm/nouveau/nouveau_drm.c | 13 +++++++++++++ drivers/gpu/drm/nouveau/nouveau_drv.h | 1 + drivers/gpu/drm/nouveau/nouveau_platform.c | 6 ++++++ 5 files changed, 30 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index d4725a968827..15da55c382f1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -645,6 +645,15 @@ nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime) disp->fini(dev, runtime, suspend); } +void +nouveau_display_shutdown(struct drm_device *dev) +{ + if (drm_drv_uses_atomic_modeset(dev)) + drm_atomic_helper_shutdown(dev); + else + drm_helper_force_disable_all(dev); +} + static void nouveau_display_create_properties(struct drm_device *dev) { diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h index 2ab2ddb1eadf..9df62e833cda 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.h +++ b/drivers/gpu/drm/nouveau/nouveau_display.h @@ -47,6 +47,7 @@ void nouveau_display_destroy(struct drm_device *dev); int nouveau_display_init(struct drm_device *dev, bool resume, bool runtime); void nouveau_display_hpd_resume(struct drm_device *dev); void nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime); +void nouveau_display_shutdown(struct drm_device *dev); int nouveau_display_suspend(struct drm_device *dev, bool runtime); void nouveau_display_resume(struct drm_device *dev, bool runtime); int nouveau_display_vblank_enable(struct drm_crtc *crtc); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index a947e1d5f309..b41154c9b9cc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -894,6 +894,18 @@ nouveau_drm_remove(struct pci_dev *pdev) pci_disable_device(pdev); } +void +nouveau_drm_device_shutdown(struct drm_device *dev) +{ + nouveau_display_shutdown(dev); +} + +static void +nouveau_drm_shutdown(struct pci_dev *pdev) +{ + nouveau_drm_device_shutdown(pci_get_drvdata(pdev)); +} + static int nouveau_do_suspend(struct drm_device *dev, bool runtime) { @@ -1361,6 +1373,7 @@ nouveau_drm_pci_driver = { .id_table = nouveau_drm_pci_table, .probe = nouveau_drm_probe, .remove = nouveau_drm_remove, + .shutdown = nouveau_drm_shutdown, .driver.pm = &nouveau_pm_ops, }; diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 25fca98a20bc..78a91686006b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -327,6 +327,7 @@ struct drm_device * nouveau_platform_device_create(const struct nvkm_device_tegra_func *, struct platform_device *, struct nvkm_device **); void nouveau_drm_device_remove(struct drm_device *dev); +void nouveau_drm_device_shutdown(struct drm_device *dev); #define NV_PRINTK(l,c,f,a...) do { \ struct nouveau_cli *_cli = (c); \ diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c b/drivers/gpu/drm/nouveau/nouveau_platform.c index bf2dc7567ea4..511f3a0c6ee9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_platform.c +++ b/drivers/gpu/drm/nouveau/nouveau_platform.c @@ -49,6 +49,11 @@ static void nouveau_platform_remove(struct platform_device *pdev) nouveau_drm_device_remove(dev); } +static void nouveau_platform_shutdown(struct platform_device *pdev) +{ + nouveau_drm_device_shutdown(platform_get_drvdata(pdev)); +} + #if IS_ENABLED(CONFIG_OF) static const struct nvkm_device_tegra_func gk20a_platform_data = { .iommu_bit = 34, @@ -93,4 +98,5 @@ struct platform_driver nouveau_platform_driver = { }, .probe = nouveau_platform_probe, .remove_new = nouveau_platform_remove, + .shutdown = nouveau_platform_shutdown, }; -- 2.45.2.505.gda0bf45e8d-goog
Possibly Parallel Threads
- [RFT PATCH v2 00/12] drm: call drm_atomic_helper_shutdown() at the right times
- [RFT PATCH v2 04/12] drm/nouveau: Call drm_atomic_helper_shutdown() or equiv at shutdown time
- [PATCH 4/7] drm: Move the legacy kms disable_all helper to crtc helpers
- [PATCH 4/7] drm: Move the legacy kms disable_all helper to crtc helpers
- [PATCH 0/4] drm/nouveau: Replace {un/reference} with {put, get} functions