summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2026-04-03 19:05:46 +1000
committerDave Airlie <airlied@redhat.com>2026-04-03 19:07:43 +1000
commit75f53c4b2dbca831bf91e9befe06c9ad58f29352 (patch)
treeee1963aeb053bbf79121903a72a8a134f9600e99 /drivers/gpu
parent293fa6ebd46fffc2722b6c960f40f1eb74b08dba (diff)
parentf8995c2df519f382525ca4bc90553ad2ec611067 (diff)
downloadlwn-75f53c4b2dbca831bf91e9befe06c9ad58f29352.tar.gz
lwn-75f53c4b2dbca831bf91e9befe06c9ad58f29352.zip
Merge tag 'drm-misc-fixes-2026-04-02' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-fixes
A refcounting fix for bridges, revert a previous framebuffer use-after-free fix that turned out to be causing more problems, a hang fix for qaic, an initialization fix for ast, a error handling fix for sysfb, and a speculation fix for drm_compat_ioctl. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maxime Ripard <mripard@redhat.com> Link: https://patch.msgid.link/20260402-vivid-perfect-caiman-ca055e@houat
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/ast/ast_dp501.c2
-rw-r--r--drivers/gpu/drm/drm_bridge.c16
-rw-r--r--drivers/gpu/drm/drm_file.c5
-rw-r--r--drivers/gpu/drm/drm_ioc32.c2
-rw-r--r--drivers/gpu/drm/drm_mode_config.c9
-rw-r--r--drivers/gpu/drm/sysfb/efidrm.c46
6 files changed, 49 insertions, 31 deletions
diff --git a/drivers/gpu/drm/ast/ast_dp501.c b/drivers/gpu/drm/ast/ast_dp501.c
index 9e19d8c17730..677c52c0d99a 100644
--- a/drivers/gpu/drm/ast/ast_dp501.c
+++ b/drivers/gpu/drm/ast/ast_dp501.c
@@ -436,7 +436,7 @@ static void ast_init_analog(struct ast_device *ast)
/* Finally, clear bits [17:16] of SCU2c */
data = ast_read32(ast, 0x1202c);
data &= 0xfffcffff;
- ast_write32(ast, 0, data);
+ ast_write32(ast, 0x1202c, data);
/* Disable DVO */
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x00);
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index d6f11c68bb6a..1987789b258a 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -1569,11 +1569,17 @@ EXPORT_SYMBOL(devm_drm_put_bridge);
static void drm_bridge_debugfs_show_bridge(struct drm_printer *p,
struct drm_bridge *bridge,
unsigned int idx,
- bool lingering)
+ bool lingering,
+ bool scoped)
{
+ unsigned int refcount = kref_read(&bridge->refcount);
+
+ if (scoped)
+ refcount--;
+
drm_printf(p, "bridge[%u]: %ps\n", idx, bridge->funcs);
- drm_printf(p, "\trefcount: %u%s\n", kref_read(&bridge->refcount),
+ drm_printf(p, "\trefcount: %u%s\n", refcount,
lingering ? " [lingering]" : "");
drm_printf(p, "\ttype: [%d] %s\n",
@@ -1607,10 +1613,10 @@ static int allbridges_show(struct seq_file *m, void *data)
mutex_lock(&bridge_lock);
list_for_each_entry(bridge, &bridge_list, list)
- drm_bridge_debugfs_show_bridge(&p, bridge, idx++, false);
+ drm_bridge_debugfs_show_bridge(&p, bridge, idx++, false, false);
list_for_each_entry(bridge, &bridge_lingering_list, list)
- drm_bridge_debugfs_show_bridge(&p, bridge, idx++, true);
+ drm_bridge_debugfs_show_bridge(&p, bridge, idx++, true, false);
mutex_unlock(&bridge_lock);
@@ -1625,7 +1631,7 @@ static int encoder_bridges_show(struct seq_file *m, void *data)
unsigned int idx = 0;
drm_for_each_bridge_in_chain_scoped(encoder, bridge)
- drm_bridge_debugfs_show_bridge(&p, bridge, idx++, false);
+ drm_bridge_debugfs_show_bridge(&p, bridge, idx++, false, true);
return 0;
}
diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
index f52141f842a1..ec820686b302 100644
--- a/drivers/gpu/drm/drm_file.c
+++ b/drivers/gpu/drm/drm_file.c
@@ -233,7 +233,6 @@ static void drm_events_release(struct drm_file *file_priv)
void drm_file_free(struct drm_file *file)
{
struct drm_device *dev;
- int idx;
if (!file)
return;
@@ -250,11 +249,9 @@ void drm_file_free(struct drm_file *file)
drm_events_release(file);
- if (drm_core_check_feature(dev, DRIVER_MODESET) &&
- drm_dev_enter(dev, &idx)) {
+ if (drm_core_check_feature(dev, DRIVER_MODESET)) {
drm_fb_release(file);
drm_property_destroy_user_blobs(dev, file);
- drm_dev_exit(idx);
}
if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c
index e6b5b06de148..f3e40d1e6098 100644
--- a/drivers/gpu/drm/drm_ioc32.c
+++ b/drivers/gpu/drm/drm_ioc32.c
@@ -28,6 +28,7 @@
* IN THE SOFTWARE.
*/
#include <linux/compat.h>
+#include <linux/nospec.h>
#include <linux/ratelimit.h>
#include <linux/export.h>
@@ -374,6 +375,7 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (nr >= ARRAY_SIZE(drm_compat_ioctls))
return drm_ioctl(filp, cmd, arg);
+ nr = array_index_nospec(nr, ARRAY_SIZE(drm_compat_ioctls));
fn = drm_compat_ioctls[nr].fn;
if (!fn)
return drm_ioctl(filp, cmd, arg);
diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c
index 802bc4608abf..d12db9b0bab8 100644
--- a/drivers/gpu/drm/drm_mode_config.c
+++ b/drivers/gpu/drm/drm_mode_config.c
@@ -577,13 +577,10 @@ void drm_mode_config_cleanup(struct drm_device *dev)
*/
WARN_ON(!list_empty(&dev->mode_config.fb_list));
list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
- if (list_empty(&fb->filp_head) || drm_framebuffer_read_refcount(fb) > 1) {
- struct drm_printer p = drm_dbg_printer(dev, DRM_UT_KMS, "[leaked fb]");
+ struct drm_printer p = drm_dbg_printer(dev, DRM_UT_KMS, "[leaked fb]");
- drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
- drm_framebuffer_print_info(&p, 1, fb);
- }
- list_del_init(&fb->filp_head);
+ drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
+ drm_framebuffer_print_info(&p, 1, fb);
drm_framebuffer_free(&fb->base.refcount);
}
diff --git a/drivers/gpu/drm/sysfb/efidrm.c b/drivers/gpu/drm/sysfb/efidrm.c
index 50e0aeef709c..9d84caf69627 100644
--- a/drivers/gpu/drm/sysfb/efidrm.c
+++ b/drivers/gpu/drm/sysfb/efidrm.c
@@ -151,7 +151,6 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv,
struct drm_sysfb_device *sysfb;
struct drm_device *dev;
struct resource *mem = NULL;
- void __iomem *screen_base = NULL;
struct drm_plane *primary_plane;
struct drm_crtc *crtc;
struct drm_encoder *encoder;
@@ -238,21 +237,38 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv,
mem_flags = efidrm_get_mem_flags(dev, res->start, vsize);
- if (mem_flags & EFI_MEMORY_WC)
- screen_base = devm_ioremap_wc(&pdev->dev, mem->start, resource_size(mem));
- else if (mem_flags & EFI_MEMORY_UC)
- screen_base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
- else if (mem_flags & EFI_MEMORY_WT)
- screen_base = devm_memremap(&pdev->dev, mem->start, resource_size(mem),
- MEMREMAP_WT);
- else if (mem_flags & EFI_MEMORY_WB)
- screen_base = devm_memremap(&pdev->dev, mem->start, resource_size(mem),
- MEMREMAP_WB);
- else
+ if (mem_flags & EFI_MEMORY_WC) {
+ void __iomem *screen_base = devm_ioremap_wc(&pdev->dev, mem->start,
+ resource_size(mem));
+
+ if (!screen_base)
+ return ERR_PTR(-ENXIO);
+ iosys_map_set_vaddr_iomem(&sysfb->fb_addr, screen_base);
+ } else if (mem_flags & EFI_MEMORY_UC) {
+ void __iomem *screen_base = devm_ioremap(&pdev->dev, mem->start,
+ resource_size(mem));
+
+ if (!screen_base)
+ return ERR_PTR(-ENXIO);
+ iosys_map_set_vaddr_iomem(&sysfb->fb_addr, screen_base);
+ } else if (mem_flags & EFI_MEMORY_WT) {
+ void *screen_base = devm_memremap(&pdev->dev, mem->start,
+ resource_size(mem), MEMREMAP_WT);
+
+ if (IS_ERR(screen_base))
+ return ERR_CAST(screen_base);
+ iosys_map_set_vaddr(&sysfb->fb_addr, screen_base);
+ } else if (mem_flags & EFI_MEMORY_WB) {
+ void *screen_base = devm_memremap(&pdev->dev, mem->start,
+ resource_size(mem), MEMREMAP_WB);
+
+ if (IS_ERR(screen_base))
+ return ERR_CAST(screen_base);
+ iosys_map_set_vaddr(&sysfb->fb_addr, screen_base);
+ } else {
drm_err(dev, "invalid mem_flags: 0x%llx\n", mem_flags);
- if (!screen_base)
- return ERR_PTR(-ENOMEM);
- iosys_map_set_vaddr_iomem(&sysfb->fb_addr, screen_base);
+ return ERR_PTR(-EINVAL);
+ }
/*
* Modesetting