[PATCH] drm/fb-helper: Remove drm_fb_helper_unprepare() from drm_fb_helper_fini()
From: Thomas Zimmermann <tzimmermann@suse.de>
Date: 2023-02-16 14:06:26
Also in:
amd-gfx, dri-devel, intel-gfx, linux-arm-msm, linux-samsung-soc, linux-tegra
Subsystem:
drm driver for qualcomm display hardware, drm drivers, drm drivers and misc gpu patches, drm drivers for exynos, drm drivers for gma500 (poulsbo, moorestown and derivative chipsets), drm drivers for nvidia tegra, drm drivers for ti omap, intel drm display for xe and i915 drivers, intel drm i915 driver (meteor lake, dg2 and older excluding poulsbo, moorestown and derivative), marvell armada drm support, radeon and amdgpu drm drivers, the rest · Maintainers:
Rob Clark, Dmitry Baryshkov, David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Inki Dae, Seung-Woo Kim, Kyungmin Park, Patrik Jakobsson, Thierry Reding, Mikko Perttunen, Tomi Valkeinen, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen, Tvrtko Ursulin, Russell King, Alex Deucher, Christian König, Linus Torvalds
Move drm_fb_helper_unprepare() from drm_fb_helper_fini() into the
calling fbdev implementation. Avoids a possible stale mutex with
generic fbdev code.
As indicated by its name, drm_fb_helper_prepare() prepares struct
drm_fb_helper before setting up the fbdev support with a call to
drm_fb_helper_init(). In legacy fbdev emulation, this happens next
to each other. If successful, drm_fb_helper_fini() later tear down
the fbdev device and also unprepare via drm_fb_helper_unprepare().
Generic fbdev emulation prepares struct drm_fb_helper immediately
after allocating the instance. It only calls drm_fb_helper_init()
as part of processing a hotplug event. If the hotplug-handling fails,
it runs drm_fb_helper_fini(). This unprepares the fb-helper instance
and the next hotplug event runs on stale data.
Solve this by moving drm_fb_helper_unprepare() from drm_fb_helper_fini()
into the fbdev implementations. Call it right before freeing the
fb-helper instance.
Fixes: 4825797c36da ("drm/fb-helper: Introduce drm_fb_helper_unprepare()")
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Javier Martinez Canillas <javierm@redhat.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: David Airlie <airlied@gmail.com>
Cc: Daniel Vetter <redacted>
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/armada/armada_fbdev.c | 3 +++
drivers/gpu/drm/drm_fb_helper.c | 2 --
drivers/gpu/drm/drm_fbdev_generic.c | 2 ++
drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 3 ++-
drivers/gpu/drm/gma500/framebuffer.c | 2 ++
drivers/gpu/drm/i915/display/intel_fbdev.c | 1 +
drivers/gpu/drm/msm/msm_fbdev.c | 2 ++
drivers/gpu/drm/omapdrm/omap_fbdev.c | 2 ++
drivers/gpu/drm/radeon/radeon_fb.c | 2 ++
drivers/gpu/drm/tegra/fb.c | 1 +
10 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c
index 07e410c62b7a..0e44f53e9fa4 100644
--- a/drivers/gpu/drm/armada/armada_fbdev.c
+++ b/drivers/gpu/drm/armada/armada_fbdev.c@@ -147,6 +147,7 @@ int armada_fbdev_init(struct drm_device *dev) err_fb_setup: drm_fb_helper_fini(fbh); err_fb_helper: + drm_fb_helper_unprepare(fbh); priv->fbdev = NULL; return ret; }
@@ -164,6 +165,8 @@ void armada_fbdev_fini(struct drm_device *dev) if (fbh->fb) fbh->fb->funcs->destroy(fbh->fb); + drm_fb_helper_unprepare(fbh); + priv->fbdev = NULL; } }
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 28c428e9c530..a39998047f8a 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c@@ -590,8 +590,6 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) } mutex_unlock(&kernel_fb_helper_lock); - drm_fb_helper_unprepare(fb_helper); - if (!fb_helper->client.funcs) drm_client_release(&fb_helper->client); }
diff --git a/drivers/gpu/drm/drm_fbdev_generic.c b/drivers/gpu/drm/drm_fbdev_generic.c
index 365f80717fa1..4d6325e91565 100644
--- a/drivers/gpu/drm/drm_fbdev_generic.c
+++ b/drivers/gpu/drm/drm_fbdev_generic.c@@ -65,6 +65,8 @@ static void drm_fbdev_fb_destroy(struct fb_info *info) drm_client_framebuffer_delete(fb_helper->buffer); drm_client_release(&fb_helper->client); + + drm_fb_helper_unprepare(fb_helper); kfree(fb_helper); }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index b89e33af8da8..4929ffe5a09a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c@@ -183,8 +183,8 @@ int exynos_drm_fbdev_init(struct drm_device *dev) err_setup: drm_fb_helper_fini(helper); - err_init: + drm_fb_helper_unprepare(helper); private->fb_helper = NULL; kfree(fbdev);
@@ -219,6 +219,7 @@ void exynos_drm_fbdev_fini(struct drm_device *dev) fbdev = to_exynos_fbdev(private->fb_helper); exynos_drm_fbdev_destroy(dev, private->fb_helper); + drm_fb_helper_unprepare(private->fb_helper); kfree(fbdev); private->fb_helper = NULL; }
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
index 1f04c07ee180..f471e0cb7298 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c@@ -427,6 +427,7 @@ int psb_fbdev_init(struct drm_device *dev) fini: drm_fb_helper_fini(fb_helper); free: + drm_fb_helper_unprepare(fb_helper); kfree(fb_helper); return ret; }
@@ -439,6 +440,7 @@ static void psb_fbdev_fini(struct drm_device *dev) return; psb_fbdev_destroy(dev, dev_priv->fb_helper); + drm_fb_helper_unprepare(dev_priv->fb_helper); kfree(dev_priv->fb_helper); dev_priv->fb_helper = NULL; }
diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c
index 6113d7627d45..98029059f701 100644
--- a/drivers/gpu/drm/i915/display/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/display/intel_fbdev.c@@ -352,6 +352,7 @@ static void intel_fbdev_destroy(struct intel_fbdev *ifbdev) if (ifbdev->fb) drm_framebuffer_remove(&ifbdev->fb->base); + drm_fb_helper_unprepare(&ifbdev->helper); kfree(ifbdev); }
diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c
index 915b213f3a5c..c804e5ba682a 100644
--- a/drivers/gpu/drm/msm/msm_fbdev.c
+++ b/drivers/gpu/drm/msm/msm_fbdev.c@@ -170,6 +170,7 @@ struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev) fini: drm_fb_helper_fini(helper); fail: + drm_fb_helper_unprepare(helper); kfree(fbdev); return NULL; }
@@ -196,6 +197,7 @@ void msm_fbdev_free(struct drm_device *dev) drm_framebuffer_remove(fbdev->fb); } + drm_fb_helper_unprepare(helper); kfree(fbdev); priv->fbdev = NULL;
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c
index fc5f52d567c6..84429728347f 100644
--- a/drivers/gpu/drm/omapdrm/omap_fbdev.c
+++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c@@ -256,6 +256,7 @@ void omap_fbdev_init(struct drm_device *dev) fini: drm_fb_helper_fini(helper); fail: + drm_fb_helper_unprepare(helper); kfree(fbdev); dev_warn(dev->dev, "omap_fbdev_init failed\n");
@@ -286,6 +287,7 @@ void omap_fbdev_fini(struct drm_device *dev) if (fbdev->fb) drm_framebuffer_remove(fbdev->fb); + drm_fb_helper_unprepare(helper); kfree(fbdev); priv->fbdev = NULL;
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index 6e5eed0e157c..c4807f0c43bc 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c@@ -367,6 +367,7 @@ int radeon_fbdev_init(struct radeon_device *rdev) fini: drm_fb_helper_fini(&rfbdev->helper); free: + drm_fb_helper_unprepare(&rfbdev->helper); kfree(rfbdev); return ret; }
@@ -377,6 +378,7 @@ void radeon_fbdev_fini(struct radeon_device *rdev) return; radeon_fbdev_destroy(rdev->ddev, rdev->mode_info.rfbdev); + drm_fb_helper_unprepare(&rdev->mode_info.rfbdev->helper); kfree(rdev->mode_info.rfbdev); rdev->mode_info.rfbdev = NULL; }
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index 153c39c32c71..bfebe2786d61 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c@@ -315,6 +315,7 @@ static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm) static void tegra_fbdev_free(struct tegra_fbdev *fbdev) { + drm_fb_helper_unprepare(&fbdev->base); kfree(fbdev); }
--
2.39.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel