From ddddedaa0db99481c5e5abe628ad54f65e8765bc Mon Sep 17 00:00:00 2001 From: Asahi Lina Date: Sun, 5 Feb 2023 21:51:24 +0900 Subject: drm/shmem-helper: Fix locking for drm_gem_shmem_get_pages_sgt() Other functions touching shmem->sgt take the pages lock, so do that here too. drm_gem_shmem_get_pages() & co take the same lock, so move to the _locked() variants to avoid recursive locking. Discovered while auditing locking to write the Rust abstractions. Fixes: 2194a63a818d ("drm: Add library for shmem backed GEM objects") Fixes: 4fa3d66f132b ("drm/shmem: Do dma_unmap_sg before purging pages") Signed-off-by: Asahi Lina Reviewed-by: Javier Martinez Canillas Signed-off-by: Javier Martinez Canillas Link: https://patchwork.freedesktop.org/patch/msgid/20230205125124.2260-1-lina@asahilina.net (cherry picked from commit aa8c85affe3facd3842c8912186623415931cc72) Signed-off-by: Javier Martinez Canillas --- drivers/gpu/drm/drm_gem_shmem_helper.c | 54 +++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c index 4b828ea7119c..259176d78f3b 100644 --- a/drivers/gpu/drm/drm_gem_shmem_helper.c +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c @@ -678,23 +678,7 @@ struct sg_table *drm_gem_shmem_get_sg_table(struct drm_gem_shmem_object *shmem) } EXPORT_SYMBOL_GPL(drm_gem_shmem_get_sg_table); -/** - * drm_gem_shmem_get_pages_sgt - Pin pages, dma map them, and return a - * scatter/gather table for a shmem GEM object. - * @shmem: shmem GEM object - * - * This function returns a scatter/gather table suitable for driver usage. If - * the sg table doesn't exist, the pages are pinned, dma-mapped, and a sg - * table created. - * - * This is the main function for drivers to get at backing storage, and it hides - * and difference between dma-buf imported and natively allocated objects. - * drm_gem_shmem_get_sg_table() should not be directly called by drivers. - * - * Returns: - * A pointer to the scatter/gather table of pinned pages or errno on failure. - */ -struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_shmem_object *shmem) +static struct sg_table *drm_gem_shmem_get_pages_sgt_locked(struct drm_gem_shmem_object *shmem) { struct drm_gem_object *obj = &shmem->base; int ret; @@ -705,7 +689,7 @@ struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_shmem_object *shmem) WARN_ON(obj->import_attach); - ret = drm_gem_shmem_get_pages(shmem); + ret = drm_gem_shmem_get_pages_locked(shmem); if (ret) return ERR_PTR(ret); @@ -727,10 +711,40 @@ err_free_sgt: sg_free_table(sgt); kfree(sgt); err_put_pages: - drm_gem_shmem_put_pages(shmem); + drm_gem_shmem_put_pages_locked(shmem); return ERR_PTR(ret); } -EXPORT_SYMBOL_GPL(drm_gem_shmem_get_pages_sgt); + +/** + * drm_gem_shmem_get_pages_sgt - Pin pages, dma map them, and return a + * scatter/gather table for a shmem GEM object. + * @shmem: shmem GEM object + * + * This function returns a scatter/gather table suitable for driver usage. If + * the sg table doesn't exist, the pages are pinned, dma-mapped, and a sg + * table created. + * + * This is the main function for drivers to get at backing storage, and it hides + * and difference between dma-buf imported and natively allocated objects. + * drm_gem_shmem_get_sg_table() should not be directly called by drivers. + * + * Returns: + * A pointer to the scatter/gather table of pinned pages or errno on failure. + */ +struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_shmem_object *shmem) +{ + int ret; + struct sg_table *sgt; + + ret = mutex_lock_interruptible(&shmem->pages_lock); + if (ret) + return ERR_PTR(ret); + sgt = drm_gem_shmem_get_pages_sgt_locked(shmem); + mutex_unlock(&shmem->pages_lock); + + return sgt; +} +EXPORT_SYMBOL(drm_gem_shmem_get_pages_sgt); /** * drm_gem_shmem_prime_import_sg_table - Produce a shmem GEM object from -- cgit v1.2.3 From fb073aa27a7e1b8c968c05c5447a77d49e832ec5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Fri, 17 Feb 2023 03:13:22 +0000 Subject: dma-buf: make kobj_type structure constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit ee6d3dd4ed48 ("driver core: make kobj_type constant.") the driver core allows the usage of const struct kobj_type. Take advantage of this to constify the structure definition to prevent modification at runtime. Signed-off-by: Thomas Weißschuh Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20230217-kobj_type-dma-buf-v1-1-b84a3616522c@weissschuh.net --- drivers/dma-buf/dma-buf-sysfs-stats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma-buf/dma-buf-sysfs-stats.c b/drivers/dma-buf/dma-buf-sysfs-stats.c index fbf725fae7c1..6cfbbf0720bd 100644 --- a/drivers/dma-buf/dma-buf-sysfs-stats.c +++ b/drivers/dma-buf/dma-buf-sysfs-stats.c @@ -112,7 +112,7 @@ static void dma_buf_sysfs_release(struct kobject *kobj) kfree(sysfs_entry); } -static struct kobj_type dma_buf_ktype = { +static const struct kobj_type dma_buf_ktype = { .sysfs_ops = &dma_buf_stats_sysfs_ops, .release = dma_buf_sysfs_release, .default_groups = dma_buf_stats_default_groups, -- cgit v1.2.3 From 3fb1f62f80a1d249260db5ea9e22c51e52fab9ae Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 16 Feb 2023 15:06:20 +0100 Subject: drm/fb-helper: Remove drm_fb_helper_unprepare() from drm_fb_helper_fini() 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: 643231b28380 ("drm/fbdev-generic: Minimize hotplug error handling") Cc: Thomas Zimmermann Cc: Javier Martinez Canillas Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: David Airlie Cc: Daniel Vetter Cc: dri-devel@lists.freedesktop.org Signed-off-by: Thomas Zimmermann Reviewed-by: Daniel Vetter Reviewed-by: Javier Martinez Canillas Link: https://patchwork.freedesktop.org/patch/msgid/20230216140620.17699-1-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(-) (limited to 'drivers') 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 ed197db5861d..3a11e23c45af 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -340,6 +340,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); } -- cgit v1.2.3