From: Greg Kroah-Hartman Date: Fri, 7 Aug 2026 12:14:59 +0000 (+0200) Subject: 6.18-stable patches X-Git-Tag: v6.6.151~27 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fd44bda7386b60985c58d93e9ab7fc77ab0ca8e7;p=thirdparty%2Fkernel%2Fstable-queue.git 6.18-stable patches added patches: drm-amdgpu-fix-context-pstate-override-handling.patch drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch drm-fb-helper-allocate-and-release-fb_info-in-single-place.patch drm-tegra-fbdev-remove-offset-into-framebuffer-memory.patch drm-xe-guc-fix-buffer-overflow-in-steered-register-list-allocation.patch --- diff --git a/queue-6.18/drm-amdgpu-fix-context-pstate-override-handling.patch b/queue-6.18/drm-amdgpu-fix-context-pstate-override-handling.patch new file mode 100644 index 0000000000..da14f533e5 --- /dev/null +++ b/queue-6.18/drm-amdgpu-fix-context-pstate-override-handling.patch @@ -0,0 +1,165 @@ +From stable+bounces-294132-greg=kroah.com@vger.kernel.org Fri Jul 31 18:07:44 2026 +From: Sasha Levin +Date: Fri, 31 Jul 2026 12:00:49 -0400 +Subject: drm/amdgpu: Fix context pstate override handling +To: stable@vger.kernel.org +Cc: "Tvrtko Ursulin" , "Chengming Gui" , "Alex Deucher" , "Christian König" , "Sasha Levin" +Message-ID: <20260731160049.647545-1-sashal@kernel.org> + +From: Tvrtko Ursulin + +[ Upstream commit c1dc4ccb82c9e56325d8e7514ca4c90bd1efb351 ] + +There are several problems in the context pstate handling code. + +The most serious ones are potential use-after-free and NULL pointer +dereferences at context initialization time. Both are due +amdgpu_ctx_init() not holding the adev->pm.stable_pstate_ctx_lock, which +is otherwise used from both sysfs and the context code itself for +modifying and clearing the stored context pointer. + +Second issue is that context fini can trample over the pstate +configuration set via sysfs. This is due the restore state +(ctx->stable_pstate) being saved at context init time, and not if, or when +the context actually changes the pstate. As the context exits it will +therefore incorrectly restore to what was set before the sysfs override +was requested. + +The simplest fix is to drastically simplify how the state is tracked, by +clearly defining the points at which pstate ownership is taken and +released, and to handle all transitions under the correct lock. + +Instead of at context init time, the previous state is saved only at the +point the context overrides the current state, and is restored on context +exit only if the context is still the owner of the current override state. + +Signed-off-by: Tvrtko Ursulin +Fixes: 79610d304133 ("drm/amdgpu: fix pstate setting issue") +Cc: Chengming Gui +Cc: Alex Deucher +Cc: "Christian König" +Signed-off-by: Alex Deucher +(cherry picked from commit 1b5e413713c0a93bc1818394d0ce49aaad21bd27) +Cc: # v6.1+ +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 71 ++++++++++++++++++-------------- + 1 file changed, 42 insertions(+), 29 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +@@ -321,7 +321,6 @@ static int amdgpu_ctx_init(struct amdgpu + struct drm_file *filp, struct amdgpu_ctx *ctx) + { + struct amdgpu_fpriv *fpriv = filp->driver_priv; +- u32 current_stable_pstate; + int r; + + r = amdgpu_ctx_priority_permit(filp, priority); +@@ -339,37 +338,22 @@ static int amdgpu_ctx_init(struct amdgpu + ctx->generation = amdgpu_vm_generation(mgr->adev, &fpriv->vm); + ctx->init_priority = priority; + ctx->override_priority = AMDGPU_CTX_PRIORITY_UNSET; +- +- r = amdgpu_ctx_get_stable_pstate(ctx, ¤t_stable_pstate); +- if (r) +- return r; +- +- if (mgr->adev->pm.stable_pstate_ctx) +- ctx->stable_pstate = mgr->adev->pm.stable_pstate_ctx->stable_pstate; +- else +- ctx->stable_pstate = current_stable_pstate; ++ ctx->stable_pstate = AMDGPU_CTX_STABLE_PSTATE_NONE; + + ctx->ctx_mgr = &(fpriv->ctx_mgr); + return 0; + } + +-static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx, +- u32 stable_pstate) ++static int __amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx, ++ u32 stable_pstate) + { + struct amdgpu_device *adev = ctx->mgr->adev; + enum amd_dpm_forced_level level; ++ struct amdgpu_ctx *current_ctx; + u32 current_stable_pstate; +- int r; +- +- mutex_lock(&adev->pm.stable_pstate_ctx_lock); +- if (adev->pm.stable_pstate_ctx && adev->pm.stable_pstate_ctx != ctx) { +- r = -EBUSY; +- goto done; +- } ++ int r = 0; + +- r = amdgpu_ctx_get_stable_pstate(ctx, ¤t_stable_pstate); +- if (r || (stable_pstate == current_stable_pstate)) +- goto done; ++ lockdep_assert_held(&adev->pm.stable_pstate_ctx_lock); + + switch (stable_pstate) { + case AMDGPU_CTX_STABLE_PSTATE_NONE: +@@ -388,17 +372,41 @@ static int amdgpu_ctx_set_stable_pstate( + level = AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; + break; + default: +- r = -EINVAL; +- goto done; ++ return -EINVAL; + } + ++ current_ctx = adev->pm.stable_pstate_ctx; ++ if (current_ctx && current_ctx != ctx) ++ return -EBUSY; ++ ++ r = amdgpu_ctx_get_stable_pstate(ctx, ¤t_stable_pstate); ++ if (r || current_stable_pstate == stable_pstate) ++ return r; ++ + r = amdgpu_dpm_force_performance_level(adev, level); ++ if (r) ++ return r; + +- if (level == AMD_DPM_FORCED_LEVEL_AUTO) +- adev->pm.stable_pstate_ctx = NULL; +- else ++ if (!current_ctx) { + adev->pm.stable_pstate_ctx = ctx; +-done: ++ /* ++ * Serialized by context taking ownership for the first time ++ * while holding adev->pm.stable_pstate_ctx_lock). ++ */ ++ WRITE_ONCE(ctx->stable_pstate, current_stable_pstate); ++ } ++ ++ return 0; ++} ++ ++static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx, ++ u32 stable_pstate) ++{ ++ struct amdgpu_device *adev = ctx->mgr->adev; ++ int r; ++ ++ mutex_lock(&adev->pm.stable_pstate_ctx_lock); ++ r = __amdgpu_ctx_set_stable_pstate(ctx, stable_pstate); + mutex_unlock(&adev->pm.stable_pstate_ctx_lock); + + return r; +@@ -424,7 +432,12 @@ static void amdgpu_ctx_fini(struct kref + } + + if (drm_dev_enter(adev_to_drm(adev), &idx)) { +- amdgpu_ctx_set_stable_pstate(ctx, ctx->stable_pstate); ++ mutex_lock(&adev->pm.stable_pstate_ctx_lock); ++ if (adev->pm.stable_pstate_ctx == ctx) { ++ __amdgpu_ctx_set_stable_pstate(ctx, ctx->stable_pstate); ++ adev->pm.stable_pstate_ctx = NULL; ++ } ++ mutex_unlock(&adev->pm.stable_pstate_ctx_lock); + drm_dev_exit(idx); + } + diff --git a/queue-6.18/drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch b/queue-6.18/drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch new file mode 100644 index 0000000000..b098cb0794 --- /dev/null +++ b/queue-6.18/drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch @@ -0,0 +1,75 @@ +From stable+bounces-294145-greg=kroah.com@vger.kernel.org Fri Jul 31 18:46:30 2026 +From: Sasha Levin +Date: Fri, 31 Jul 2026 12:25:27 -0400 +Subject: drm/amdgpu: Respect placement requirements in amdgpu_gtt_mgr functions +To: stable@vger.kernel.org +Cc: "Timur Kristóf" , "Christian König" , "Alex Deucher" , "Sasha Levin" +Message-ID: <20260731162527.789626-1-sashal@kernel.org> + +From: Timur Kristóf + +[ Upstream commit 8882f8897e554053af9e72f4c2da8b1e2cce56c7 ] + +When testing intersection and compatibility, respect +the actual placement requirements. This is a pre-requisite +for ensuring that UVD CS BOs do not cross 256M segments. + +Fixes: ded910f368a5 ("drm/amdgpu: Implement intersect/compatible functions") +Suggested-by: Christian König +Signed-off-by: Timur Kristóf +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +(cherry picked from commit bc06579ca29dee9c245a41b12e39c7bb6938af5d) +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 30 ++++++++++++++++++++++++++-- + 1 file changed, 28 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +@@ -217,7 +217,20 @@ static bool amdgpu_gtt_mgr_intersects(st + const struct ttm_place *place, + size_t size) + { +- return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res); ++ const struct drm_mm_node *const node = &to_ttm_range_mgr_node(res)->mm_nodes[0]; ++ const u32 num_pages = PFN_UP(size); ++ ++ if (!place->lpfn) ++ return true; ++ ++ if (!amdgpu_gtt_mgr_has_gart_addr(res)) ++ return false; ++ ++ if (place->fpfn >= (node->start + num_pages) || ++ (place->lpfn && place->lpfn <= node->start)) ++ return false; ++ ++ return true; + } + + /** +@@ -235,7 +248,20 @@ static bool amdgpu_gtt_mgr_compatible(st + const struct ttm_place *place, + size_t size) + { +- return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res); ++ const struct drm_mm_node *const node = &to_ttm_range_mgr_node(res)->mm_nodes[0]; ++ const u32 num_pages = PFN_UP(size); ++ ++ if (!place->lpfn) ++ return true; ++ ++ if (!amdgpu_gtt_mgr_has_gart_addr(res)) ++ return false; ++ ++ if (node->start < place->fpfn || ++ (place->lpfn && (node->start + num_pages) > place->lpfn)) ++ return false; ++ ++ return true; + } + + /** diff --git a/queue-6.18/drm-fb-helper-allocate-and-release-fb_info-in-single-place.patch b/queue-6.18/drm-fb-helper-allocate-and-release-fb_info-in-single-place.patch new file mode 100644 index 0000000000..b1a2ab0ab6 --- /dev/null +++ b/queue-6.18/drm-fb-helper-allocate-and-release-fb_info-in-single-place.patch @@ -0,0 +1,526 @@ +From stable+bounces-293912-greg=kroah.com@vger.kernel.org Fri Jul 31 04:41:37 2026 +From: Sasha Levin +Date: Thu, 30 Jul 2026 22:41:00 -0400 +Subject: drm/fb-helper: Allocate and release fb_info in single place +To: stable@vger.kernel.org +Cc: "Thomas Zimmermann" , "Christian König" , "Dmitry Baryshkov" , "Javier Martinez Canillas" , "Sasha Levin" +Message-ID: <20260731024101.3339564-1-sashal@kernel.org> + +From: Thomas Zimmermann + +[ Upstream commit 63c971af40365ee706c7e24f6a7900d693518f09 ] + +Move the calls to drm_fb_helper_alloc_info() from drivers into a +single place in fbdev helpers. Allocates struct fb_info for a new +framebuffer device. Then call drm_fb_helper_single_fb_probe() to +create an fbdev screen buffer. Also release the instance on errors +by calling drm_fb_helper_release_info(). + +Simplifies the code and fixes the error cleanup for some of the +drivers. + +Regular release of the struct fb_info instance still happens in +drm_fb_helper_fini() as before. + +v2: +- remove error rollback in driver implementations (kernel test robot) +- initialize info in TTM implementation (kernel test robot) + +Signed-off-by: Thomas Zimmermann +Acked-by: Christian König # radeon +Acked-by: Dmitry Baryshkov # msm +Acked-by: Javier Martinez Canillas +Link: https://patch.msgid.link/20251027081245.80262-1-tzimmermann@suse.de +Stable-dep-of: a18b6e30ecd6 ("drm/tegra: fbdev: Remove offset into framebuffer memory") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/armada/armada_fbdev.c | 12 -------- + drivers/gpu/drm/drm_fb_helper.c | 39 ++++++++--------------------- + drivers/gpu/drm/drm_fbdev_dma.c | 12 +------- + drivers/gpu/drm/drm_fbdev_shmem.c | 12 +------- + drivers/gpu/drm/drm_fbdev_ttm.c | 12 +------- + drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 9 ------ + drivers/gpu/drm/gma500/fbdev.c | 12 -------- + drivers/gpu/drm/i915/display/intel_fbdev.c | 9 ------ + drivers/gpu/drm/msm/msm_fbdev.c | 9 ------ + drivers/gpu/drm/omapdrm/omap_fbdev.c | 9 ------ + drivers/gpu/drm/radeon/radeon_fbdev.c | 13 --------- + drivers/gpu/drm/tegra/fbdev.c | 9 ------ + include/drm/drm_fb_helper.h | 12 -------- + 13 files changed, 26 insertions(+), 143 deletions(-) + +--- a/drivers/gpu/drm/armada/armada_fbdev.c ++++ b/drivers/gpu/drm/armada/armada_fbdev.c +@@ -45,10 +45,10 @@ int armada_fbdev_driver_fbdev_probe(stru + struct drm_fb_helper_surface_size *sizes) + { + struct drm_device *dev = fbh->dev; ++ struct fb_info *info = fbh->info; + struct drm_mode_fb_cmd2 mode; + struct armada_framebuffer *dfb; + struct armada_gem_object *obj; +- struct fb_info *info; + int size, ret; + void *ptr; + +@@ -92,12 +92,6 @@ int armada_fbdev_driver_fbdev_probe(stru + if (IS_ERR(dfb)) + return PTR_ERR(dfb); + +- info = drm_fb_helper_alloc_info(fbh); +- if (IS_ERR(info)) { +- ret = PTR_ERR(info); +- goto err_fballoc; +- } +- + info->fbops = &armada_fb_ops; + info->fix.smem_start = obj->phys_addr; + info->fix.smem_len = obj->obj.size; +@@ -113,8 +107,4 @@ int armada_fbdev_driver_fbdev_probe(stru + (unsigned long long)obj->phys_addr); + + return 0; +- +- err_fballoc: +- dfb->fb.funcs->destroy(&dfb->fb); +- return ret; + } +--- a/drivers/gpu/drm/drm_fb_helper.c ++++ b/drivers/gpu/drm/drm_fb_helper.c +@@ -489,20 +489,7 @@ int drm_fb_helper_init(struct drm_device + } + EXPORT_SYMBOL(drm_fb_helper_init); + +-/** +- * drm_fb_helper_alloc_info - allocate fb_info and some of its members +- * @fb_helper: driver-allocated fbdev helper +- * +- * A helper to alloc fb_info and the member cmap. Called by the driver +- * within the struct &drm_driver.fbdev_probe callback function. Drivers do +- * not need to release the allocated fb_info structure themselves, this is +- * automatically done when calling drm_fb_helper_fini(). +- * +- * RETURNS: +- * fb_info pointer if things went okay, pointer containing error code +- * otherwise +- */ +-struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper) ++static struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper) + { + struct device *dev = fb_helper->dev->dev; + struct fb_info *info; +@@ -529,17 +516,8 @@ err_release: + framebuffer_release(info); + return ERR_PTR(ret); + } +-EXPORT_SYMBOL(drm_fb_helper_alloc_info); + +-/** +- * drm_fb_helper_release_info - release fb_info and its members +- * @fb_helper: driver-allocated fbdev helper +- * +- * A helper to release fb_info and the member cmap. Drivers do not +- * need to release the allocated fb_info structure themselves, this is +- * automatically done when calling drm_fb_helper_fini(). +- */ +-void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper) ++static void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper) + { + struct fb_info *info = fb_helper->info; + +@@ -552,7 +530,6 @@ void drm_fb_helper_release_info(struct d + fb_dealloc_cmap(&info->cmap); + framebuffer_release(info); + } +-EXPORT_SYMBOL(drm_fb_helper_release_info); + + /** + * drm_fb_helper_unregister_info - unregister fb_info framebuffer device +@@ -1813,6 +1790,11 @@ __drm_fb_helper_initial_config_and_unloc + height = dev->mode_config.max_height; + + drm_client_modeset_probe(&fb_helper->client, width, height); ++ ++ info = drm_fb_helper_alloc_info(fb_helper); ++ if (IS_ERR(info)) ++ return PTR_ERR(info); ++ + ret = drm_fb_helper_single_fb_probe(fb_helper); + if (ret < 0) { + if (ret == -EAGAIN) { +@@ -1821,13 +1803,12 @@ __drm_fb_helper_initial_config_and_unloc + } + mutex_unlock(&fb_helper->lock); + +- return ret; ++ goto err_drm_fb_helper_release_info; + } + drm_setup_crtcs_fb(fb_helper); + + fb_helper->deferred_setup = false; + +- info = fb_helper->info; + info->var.pixclock = 0; + + /* Need to drop locks to avoid recursive deadlock in +@@ -1850,6 +1831,10 @@ __drm_fb_helper_initial_config_and_unloc + mutex_unlock(&kernel_fb_helper_lock); + + return 0; ++ ++err_drm_fb_helper_release_info: ++ drm_fb_helper_release_info(fb_helper); ++ return ret; + } + + /** +--- a/drivers/gpu/drm/drm_fbdev_dma.c ++++ b/drivers/gpu/drm/drm_fbdev_dma.c +@@ -272,9 +272,9 @@ int drm_fbdev_dma_driver_fbdev_probe(str + { + struct drm_client_dev *client = &fb_helper->client; + struct drm_device *dev = fb_helper->dev; ++ struct fb_info *info = fb_helper->info; + struct drm_client_buffer *buffer; + struct drm_framebuffer *fb; +- struct fb_info *info; + u32 format; + struct iosys_map map; + int ret; +@@ -304,12 +304,6 @@ int drm_fbdev_dma_driver_fbdev_probe(str + fb_helper->buffer = buffer; + fb_helper->fb = fb; + +- info = drm_fb_helper_alloc_info(fb_helper); +- if (IS_ERR(info)) { +- ret = PTR_ERR(info); +- goto err_drm_client_buffer_vunmap; +- } +- + drm_fb_helper_fill_info(info, fb_helper, sizes); + + if (fb->funcs->dirty) +@@ -317,12 +311,10 @@ int drm_fbdev_dma_driver_fbdev_probe(str + else + ret = drm_fbdev_dma_driver_fbdev_probe_tail(fb_helper, sizes); + if (ret) +- goto err_drm_fb_helper_release_info; ++ goto err_drm_client_buffer_vunmap; + + return 0; + +-err_drm_fb_helper_release_info: +- drm_fb_helper_release_info(fb_helper); + err_drm_client_buffer_vunmap: + fb_helper->fb = NULL; + fb_helper->buffer = NULL; +--- a/drivers/gpu/drm/drm_fbdev_shmem.c ++++ b/drivers/gpu/drm/drm_fbdev_shmem.c +@@ -136,10 +136,10 @@ int drm_fbdev_shmem_driver_fbdev_probe(s + { + struct drm_client_dev *client = &fb_helper->client; + struct drm_device *dev = fb_helper->dev; ++ struct fb_info *info = fb_helper->info; + struct drm_client_buffer *buffer; + struct drm_gem_shmem_object *shmem; + struct drm_framebuffer *fb; +- struct fb_info *info; + u32 format; + struct iosys_map map; + int ret; +@@ -169,12 +169,6 @@ int drm_fbdev_shmem_driver_fbdev_probe(s + fb_helper->buffer = buffer; + fb_helper->fb = fb; + +- info = drm_fb_helper_alloc_info(fb_helper); +- if (IS_ERR(info)) { +- ret = PTR_ERR(info); +- goto err_drm_client_buffer_vunmap; +- } +- + drm_fb_helper_fill_info(info, fb_helper, sizes); + + info->fbops = &drm_fbdev_shmem_fb_ops; +@@ -195,12 +189,10 @@ int drm_fbdev_shmem_driver_fbdev_probe(s + info->fbdefio = &fb_helper->fbdefio; + ret = fb_deferred_io_init(info); + if (ret) +- goto err_drm_fb_helper_release_info; ++ goto err_drm_client_buffer_vunmap; + + return 0; + +-err_drm_fb_helper_release_info: +- drm_fb_helper_release_info(fb_helper); + err_drm_client_buffer_vunmap: + fb_helper->fb = NULL; + fb_helper->buffer = NULL; +--- a/drivers/gpu/drm/drm_fbdev_ttm.c ++++ b/drivers/gpu/drm/drm_fbdev_ttm.c +@@ -176,8 +176,8 @@ int drm_fbdev_ttm_driver_fbdev_probe(str + { + struct drm_client_dev *client = &fb_helper->client; + struct drm_device *dev = fb_helper->dev; ++ struct fb_info *info = fb_helper->info; + struct drm_client_buffer *buffer; +- struct fb_info *info; + size_t screen_size; + void *screen_buffer; + u32 format; +@@ -205,12 +205,6 @@ int drm_fbdev_ttm_driver_fbdev_probe(str + goto err_drm_client_framebuffer_delete; + } + +- info = drm_fb_helper_alloc_info(fb_helper); +- if (IS_ERR(info)) { +- ret = PTR_ERR(info); +- goto err_vfree; +- } +- + drm_fb_helper_fill_info(info, fb_helper, sizes); + + info->fbops = &drm_fbdev_ttm_fb_ops; +@@ -227,12 +221,10 @@ int drm_fbdev_ttm_driver_fbdev_probe(str + info->fbdefio = &fb_helper->fbdefio; + ret = fb_deferred_io_init(info); + if (ret) +- goto err_drm_fb_helper_release_info; ++ goto err_vfree; + + return 0; + +-err_drm_fb_helper_release_info: +- drm_fb_helper_release_info(fb_helper); + err_vfree: + vfree(screen_buffer); + err_drm_client_framebuffer_delete: +--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +@@ -59,18 +59,11 @@ static int exynos_drm_fbdev_update(struc + struct drm_fb_helper_surface_size *sizes, + struct exynos_drm_gem *exynos_gem) + { +- struct fb_info *fbi; ++ struct fb_info *fbi = helper->info; + struct drm_framebuffer *fb = helper->fb; + unsigned int size = fb->width * fb->height * fb->format->cpp[0]; + unsigned long offset; + +- fbi = drm_fb_helper_alloc_info(helper); +- if (IS_ERR(fbi)) { +- DRM_DEV_ERROR(to_dma_dev(helper->dev), +- "failed to allocate fb info.\n"); +- return PTR_ERR(fbi); +- } +- + fbi->fbops = &exynos_drm_fb_ops; + + drm_fb_helper_fill_info(fbi, helper, sizes); +--- a/drivers/gpu/drm/gma500/fbdev.c ++++ b/drivers/gpu/drm/gma500/fbdev.c +@@ -111,7 +111,7 @@ int psb_fbdev_driver_fbdev_probe(struct + struct drm_device *dev = fb_helper->dev; + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + struct pci_dev *pdev = to_pci_dev(dev->dev); +- struct fb_info *info; ++ struct fb_info *info = fb_helper->info; + struct drm_framebuffer *fb; + struct drm_mode_fb_cmd2 mode_cmd = { }; + int size; +@@ -170,12 +170,6 @@ int psb_fbdev_driver_fbdev_probe(struct + fb_helper->funcs = &psb_fbdev_fb_helper_funcs; + fb_helper->fb = fb; + +- info = drm_fb_helper_alloc_info(fb_helper); +- if (IS_ERR(info)) { +- ret = PTR_ERR(info); +- goto err_drm_framebuffer_unregister_private; +- } +- + info->fbops = &psb_fbdev_fb_ops; + + /* Accessed stolen memory directly */ +@@ -199,10 +193,6 @@ int psb_fbdev_driver_fbdev_probe(struct + + return 0; + +-err_drm_framebuffer_unregister_private: +- drm_framebuffer_unregister_private(fb); +- drm_framebuffer_cleanup(fb); +- kfree(fb); + err_drm_gem_object_put: + drm_gem_object_put(obj); + return ret; +--- a/drivers/gpu/drm/i915/display/intel_fbdev.c ++++ b/drivers/gpu/drm/i915/display/intel_fbdev.c +@@ -242,8 +242,8 @@ int intel_fbdev_driver_fbdev_probe(struc + struct intel_display *display = to_intel_display(helper->dev); + struct intel_fbdev *ifbdev = to_intel_fbdev(helper); + struct intel_framebuffer *fb = ifbdev->fb; ++ struct fb_info *info = helper->info; + struct ref_tracker *wakeref; +- struct fb_info *info; + struct i915_vma *vma; + unsigned long flags = 0; + bool prealloc = false; +@@ -296,13 +296,6 @@ int intel_fbdev_driver_fbdev_probe(struc + goto out_unlock; + } + +- info = drm_fb_helper_alloc_info(helper); +- if (IS_ERR(info)) { +- drm_err(display->drm, "Failed to allocate fb_info (%pe)\n", info); +- ret = PTR_ERR(info); +- goto out_unpin; +- } +- + helper->funcs = &intel_fb_helper_funcs; + helper->fb = &fb->base; + +--- a/drivers/gpu/drm/msm/msm_fbdev.c ++++ b/drivers/gpu/drm/msm/msm_fbdev.c +@@ -93,9 +93,9 @@ int msm_fbdev_driver_fbdev_probe(struct + { + struct drm_device *dev = helper->dev; + struct msm_drm_private *priv = dev->dev_private; ++ struct fb_info *fbi = helper->info; + struct drm_framebuffer *fb = NULL; + struct drm_gem_object *bo; +- struct fb_info *fbi = NULL; + uint64_t paddr; + uint32_t format; + int ret, pitch; +@@ -128,13 +128,6 @@ int msm_fbdev_driver_fbdev_probe(struct + goto fail; + } + +- fbi = drm_fb_helper_alloc_info(helper); +- if (IS_ERR(fbi)) { +- DRM_DEV_ERROR(dev->dev, "failed to allocate fb info\n"); +- ret = PTR_ERR(fbi); +- goto fail; +- } +- + DBG("fbi=%p, dev=%p", fbi, dev); + + helper->funcs = &msm_fbdev_helper_funcs; +--- a/drivers/gpu/drm/omapdrm/omap_fbdev.c ++++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c +@@ -155,9 +155,9 @@ int omap_fbdev_driver_fbdev_probe(struct + struct drm_device *dev = helper->dev; + struct omap_drm_private *priv = dev->dev_private; + struct omap_fbdev *fbdev = priv->fbdev; ++ struct fb_info *fbi = helper->info; + struct drm_framebuffer *fb = NULL; + union omap_gem_size gsize; +- struct fb_info *fbi = NULL; + struct drm_mode_fb_cmd2 mode_cmd = {0}; + struct drm_gem_object *bo; + dma_addr_t dma_addr; +@@ -226,13 +226,6 @@ int omap_fbdev_driver_fbdev_probe(struct + goto fail; + } + +- fbi = drm_fb_helper_alloc_info(helper); +- if (IS_ERR(fbi)) { +- dev_err(dev->dev, "failed to allocate fb info\n"); +- ret = PTR_ERR(fbi); +- goto fail; +- } +- + DBG("fbi=%p, dev=%p", fbi, dev); + + helper->funcs = &omap_fbdev_helper_funcs; +--- a/drivers/gpu/drm/radeon/radeon_fbdev.c ++++ b/drivers/gpu/drm/radeon/radeon_fbdev.c +@@ -206,7 +206,7 @@ int radeon_fbdev_driver_fbdev_probe(stru + struct radeon_device *rdev = fb_helper->dev->dev_private; + const struct drm_format_info *format_info; + struct drm_mode_fb_cmd2 mode_cmd = { }; +- struct fb_info *info; ++ struct fb_info *info = fb_helper->info; + struct drm_gem_object *gobj; + struct radeon_bo *rbo; + struct drm_framebuffer *fb; +@@ -247,13 +247,6 @@ int radeon_fbdev_driver_fbdev_probe(stru + fb_helper->funcs = &radeon_fbdev_fb_helper_funcs; + fb_helper->fb = fb; + +- /* okay we have an object now allocate the framebuffer */ +- info = drm_fb_helper_alloc_info(fb_helper); +- if (IS_ERR(info)) { +- ret = PTR_ERR(info); +- goto err_drm_framebuffer_unregister_private; +- } +- + info->fbops = &radeon_fbdev_fb_ops; + + /* radeon resume is fragile and needs a vt switch to help it along */ +@@ -279,10 +272,6 @@ int radeon_fbdev_driver_fbdev_probe(stru + + return 0; + +-err_drm_framebuffer_unregister_private: +- fb_helper->fb = NULL; +- drm_framebuffer_unregister_private(fb); +- drm_framebuffer_cleanup(fb); + err_kfree: + kfree(fb); + err_radeon_fbdev_destroy_pinned_object: +--- a/drivers/gpu/drm/tegra/fbdev.c ++++ b/drivers/gpu/drm/tegra/fbdev.c +@@ -75,10 +75,10 @@ int tegra_fbdev_driver_fbdev_probe(struc + struct tegra_drm *tegra = helper->dev->dev_private; + struct drm_device *drm = helper->dev; + struct drm_mode_fb_cmd2 cmd = { 0 }; ++ struct fb_info *info = helper->info; + unsigned int bytes_per_pixel; + struct drm_framebuffer *fb; + unsigned long offset; +- struct fb_info *info; + struct tegra_bo *bo; + size_t size; + int err; +@@ -99,13 +99,6 @@ int tegra_fbdev_driver_fbdev_probe(struc + if (IS_ERR(bo)) + return PTR_ERR(bo); + +- info = drm_fb_helper_alloc_info(helper); +- if (IS_ERR(info)) { +- dev_err(drm->dev, "failed to allocate framebuffer info\n"); +- drm_gem_object_put(&bo->gem); +- return PTR_ERR(info); +- } +- + fb = tegra_fb_alloc(drm, + drm_get_format_info(drm, cmd.pixel_format, cmd.modifier[0]), + &cmd, &bo, 1); +--- a/include/drm/drm_fb_helper.h ++++ b/include/drm/drm_fb_helper.h +@@ -256,8 +256,6 @@ int drm_fb_helper_check_var(struct fb_va + + int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper); + +-struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper); +-void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper); + void drm_fb_helper_unregister_info(struct drm_fb_helper *fb_helper); + void drm_fb_helper_fill_info(struct fb_info *info, + struct drm_fb_helper *fb_helper, +@@ -340,16 +338,6 @@ drm_fb_helper_restore_fbdev_mode_unlocke + return 0; + } + +-static inline struct fb_info * +-drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper) +-{ +- return NULL; +-} +- +-static inline void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper) +-{ +-} +- + static inline void drm_fb_helper_unregister_info(struct drm_fb_helper *fb_helper) + { + } diff --git a/queue-6.18/drm-tegra-fbdev-remove-offset-into-framebuffer-memory.patch b/queue-6.18/drm-tegra-fbdev-remove-offset-into-framebuffer-memory.patch new file mode 100644 index 0000000000..3d6a1fb01b --- /dev/null +++ b/queue-6.18/drm-tegra-fbdev-remove-offset-into-framebuffer-memory.patch @@ -0,0 +1,61 @@ +From stable+bounces-293911-greg=kroah.com@vger.kernel.org Fri Jul 31 04:41:11 2026 +From: Sasha Levin +Date: Thu, 30 Jul 2026 22:41:01 -0400 +Subject: drm/tegra: fbdev: Remove offset into framebuffer memory +To: stable@vger.kernel.org +Cc: Thomas Zimmermann , dri-devel@lists.freedesktop.org, linux-tegra@vger.kernel.org, Thierry Reding , Sasha Levin +Message-ID: <20260731024101.3339564-2-sashal@kernel.org> + +From: Thomas Zimmermann + +[ Upstream commit a18b6e30ecd69096beda4a0c96d2570900c3879a ] + +The screen_buffer field in struct fb_info contains the kernel address +of the first byte of framebuffer memory. Do not add the display offset. +This offset only describes scrolling during scanout. + +Signed-off-by: Thomas Zimmermann +Fixes: de2ba664c30f ("gpu: host1x: drm: Add memory manager and fb") +Cc: dri-devel@lists.freedesktop.org +Cc: linux-tegra@vger.kernel.org +Cc: # v3.10+ +Signed-off-by: Thierry Reding +Link: https://patch.msgid.link/20260421073646.144712-3-tzimmermann@suse.de +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/tegra/fbdev.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/tegra/fbdev.c ++++ b/drivers/gpu/drm/tegra/fbdev.c +@@ -78,7 +78,6 @@ int tegra_fbdev_driver_fbdev_probe(struc + struct fb_info *info = helper->info; + unsigned int bytes_per_pixel; + struct drm_framebuffer *fb; +- unsigned long offset; + struct tegra_bo *bo; + size_t size; + int err; +@@ -118,9 +117,6 @@ int tegra_fbdev_driver_fbdev_probe(struc + + drm_fb_helper_fill_info(info, helper, sizes); + +- offset = info->var.xoffset * bytes_per_pixel + +- info->var.yoffset * fb->pitches[0]; +- + if (bo->pages) { + bo->vaddr = vmap(bo->pages, bo->num_pages, VM_MAP, + pgprot_writecombine(PAGE_KERNEL)); +@@ -132,9 +128,9 @@ int tegra_fbdev_driver_fbdev_probe(struc + } + + info->flags |= FBINFO_VIRTFB; +- info->screen_buffer = bo->vaddr + offset; ++ info->screen_buffer = bo->vaddr; + info->screen_size = size; +- info->fix.smem_start = (unsigned long)(bo->iova + offset); ++ info->fix.smem_start = (unsigned long)(bo->iova); + info->fix.smem_len = size; + + return 0; diff --git a/queue-6.18/drm-xe-guc-fix-buffer-overflow-in-steered-register-list-allocation.patch b/queue-6.18/drm-xe-guc-fix-buffer-overflow-in-steered-register-list-allocation.patch new file mode 100644 index 0000000000..255a76bc41 --- /dev/null +++ b/queue-6.18/drm-xe-guc-fix-buffer-overflow-in-steered-register-list-allocation.patch @@ -0,0 +1,70 @@ +From stable+bounces-294257-greg=kroah.com@vger.kernel.org Sat Aug 1 02:46:58 2026 +From: Sasha Levin +Date: Fri, 31 Jul 2026 20:45:07 -0400 +Subject: drm/xe/guc: Fix buffer overflow in steered register list allocation +To: stable@vger.kernel.org +Cc: Tejas Upadhyay , Zhanjun Dong , Matthew Brost , Sasha Levin +Message-ID: <20260801004507.3661318-1-sashal@kernel.org> + +From: Tejas Upadhyay + +[ Upstream commit 632ecc90e1ca5d3b6822bb4d08f84a175b6c42c0 ] + +The size calculation for the steered register extarray uses only the +geometry DSS mask (g_dss_mask) to determine the number of entries to +allocate: + + total = bitmap_weight(gt->fuse_topo.g_dss_mask, ...) * steer_reg_num; + +However, the filling loop uses for_each_dss_steering(), which iterates +over for_each_dss(), defined as the union of g_dss_mask and c_dss_mask +(geometry + compute DSS). On platforms with compute-only DSS bits, the +loop writes past the allocated buffer, corrupting adjacent slab objects. + +This manifests as list_del corruption and SLUB redzone overwrites during +drm_managed_release on device unbind, since the overflow corrupts the +drmres list_head of neighboring allocations. + +Fix by computing the allocation size using the union of both DSS masks, +matching the iteration pattern of for_each_dss_steering(). + +-- +v2: +- use bitmap_weighted_or() (Zhanjun) + +Fixes: b170d696c1e2 ("drm/xe/guc: Add XE_LP steered register lists") +Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/8049 +Cc: Zhanjun Dong +Cc: stable@vger.kernel.org +Assisted-by: GitHub-Copilot:claude-opus-4.6 +Reviewed-by: Zhanjun Dong +Link: https://patch.msgid.link/20260612070401.543305-2-tejas.upadhyay@intel.com +Signed-off-by: Tejas Upadhyay +(cherry picked from commit 0a78a44f4901aa6c9263e66be7fce02282f1109f) +Signed-off-by: Matthew Brost +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/xe/xe_guc_capture.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/xe/xe_guc_capture.c ++++ b/drivers/gpu/drm/xe/xe_guc_capture.c +@@ -437,8 +437,15 @@ static void guc_capture_alloc_steered_li + if (!list || guc->capture->extlists) + return; + +- total = bitmap_weight(gt->fuse_topo.g_dss_mask, sizeof(gt->fuse_topo.g_dss_mask) * 8) * +- guc_capture_get_steer_reg_num(guc_to_xe(guc)); ++ { ++ xe_dss_mask_t all_dss; ++ ++ bitmap_or(all_dss, gt->fuse_topo.g_dss_mask, gt->fuse_topo.c_dss_mask, ++ XE_MAX_DSS_FUSE_BITS); ++ ++ total = bitmap_weight(all_dss, XE_MAX_DSS_FUSE_BITS) * ++ guc_capture_get_steer_reg_num(guc_to_xe(guc)); ++ } + + if (!total) + return; diff --git a/queue-6.18/series b/queue-6.18/series index 8ffe76d83c..cf76768f2a 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -370,3 +370,8 @@ media-qcom-camss-fix-rdi-streaming-for-csid-340.patch media-uapi-rkisp-correct-name-version-enum.patch wifi-brcmfmac-drain-bus_reset-work-on-device-removal.patch userfaultfd-prevent-registration-of-special-vmas.patch +drm-fb-helper-allocate-and-release-fb_info-in-single-place.patch +drm-tegra-fbdev-remove-offset-into-framebuffer-memory.patch +drm-amdgpu-fix-context-pstate-override-handling.patch +drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch +drm-xe-guc-fix-buffer-overflow-in-steered-register-list-allocation.patch