* [PATCH v5 12/15] drm/damage-helper: Remove old state from drm_atomic_helper_damage_iter_init()
From: Thomas Zimmermann @ 2026-06-10 15:18 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklkml, zack.rusin,
bcm-kernel-feedback-list, harry.wentland, sunpeng.li, siqueira,
alexander.deucher, rodrigo.vivi, joonas.lahtinen, tursulin,
javierm, dmitry.osipenko, gurchetansingh, olvaffe
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, amd-gfx, Thomas Zimmermann, Hamza Mahfooz
In-Reply-To: <20260610152505.260172-1-tzimmermann@suse.de>
Nothing in drm_atomic_helper_damage_iter_init() requires the old
plane state. Remove the parameter and mass-convert callers.
Most callers now no longer require the old plane state in their plane's
atomic_update helper. Remove it as well.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Acked-by: Zack Rusin <zack.rusin@broadcom.com>
Acked-by: Hamza Mahfooz <hamzamahfooz@linux.microsoft.com> # hyperv
---
drivers/gpu/drm/ast/ast_mode.c | 2 +-
drivers/gpu/drm/drm_damage_helper.c | 4 +-
drivers/gpu/drm/drm_fb_dma_helper.c | 2 +-
drivers/gpu/drm/gud/gud_pipe.c | 3 +-
drivers/gpu/drm/hyperv/hyperv_drm_modeset.c | 3 +-
drivers/gpu/drm/mgag200/mgag200_mode.c | 3 +-
drivers/gpu/drm/sitronix/st7571.c | 3 +-
drivers/gpu/drm/sitronix/st7920.c | 3 +-
drivers/gpu/drm/solomon/ssd130x.c | 9 +--
drivers/gpu/drm/sysfb/drm_sysfb_modeset.c | 3 +-
.../gpu/drm/tests/drm_damage_helper_test.c | 55 ++++++-------------
drivers/gpu/drm/tiny/appletbdrm.c | 8 +--
drivers/gpu/drm/tiny/bochs.c | 3 +-
drivers/gpu/drm/tiny/cirrus-qemu.c | 2 +-
drivers/gpu/drm/udl/udl_modeset.c | 3 +-
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 5 +-
include/drm/drm_damage_helper.h | 3 +-
17 files changed, 37 insertions(+), 77 deletions(-)
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index d5ed8c5c7925..6fe3fda6d145 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -579,7 +579,7 @@ static void ast_primary_plane_helper_atomic_update(struct drm_plane *plane,
/* if the buffer comes from another device */
if (drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE) == 0) {
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
ast_handle_damage(ast_plane, shadow_plane_state->data, fb, &damage,
&shadow_plane_state->fmtcnv_state);
diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c
index f492a59edbeb..28f26234523d 100644
--- a/drivers/gpu/drm/drm_damage_helper.c
+++ b/drivers/gpu/drm/drm_damage_helper.c
@@ -209,7 +209,6 @@ EXPORT_SYMBOL(drm_atomic_helper_dirtyfb);
/**
* drm_atomic_helper_damage_iter_init - Initialize the damage iterator.
* @iter: The iterator to initialize.
- * @old_state: Unused, pass NULL.
* @state: Plane state from which to iterate the damage clips.
*
* Initialize an iterator, which clips plane damage
@@ -226,7 +225,6 @@ EXPORT_SYMBOL(drm_atomic_helper_dirtyfb);
*/
void
drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter,
- const struct drm_plane_state *old_state,
const struct drm_plane_state *state)
{
struct drm_rect src;
@@ -324,7 +322,7 @@ bool drm_atomic_helper_damage_merged(const struct drm_plane_state *old_state,
rect->x2 = 0;
rect->y2 = 0;
- drm_atomic_helper_damage_iter_init(&iter, old_state, state);
+ drm_atomic_helper_damage_iter_init(&iter, state);
drm_atomic_for_each_plane_damage(&iter, &clip) {
rect->x1 = min(rect->x1, clip.x1);
rect->y1 = min(rect->y1, clip.y1);
diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c b/drivers/gpu/drm/drm_fb_dma_helper.c
index fd71969d2fb1..bbad16d32b6f 100644
--- a/drivers/gpu/drm/drm_fb_dma_helper.c
+++ b/drivers/gpu/drm/drm_fb_dma_helper.c
@@ -138,7 +138,7 @@ void drm_fb_dma_sync_non_coherent(struct drm_device *drm,
continue;
daddr = drm_fb_dma_get_gem_addr(state->fb, state, i);
- drm_atomic_helper_damage_iter_init(&iter, old_state, state);
+ drm_atomic_helper_damage_iter_init(&iter, state);
drm_atomic_for_each_plane_damage(&iter, &clip) {
/* Ignore x1/x2 values, invalidate complete lines */
diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c
index 5ef887d8485a..758990cd78aa 100644
--- a/drivers/gpu/drm/gud/gud_pipe.c
+++ b/drivers/gpu/drm/gud/gud_pipe.c
@@ -618,7 +618,6 @@ void gud_plane_atomic_update(struct drm_plane *plane,
{
struct drm_device *drm = plane->dev;
struct gud_device *gdrm = to_gud_device(drm);
- struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(atomic_state, plane);
struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(atomic_state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(new_state);
struct drm_framebuffer *fb = new_state->fb;
@@ -647,7 +646,7 @@ void gud_plane_atomic_update(struct drm_plane *plane,
if (ret)
goto out;
- drm_atomic_helper_damage_iter_init(&iter, old_state, new_state);
+ drm_atomic_helper_damage_iter_init(&iter, new_state);
drm_atomic_for_each_plane_damage(&iter, &damage)
gud_fb_handle_damage(gdrm, fb, &shadow_plane_state->data[0], &damage);
diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
index 44425f2d7e04..ee81056e5c53 100644
--- a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
+++ b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
@@ -171,14 +171,13 @@ static void hv_drm_plane_atomic_update(struct drm_plane *plane,
struct drm_atomic_commit *state)
{
struct hv_drm_device *hv = to_hv_drm(plane->dev);
- struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(new_state);
struct drm_rect damage;
struct drm_rect dst_clip;
struct drm_atomic_helper_damage_iter iter;
- drm_atomic_helper_damage_iter_init(&iter, old_state, new_state);
+ drm_atomic_helper_damage_iter_init(&iter, new_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
dst_clip = new_state->dst;
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 7e07fc3f1a60..ea121428adf2 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -503,14 +503,13 @@ void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane,
struct drm_device *dev = plane->dev;
struct mga_device *mdev = to_mga_device(dev);
struct drm_plane_state *plane_state = plane->state;
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(old_state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_framebuffer *fb = plane_state->fb;
struct drm_atomic_helper_damage_iter iter;
struct drm_rect damage;
mgag200_set_datasiz(mdev, fb->format->format);
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
mgag200_handle_damage(mdev, shadow_plane_state->data, fb, &damage);
}
diff --git a/drivers/gpu/drm/sitronix/st7571.c b/drivers/gpu/drm/sitronix/st7571.c
index 20954c33eca9..bc0e59c2600c 100644
--- a/drivers/gpu/drm/sitronix/st7571.c
+++ b/drivers/gpu/drm/sitronix/st7571.c
@@ -342,7 +342,6 @@ static int st7571_primary_plane_helper_atomic_check(struct drm_plane *plane,
static void st7571_primary_plane_helper_atomic_update(struct drm_plane *plane,
struct drm_atomic_commit *state)
{
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_framebuffer *fb = plane_state->fb;
@@ -362,7 +361,7 @@ static void st7571_primary_plane_helper_atomic_update(struct drm_plane *plane,
if (!drm_dev_enter(drm, &idx))
goto out_drm_gem_fb_end_cpu_access;
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
st7571->pformat->prepare_buffer(st7571,
&shadow_plane_state->data[0],
diff --git a/drivers/gpu/drm/sitronix/st7920.c b/drivers/gpu/drm/sitronix/st7920.c
index d320391801f3..7ee45a2b2d3e 100644
--- a/drivers/gpu/drm/sitronix/st7920.c
+++ b/drivers/gpu/drm/sitronix/st7920.c
@@ -390,7 +390,6 @@ static void st7920_primary_plane_atomic_update(struct drm_plane *plane,
struct drm_atomic_commit *state)
{
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
struct st7920_crtc_state *st7920_crtc_state = to_st7920_crtc_state(crtc_state);
@@ -407,7 +406,7 @@ static void st7920_primary_plane_atomic_update(struct drm_plane *plane,
return;
if (drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE) == 0) {
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
dst_clip = plane_state->dst;
diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c
index cae92a3ae8a4..4b55532da31b 100644
--- a/drivers/gpu/drm/solomon/ssd130x.c
+++ b/drivers/gpu/drm/solomon/ssd130x.c
@@ -1198,7 +1198,6 @@ static void ssd130x_primary_plane_atomic_update(struct drm_plane *plane,
struct drm_atomic_commit *state)
{
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
struct ssd130x_crtc_state *ssd130x_crtc_state = to_ssd130x_crtc_state(crtc_state);
@@ -1216,7 +1215,7 @@ static void ssd130x_primary_plane_atomic_update(struct drm_plane *plane,
if (drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE))
goto out_drm_dev_exit;
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
dst_clip = plane_state->dst;
@@ -1239,7 +1238,6 @@ static void ssd132x_primary_plane_atomic_update(struct drm_plane *plane,
struct drm_atomic_commit *state)
{
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
struct ssd130x_crtc_state *ssd130x_crtc_state = to_ssd130x_crtc_state(crtc_state);
@@ -1257,7 +1255,7 @@ static void ssd132x_primary_plane_atomic_update(struct drm_plane *plane,
if (drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE))
goto out_drm_dev_exit;
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
dst_clip = plane_state->dst;
@@ -1280,7 +1278,6 @@ static void ssd133x_primary_plane_atomic_update(struct drm_plane *plane,
struct drm_atomic_commit *state)
{
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
struct ssd130x_crtc_state *ssd130x_crtc_state = to_ssd130x_crtc_state(crtc_state);
@@ -1297,7 +1294,7 @@ static void ssd133x_primary_plane_atomic_update(struct drm_plane *plane,
if (drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE))
goto out_drm_dev_exit;
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
dst_clip = plane_state->dst;
diff --git a/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c b/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c
index d2de29caf89e..9f1ae5ca9a11 100644
--- a/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c
+++ b/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c
@@ -331,7 +331,6 @@ void drm_sysfb_plane_helper_atomic_update(struct drm_plane *plane, struct drm_at
struct drm_device *dev = plane->dev;
struct drm_sysfb_device *sysfb = to_drm_sysfb_device(dev);
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_sysfb_plane_state *sysfb_plane_state = to_drm_sysfb_plane_state(plane_state);
struct drm_shadow_plane_state *shadow_plane_state = &sysfb_plane_state->base;
struct drm_framebuffer *fb = plane_state->fb;
@@ -351,7 +350,7 @@ void drm_sysfb_plane_helper_atomic_update(struct drm_plane *plane, struct drm_at
if (!drm_dev_enter(dev, &idx))
goto out_drm_gem_fb_end_cpu_access;
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
struct iosys_map dst = sysfb->fb_addr;
struct drm_rect dst_clip = plane_state->dst;
diff --git a/drivers/gpu/drm/tests/drm_damage_helper_test.c b/drivers/gpu/drm/tests/drm_damage_helper_test.c
index ef931497baf9..2139ec8b0eb0 100644
--- a/drivers/gpu/drm/tests/drm_damage_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_damage_helper_test.c
@@ -20,7 +20,6 @@ struct drm_damage_mock {
struct drm_property prop;
struct drm_framebuffer fb;
struct drm_plane_state state;
- struct drm_plane_state old_state;
};
static int drm_damage_helper_init(struct kunit *test)
@@ -37,7 +36,6 @@ static int drm_damage_helper_init(struct kunit *test)
mock->state.fb = &mock->fb;
mock->state.visible = true;
- mock->old_state.plane = &mock->plane;
mock->state.plane = &mock->plane;
/* just enough so that drm_plane_enable_fb_damage_clips() works */
@@ -124,9 +122,8 @@ static void drm_test_damage_iter_no_damage(struct kunit *test)
u32 num_hits = 0;
/* Plane src same as fb size. */
- set_plane_src(&mock->old_state, 0, 0, mock->fb.width << 16, mock->fb.height << 16);
set_plane_src(&mock->state, 0, 0, mock->fb.width << 16, mock->fb.height << 16);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -142,11 +139,9 @@ static void drm_test_damage_iter_no_damage_fractional_src(struct kunit *test)
u32 num_hits = 0;
/* Plane src has fractional part. */
- set_plane_src(&mock->old_state, 0x3fffe, 0x3fffe,
- 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
set_plane_src(&mock->state, 0x3fffe, 0x3fffe,
0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -164,9 +159,8 @@ static void drm_test_damage_iter_no_damage_not_visible(struct kunit *test)
mock->state.visible = false;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -182,9 +176,8 @@ static void drm_test_damage_iter_no_damage_no_crtc(struct kunit *test)
mock->state.crtc = NULL;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -200,9 +193,8 @@ static void drm_test_damage_iter_no_damage_no_fb(struct kunit *test)
mock->state.fb = NULL;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -218,13 +210,12 @@ static void drm_test_damage_iter_simple_damage(struct kunit *test)
struct drm_rect clip;
u32 num_hits = 0;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
/* Damage set to plane src */
set_damage_clip(&damage, 0, 0, 1024, 768);
set_damage_blob(&damage_blob, &damage, sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -241,12 +232,11 @@ static void drm_test_damage_iter_single_damage(struct kunit *test)
struct drm_rect clip;
u32 num_hits = 0;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
set_damage_clip(&damage, 256, 192, 768, 576);
set_damage_blob(&damage_blob, &damage, sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -263,13 +253,12 @@ static void drm_test_damage_iter_single_damage_intersect_src(struct kunit *test)
struct drm_rect clip;
u32 num_hits = 0;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
/* Damage intersect with plane src. */
set_damage_clip(&damage, 256, 192, 1360, 768);
set_damage_blob(&damage_blob, &damage, sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -286,13 +275,12 @@ static void drm_test_damage_iter_single_damage_outside_src(struct kunit *test)
struct drm_rect clip;
u32 num_hits = 0;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
/* Damage clip outside plane src */
set_damage_clip(&damage, 1360, 1360, 1380, 1380);
set_damage_blob(&damage_blob, &damage, sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -309,14 +297,12 @@ static void drm_test_damage_iter_single_damage_fractional_src(struct kunit *test
u32 num_hits = 0;
/* Plane src has fractional part. */
- set_plane_src(&mock->old_state, 0x40002, 0x40002,
- 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
set_plane_src(&mock->state, 0x40002, 0x40002,
0x40002 + (1024 << 16), 0x40002 + (768 << 16));
set_damage_clip(&damage, 10, 10, 256, 330);
set_damage_blob(&damage_blob, &damage, sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -334,15 +320,13 @@ static void drm_test_damage_iter_single_damage_intersect_fractional_src(struct k
u32 num_hits = 0;
/* Plane src has fractional part. */
- set_plane_src(&mock->old_state, 0x40002, 0x40002,
- 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
set_plane_src(&mock->state, 0x40002, 0x40002,
0x40002 + (1024 << 16), 0x40002 + (768 << 16));
/* Damage intersect with plane src. */
set_damage_clip(&damage, 10, 1, 1360, 330);
set_damage_blob(&damage_blob, &damage, sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -361,15 +345,13 @@ static void drm_test_damage_iter_single_damage_outside_fractional_src(struct kun
u32 num_hits = 0;
/* Plane src has fractional part. */
- set_plane_src(&mock->old_state, 0x40002, 0x40002,
- 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
set_plane_src(&mock->state, 0x40002, 0x40002,
0x40002 + (1024 << 16), 0x40002 + (768 << 16));
/* Damage clip outside plane src */
set_damage_clip(&damage, 1360, 1360, 1380, 1380);
set_damage_blob(&damage_blob, &damage, sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -385,14 +367,13 @@ static void drm_test_damage_iter_damage(struct kunit *test)
struct drm_rect clip;
u32 num_hits = 0;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
/* 2 damage clips. */
set_damage_clip(&damage[0], 20, 30, 200, 180);
set_damage_clip(&damage[1], 240, 200, 280, 250);
set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip) {
if (num_hits == 0)
check_damage_clip(test, &clip, 20, 30, 200, 180);
@@ -413,8 +394,6 @@ static void drm_test_damage_iter_damage_one_intersect(struct kunit *test)
struct drm_rect clip;
u32 num_hits = 0;
- set_plane_src(&mock->old_state, 0x40002, 0x40002,
- 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
set_plane_src(&mock->state, 0x40002, 0x40002,
0x40002 + (1024 << 16), 0x40002 + (768 << 16));
/* 2 damage clips, one intersect plane src. */
@@ -422,7 +401,7 @@ static void drm_test_damage_iter_damage_one_intersect(struct kunit *test)
set_damage_clip(&damage[1], 2, 2, 1360, 1360);
set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip) {
if (num_hits == 0)
check_damage_clip(test, &clip, 20, 30, 200, 180);
@@ -443,14 +422,13 @@ static void drm_test_damage_iter_damage_one_outside(struct kunit *test)
struct drm_rect clip;
u32 num_hits = 0;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
/* 2 damage clips, one outside plane src. */
set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
set_damage_clip(&damage[1], 240, 200, 280, 250);
set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -467,7 +445,6 @@ static void drm_test_damage_iter_damage_ignore(struct kunit *test)
struct drm_rect clip;
u32 num_hits = 0;
- set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
/* 2 damage clips, but ignore them. */
set_damage_clip(&damage[0], 20, 30, 200, 180);
@@ -475,7 +452,7 @@ static void drm_test_damage_iter_damage_ignore(struct kunit *test)
set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
set_plane_damage(&mock->state, &damage_blob);
mock->state.ignore_damage_clips = true;
- drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_helper_damage_iter_init(&iter, &mock->state);
drm_atomic_for_each_plane_damage(&iter, &clip) {
if (num_hits == 0)
check_damage_clip(test, &clip, 0, 0, 1024, 768);
diff --git a/drivers/gpu/drm/tiny/appletbdrm.c b/drivers/gpu/drm/tiny/appletbdrm.c
index ef71b9957961..eadc3aed7277 100644
--- a/drivers/gpu/drm/tiny/appletbdrm.c
+++ b/drivers/gpu/drm/tiny/appletbdrm.c
@@ -324,7 +324,7 @@ static int appletbdrm_primary_plane_helper_begin_fb_access(struct drm_plane *pla
struct drm_rect damage;
size_t request_size;
- drm_atomic_helper_damage_iter_init(&iter, plane->state, new_plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, new_plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
frames_size += struct_size((struct appletbdrm_frame *)0, buf, rect_size(&damage));
}
@@ -376,7 +376,6 @@ static int appletbdrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
}
static int appletbdrm_flush_damage(struct appletbdrm_device *adev,
- struct drm_plane_state *old_state,
struct drm_plane_state *state)
{
struct appletbdrm_plane_state *appletbdrm_state = to_appletbdrm_plane_state(state);
@@ -412,7 +411,7 @@ static int appletbdrm_flush_damage(struct appletbdrm_device *adev,
frame = (struct appletbdrm_frame *)request->data;
- drm_atomic_helper_damage_iter_init(&iter, old_state, state);
+ drm_atomic_helper_damage_iter_init(&iter, state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
struct drm_rect dst_clip = state->dst;
struct iosys_map dst = IOSYS_MAP_INIT_VADDR(frame->buf);
@@ -479,13 +478,12 @@ static void appletbdrm_primary_plane_helper_atomic_update(struct drm_plane *plan
struct appletbdrm_device *adev = drm_to_adev(plane->dev);
struct drm_device *drm = plane->dev;
struct drm_plane_state *plane_state = plane->state;
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(old_state, plane);
int idx;
if (!drm_dev_enter(drm, &idx))
return;
- appletbdrm_flush_damage(adev, old_plane_state, plane_state);
+ appletbdrm_flush_damage(adev, plane_state);
drm_dev_exit(idx);
}
diff --git a/drivers/gpu/drm/tiny/bochs.c b/drivers/gpu/drm/tiny/bochs.c
index e2d957e51505..1e19e98694c0 100644
--- a/drivers/gpu/drm/tiny/bochs.c
+++ b/drivers/gpu/drm/tiny/bochs.c
@@ -447,7 +447,6 @@ static void bochs_primary_plane_helper_atomic_update(struct drm_plane *plane,
struct drm_device *dev = plane->dev;
struct bochs_device *bochs = to_bochs_device(dev);
struct drm_plane_state *plane_state = plane->state;
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_framebuffer *fb = plane_state->fb;
struct drm_atomic_helper_damage_iter iter;
@@ -456,7 +455,7 @@ static void bochs_primary_plane_helper_atomic_update(struct drm_plane *plane,
if (!fb || !bochs->stride)
return;
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
struct iosys_map dst = IOSYS_MAP_INIT_VADDR_IOMEM(bochs->fb_map);
diff --git a/drivers/gpu/drm/tiny/cirrus-qemu.c b/drivers/gpu/drm/tiny/cirrus-qemu.c
index 075221b431d3..44ffce563e51 100644
--- a/drivers/gpu/drm/tiny/cirrus-qemu.c
+++ b/drivers/gpu/drm/tiny/cirrus-qemu.c
@@ -350,7 +350,7 @@ static void cirrus_primary_plane_helper_atomic_update(struct drm_plane *plane,
if (!old_fb || old_fb->pitches[0] != fb->pitches[0])
cirrus_pitch_set(cirrus, fb->pitches[0]);
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
unsigned int offset = drm_fb_clip_offset(fb->pitches[0], fb->format, &damage);
struct iosys_map dst = IOSYS_MAP_INIT_OFFSET(&vaddr, offset);
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
index 289711035b67..ac981ffca5d9 100644
--- a/drivers/gpu/drm/udl/udl_modeset.c
+++ b/drivers/gpu/drm/udl/udl_modeset.c
@@ -286,7 +286,6 @@ static void udl_primary_plane_helper_atomic_update(struct drm_plane *plane,
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_framebuffer *fb = plane_state->fb;
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_atomic_helper_damage_iter iter;
struct drm_rect damage;
int ret, idx;
@@ -301,7 +300,7 @@ static void udl_primary_plane_helper_atomic_update(struct drm_plane *plane,
if (!drm_dev_enter(dev, &idx))
goto out_drm_gem_fb_end_cpu_access;
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
udl_handle_damage(fb, &shadow_plane_state->data[0], &damage);
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 1b407b61f683..32617eb9538e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1733,7 +1733,6 @@ void vmw_kms_lost_device(struct drm_device *dev)
int vmw_du_helper_plane_update(struct vmw_du_update_plane *update)
{
struct drm_plane_state *state = update->plane->state;
- struct drm_plane_state *old_state = update->old_state;
struct drm_atomic_helper_damage_iter iter;
struct drm_rect clip;
struct drm_rect bb;
@@ -1750,7 +1749,7 @@ int vmw_du_helper_plane_update(struct vmw_du_update_plane *update)
* Iterate in advance to check if really need plane update and find the
* number of clips that actually are in plane src for fifo allocation.
*/
- drm_atomic_helper_damage_iter_init(&iter, old_state, state);
+ drm_atomic_helper_damage_iter_init(&iter, state);
drm_atomic_for_each_plane_damage(&iter, &clip)
num_hits++;
@@ -1818,7 +1817,7 @@ int vmw_du_helper_plane_update(struct vmw_du_update_plane *update)
bb.x2 = INT_MIN;
bb.y2 = INT_MIN;
- drm_atomic_helper_damage_iter_init(&iter, old_state, state);
+ drm_atomic_helper_damage_iter_init(&iter, state);
drm_atomic_for_each_plane_damage(&iter, &clip) {
uint32_t fb_x = clip.x1;
uint32_t fb_y = clip.y1;
diff --git a/include/drm/drm_damage_helper.h b/include/drm/drm_damage_helper.h
index e93eaa0fbcb6..fafe29b50fc6 100644
--- a/include/drm/drm_damage_helper.h
+++ b/include/drm/drm_damage_helper.h
@@ -73,8 +73,7 @@ int drm_atomic_helper_dirtyfb(struct drm_framebuffer *fb,
unsigned int num_clips);
void
drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter,
- const struct drm_plane_state *old_state,
- const struct drm_plane_state *new_state);
+ const struct drm_plane_state *state);
bool
drm_atomic_helper_damage_iter_next(struct drm_atomic_helper_damage_iter *iter,
struct drm_rect *rect);
--
2.54.0
^ permalink raw reply related
* [PATCH v5 07/15] drm/damage-helper: Do not alter damage clips on modeset, but ignore them
From: Thomas Zimmermann @ 2026-06-10 15:18 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklkml, zack.rusin,
bcm-kernel-feedback-list, harry.wentland, sunpeng.li, siqueira,
alexander.deucher, rodrigo.vivi, joonas.lahtinen, tursulin,
javierm, dmitry.osipenko, gurchetansingh, olvaffe
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, amd-gfx, Thomas Zimmermann
In-Reply-To: <20260610152505.260172-1-tzimmermann@suse.de>
User space supplies rectangles for damage clipping in a plane property.
For full mode sets, drivers still require a full plane update. In this
case, leave the information as-is and set the ignore_damage_clips flag
instead. The damage iterator will later ignore any damage information.
Leaving the damage information as-is might be helpful to drivers that
benefit from this information even on full modesets (e.g., for cache
management). It will also help with consolidating the damage-handling
logic.
Also add a new unit test that evaluates the ignore_damage_clips flag. It
sets two damage clips plus the flag and tests if the reported damage
covers the entire framebuffer.
v5:
- clear ignore_damage_clips in a separate patch (Javier)
v4:
- slightly reword the commit description
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Acked-by: Zack Rusin <zack.rusin@broadcom.com>
---
drivers/gpu/drm/drm_damage_helper.c | 6 ++--
.../gpu/drm/tests/drm_damage_helper_test.c | 28 +++++++++++++++++++
2 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c
index 74a7f4252ecf..945fac8dc27b 100644
--- a/drivers/gpu/drm/drm_damage_helper.c
+++ b/drivers/gpu/drm/drm_damage_helper.c
@@ -78,10 +78,8 @@ void drm_atomic_helper_check_plane_damage(struct drm_atomic_commit *state,
if (WARN_ON(!crtc_state))
return;
- if (drm_atomic_crtc_needs_modeset(crtc_state)) {
- drm_property_blob_put(plane_state->fb_damage_clips);
- plane_state->fb_damage_clips = NULL;
- }
+ if (drm_atomic_crtc_needs_modeset(crtc_state))
+ plane_state->ignore_damage_clips = true;
}
}
EXPORT_SYMBOL(drm_atomic_helper_check_plane_damage);
diff --git a/drivers/gpu/drm/tests/drm_damage_helper_test.c b/drivers/gpu/drm/tests/drm_damage_helper_test.c
index 0df2e1a54b0d..64f038a62ffe 100644
--- a/drivers/gpu/drm/tests/drm_damage_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_damage_helper_test.c
@@ -603,6 +603,33 @@ static void drm_test_damage_iter_damage_not_visible(struct kunit *test)
KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should not return any damage.");
}
+static void drm_test_damage_iter_damage_ignore(struct kunit *test)
+{
+ struct drm_damage_mock *mock = test->priv;
+ struct drm_atomic_helper_damage_iter iter;
+ struct drm_property_blob damage_blob;
+ struct drm_mode_rect damage[2];
+ struct drm_rect clip;
+ u32 num_hits = 0;
+
+ set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
+ set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
+ /* 2 damage clips, but ignore them. */
+ set_damage_clip(&damage[0], 20, 30, 200, 180);
+ set_damage_clip(&damage[1], 240, 200, 280, 250);
+ set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
+ set_plane_damage(&mock->state, &damage_blob);
+ mock->state.ignore_damage_clips = true;
+ drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+ drm_atomic_for_each_plane_damage(&iter, &clip) {
+ if (num_hits == 0)
+ check_damage_clip(test, &clip, 0, 0, 1024, 768);
+ num_hits++;
+ }
+
+ KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return full-framebuffer damage.");
+}
+
static struct kunit_case drm_damage_helper_tests[] = {
KUNIT_CASE(drm_test_damage_iter_no_damage),
KUNIT_CASE(drm_test_damage_iter_no_damage_fractional_src),
@@ -625,6 +652,7 @@ static struct kunit_case drm_damage_helper_tests[] = {
KUNIT_CASE(drm_test_damage_iter_damage_one_outside),
KUNIT_CASE(drm_test_damage_iter_damage_src_moved),
KUNIT_CASE(drm_test_damage_iter_damage_not_visible),
+ KUNIT_CASE(drm_test_damage_iter_damage_ignore),
{ }
};
--
2.54.0
^ permalink raw reply related
* [PATCH v5 06/15] drm/damage-helper: Clear ignore_damage_clips in plane-state duplication
From: Thomas Zimmermann @ 2026-06-10 15:18 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklkml, zack.rusin,
bcm-kernel-feedback-list, harry.wentland, sunpeng.li, siqueira,
alexander.deucher, rodrigo.vivi, joonas.lahtinen, tursulin,
javierm, dmitry.osipenko, gurchetansingh, olvaffe
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, amd-gfx, Thomas Zimmermann, stable
In-Reply-To: <20260610152505.260172-1-tzimmermann@suse.de>
Clear ignore_damage_clips when duplicating struct drm_plane_state. The
flag track the state of the damage clips during atomic commits and should
not be kept across plane-state duplications.
Fixes a bug where ignore_damage_clips was not cleared. Once set, the
damage iterator would always ignore damage clips. Only happens in rare
cases in virtgpu and vmwgfx.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Fixes: 35ed38d58257 ("drm: Allow drivers to indicate the damage helpers to ignore damage clips")
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Acked-by: Zack Rusin <zack.rusin@broadcom.com>
Cc: dri-devel@lists.freedesktop.org
Cc: <stable@vger.kernel.org> # v6.10+
---
drivers/gpu/drm/drm_atomic_state_helper.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
index 07686e94aae0..3e26e208e784 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -409,6 +409,7 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
state->fence = NULL;
state->commit = NULL;
state->fb_damage_clips = NULL;
+ state->ignore_damage_clips = false;
state->color_mgmt_changed = false;
}
EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
--
2.54.0
^ permalink raw reply related
* [PATCH v5 05/15] drm/appletbdrm: Allocate request/response buffers in begin_fb_access
From: Thomas Zimmermann @ 2026-06-10 15:18 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklkml, zack.rusin,
bcm-kernel-feedback-list, harry.wentland, sunpeng.li, siqueira,
alexander.deucher, rodrigo.vivi, joonas.lahtinen, tursulin,
javierm, dmitry.osipenko, gurchetansingh, olvaffe
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, amd-gfx, Thomas Zimmermann
In-Reply-To: <20260610152505.260172-1-tzimmermann@suse.de>
In atomic_check, damage handling is not fully evaluated. Another
atomic_check helper could trigger a full modeset and thus invalidate
damage clips.
Allocation of the request/response buffers in appletbdrm depends on
correct damage information. Otherwise it might allocate incorrectly
sized buffers. Allocate the buffers in the driver's begin_fb_access
helper. It runs early during the commit when damage clipping has been
fully evaluated.
v5:
- pass plane state as the old damage-iterator state
v2:
- allocate before drm_gem_begin_shadow_fb_access() to avoid leak on error
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Acked-by: Aditya Garg <gargaditya08@proton.me>
Acked-by: Zack Rusin <zack.rusin@broadcom.com>
---
drivers/gpu/drm/tiny/appletbdrm.c | 53 +++++++++++++++++--------------
1 file changed, 30 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/tiny/appletbdrm.c b/drivers/gpu/drm/tiny/appletbdrm.c
index cdd35af49892..ef71b9957961 100644
--- a/drivers/gpu/drm/tiny/appletbdrm.c
+++ b/drivers/gpu/drm/tiny/appletbdrm.c
@@ -315,33 +315,16 @@ static const u32 appletbdrm_primary_plane_formats[] = {
DRM_FORMAT_XRGB8888, /* emulated */
};
-static int appletbdrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
- struct drm_atomic_commit *state)
+static int appletbdrm_primary_plane_helper_begin_fb_access(struct drm_plane *plane,
+ struct drm_plane_state *new_plane_state)
{
- struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
- struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
- struct drm_crtc *new_crtc = new_plane_state->crtc;
- struct drm_crtc_state *new_crtc_state = NULL;
struct appletbdrm_plane_state *appletbdrm_state = to_appletbdrm_plane_state(new_plane_state);
+ size_t frames_size = 0;
struct drm_atomic_helper_damage_iter iter;
struct drm_rect damage;
- size_t frames_size = 0;
size_t request_size;
- int ret;
-
- if (new_crtc)
- new_crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc);
- ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
- DRM_PLANE_NO_SCALING,
- DRM_PLANE_NO_SCALING,
- false, false);
- if (ret)
- return ret;
- else if (!new_plane_state->visible)
- return 0;
-
- drm_atomic_helper_damage_iter_init(&iter, old_plane_state, new_plane_state);
+ drm_atomic_helper_damage_iter_init(&iter, plane->state, new_plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
frames_size += struct_size((struct appletbdrm_frame *)0, buf, rect_size(&damage));
}
@@ -366,6 +349,29 @@ static int appletbdrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
appletbdrm_state->request_size = request_size;
appletbdrm_state->frames_size = frames_size;
+ return drm_gem_begin_shadow_fb_access(plane, new_plane_state);
+}
+
+static int appletbdrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
+ struct drm_atomic_commit *state)
+{
+ struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
+ struct drm_crtc *new_crtc = new_plane_state->crtc;
+ struct drm_crtc_state *new_crtc_state = NULL;
+ int ret;
+
+ if (new_crtc)
+ new_crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc);
+
+ ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
+ DRM_PLANE_NO_SCALING,
+ DRM_PLANE_NO_SCALING,
+ false, false);
+ if (ret)
+ return ret;
+ else if (!new_plane_state->visible)
+ return 0;
+
return 0;
}
@@ -468,7 +474,7 @@ static int appletbdrm_flush_damage(struct appletbdrm_device *adev,
}
static void appletbdrm_primary_plane_helper_atomic_update(struct drm_plane *plane,
- struct drm_atomic_commit *old_state)
+ struct drm_atomic_commit *old_state)
{
struct appletbdrm_device *adev = drm_to_adev(plane->dev);
struct drm_device *drm = plane->dev;
@@ -552,7 +558,8 @@ static void appletbdrm_primary_plane_destroy_state(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs appletbdrm_primary_plane_helper_funcs = {
- DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
+ .begin_fb_access = appletbdrm_primary_plane_helper_begin_fb_access,
+ .end_fb_access = drm_gem_end_shadow_fb_access,
.atomic_check = appletbdrm_primary_plane_helper_atomic_check,
.atomic_update = appletbdrm_primary_plane_helper_atomic_update,
.atomic_disable = appletbdrm_primary_plane_helper_atomic_disable,
--
2.54.0
^ permalink raw reply related
* [PATCH v5 04/15] drm/vmwgfx: Handle struct drm_plane_state.ignore_damage_clips
From: Thomas Zimmermann @ 2026-06-10 15:18 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklkml, zack.rusin,
bcm-kernel-feedback-list, harry.wentland, sunpeng.li, siqueira,
alexander.deucher, rodrigo.vivi, joonas.lahtinen, tursulin,
javierm, dmitry.osipenko, gurchetansingh, olvaffe
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, amd-gfx, Thomas Zimmermann, Zack Rusin, stable
In-Reply-To: <20260610152505.260172-1-tzimmermann@suse.de>
The mode-setting pipeline can disabled damage clippings for a commit
by setting ignore_damage_clips in struct drm_plane_state. The commit
will then do a full display update.
Test the flag in the primary ldu plane's atomic_update and do a full
update if it has been set.
Commit 35ed38d58257 ("drm: Allow drivers to indicate the damage helpers
to ignore damage clips") introduced ignore_damage_clips to selectively
ignore damage clipping in certain framebuffer changes. Vmwgfx does not
do that, but DRM's damage iterator will soon rely on the flag. Therefore
supporting it here as well make sense for consistency.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Fixes: 35ed38d58257 ("drm: Allow drivers to indicate the damage helpers to ignore damage clips")
Cc: Javier Martinez Canillas <javierm@redhat.com>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Zack Rusin <zackr@vmware.com>
Cc: dri-devel@lists.freedesktop.org
Cc: <stable@vger.kernel.org> # v6.8+
---
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index af3e32174563..40618759c940 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -342,10 +342,15 @@ vmw_ldu_primary_plane_atomic_update(struct drm_plane *plane,
.x2 = vfb->base.width,
.y2 = vfb->base.height
};
- struct drm_mode_rect *damage_rects = drm_plane_get_damage_clips(new_state);
- u32 rect_count = drm_plane_get_damage_clips_count(new_state);
+ struct drm_mode_rect *damage_rects = NULL;
+ u32 rect_count = 0;
int ret;
+ if (!new_state->ignore_damage_clips) {
+ damage_rects = drm_plane_get_damage_clips(new_state);
+ rect_count = drm_plane_get_damage_clips_count(new_state);
+ }
+
if (!damage_rects) {
damage_rects = &fb_rect;
rect_count = 1;
--
2.54.0
^ permalink raw reply related
* [PATCH v5 02/15] drm/i915/display: Handle struct drm_plane_state.ignore_damage_clips
From: Thomas Zimmermann @ 2026-06-10 15:18 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklkml, zack.rusin,
bcm-kernel-feedback-list, harry.wentland, sunpeng.li, siqueira,
alexander.deucher, rodrigo.vivi, joonas.lahtinen, tursulin,
javierm, dmitry.osipenko, gurchetansingh, olvaffe
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, amd-gfx, Thomas Zimmermann, stable, Zack Rusin
In-Reply-To: <20260610152505.260172-1-tzimmermann@suse.de>
The mode-setting pipeline can disabled damage clippings for a commit
by setting ignore_damage_clips in struct drm_plane_state. The commit
will then do a full display update. Commit 35ed38d58257 ("drm: Allow
drivers to indicate the damage helpers to ignore damage clips") introduced
ignore_damage_clips to selectively ignore damage clipping in certain
framebuffer changes.
The i915 driver does not modify the flag, but DRM's damage iterator
will soon rely on it. Calling drm_atomic_helper_check_plane_damage()
right before drm_atomic_helper_damage_merged() guarantees that it
has the correct state. The i915 driver does not do this elsewhere
so far.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Fixes: 35ed38d58257 ("drm: Allow drivers to indicate the damage helpers to ignore damage clips")
Cc: <stable@vger.kernel.org> # v6.4+
Cc: Javier Martinez Canillas <javierm@redhat.com>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Zack Rusin <zackr@vmware.com>
Cc: dri-devel@lists.freedesktop.org
Cc: <stable@vger.kernel.org> # v6.8+
---
drivers/gpu/drm/i915/display/intel_psr.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index e138982dc91f..e4f43eb5bd72 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -3018,6 +3018,9 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
src = drm_plane_state_src(&new_plane_state->uapi);
drm_rect_fp_to_int(&src, &src);
+ /* Prepare plane-damage state before using it */
+ drm_atomic_helper_check_plane_damage(&state->base, &new_plane_state->uapi);
+
if (!drm_atomic_helper_damage_merged(&old_plane_state->uapi,
&new_plane_state->uapi, &damaged_area))
continue;
--
2.54.0
^ permalink raw reply related
* [PATCH v5 03/15] drm/vboxvideo: Handle struct drm_plane_state.ignore_damage_clips
From: Thomas Zimmermann @ 2026-06-10 15:18 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklkml, zack.rusin,
bcm-kernel-feedback-list, harry.wentland, sunpeng.li, siqueira,
alexander.deucher, rodrigo.vivi, joonas.lahtinen, tursulin,
javierm, dmitry.osipenko, gurchetansingh, olvaffe
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, amd-gfx, Thomas Zimmermann, Zack Rusin, stable
In-Reply-To: <20260610152505.260172-1-tzimmermann@suse.de>
The mode-setting pipeline can disabled damage clippings for a commit
by setting ignore_damage_clips in struct drm_plane_state. The commit
will then do a full display update.
Test the flag in the primary plane's atomic_update and do a full update
if it has been set.
Commit 35ed38d58257 ("drm: Allow drivers to indicate the damage helpers
to ignore damage clips") introduced ignore_damage_clips to selectively
ignore damage clipping in certain framebuffer changes. Vboxvideo does not
do that, but DRM's damage iterator will soon rely on the flag. Therefore
supporting it here as well make sense for consistency.
While at it, also replace uint32_t with the preferred u32.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Fixes: 35ed38d58257 ("drm: Allow drivers to indicate the damage helpers to ignore damage clips")
Cc: Javier Martinez Canillas <javierm@redhat.com>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Zack Rusin <zackr@vmware.com>
Cc: dri-devel@lists.freedesktop.org
Cc: <stable@vger.kernel.org> # v6.8+
---
drivers/gpu/drm/vboxvideo/vbox_mode.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/vboxvideo/vbox_mode.c b/drivers/gpu/drm/vboxvideo/vbox_mode.c
index 8e4e5fc9d3c5..635777f1ca23 100644
--- a/drivers/gpu/drm/vboxvideo/vbox_mode.c
+++ b/drivers/gpu/drm/vboxvideo/vbox_mode.c
@@ -283,8 +283,9 @@ static void vbox_primary_atomic_update(struct drm_plane *plane,
struct drm_crtc *crtc = new_state->crtc;
struct drm_framebuffer *fb = new_state->fb;
struct vbox_private *vbox = to_vbox_dev(fb->dev);
- struct drm_mode_rect *clips;
- uint32_t num_clips, i;
+ struct drm_mode_rect *clips = NULL;
+ u32 num_clips = 0;
+ u32 i;
vbox_crtc_set_base_and_mode(crtc, fb,
new_state->src_x >> 16,
@@ -292,8 +293,10 @@ static void vbox_primary_atomic_update(struct drm_plane *plane,
/* Send information about dirty rectangles to VBVA. */
- clips = drm_plane_get_damage_clips(new_state);
- num_clips = drm_plane_get_damage_clips_count(new_state);
+ if (!new_state->ignore_damage_clips) {
+ clips = drm_plane_get_damage_clips(new_state);
+ num_clips = drm_plane_get_damage_clips_count(new_state);
+ }
if (!num_clips)
return;
--
2.54.0
^ permalink raw reply related
* [PATCH v5 00/15] drm: Improve logic behind damage handling
From: Thomas Zimmermann @ 2026-06-10 15:18 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklkml, zack.rusin,
bcm-kernel-feedback-list, harry.wentland, sunpeng.li, siqueira,
alexander.deucher, rodrigo.vivi, joonas.lahtinen, tursulin,
javierm, dmitry.osipenko, gurchetansingh, olvaffe
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, amd-gfx, Thomas Zimmermann
DRM clients can supply information on framebuffer areas to update as
part of each page flip, called damage-clipping rectangles. But DRM's
processing of this information is inconsistent and prone to errors.
- There are multiple fields and tests that decide if damage clips
should be taken or ignored.
- Sometimes damage clips are removed behind the back of the DRM client.
- Atomic helpers evaluate damage clipping in the middle of the atomic
check: after connectors and encoders, but before planes and CRTCs. Hence
pipeline stages have an inconsistent view.
- Which leads to drivers (ingenic) doing a re-evaluation if necessary.
- Tests of plane source coordinates only happen during commits. At this
point, the driver should already know if damage clips are to be taken or
not. Because of this, some drivers (appletbdrm) might operate on incorrect
damage information for their internal workings. This also leads to excessive
use of the old plane state.
Therefore go through DRM helpers and drivers and fix the logic.
- Run all of the atomic checks with the damage information supplied by
DRM clients. Afterwards evaluate plane and CRTC states on whether to
take or ignore damage clips. Do all related tests in a single atomic
helper.
- Do not discard damage clips. Set ignore_damage_clips in struct
drm_plane_state instead. This includes changes to plane source-coordinates.
The damage iterator now only has to look at this flag to detect if it
should use the damage clips.
- Go over drivers and fix the damage handling in the plane's
atomic_update helpers. Most drivers no longer need the old plane state
in their update.
- The appletbdrm driver requires a fix in how it uses damage information.
Ingenic and vmwgfx can be simplified. These changes improve the drivers'
code organization.
- Add support for ignore_damage_clips to various drivers that ignored it
until now.
- Kunit tests require some changes. Drop some obsolete tests and add a new
one for ignore_damage_flags.
Tested with bochs, mgag200, Kunit tests.
v5:
- support ignore_damage_clips in amdgpu, i915, virtgpu, vmwgfx
- reorder patches to avoid possible regressions during the series
- fix clearing ignore_damage_clips in a separate patch (Javier)
v4:
- reorder patches to avoid error-prone intermediate state
v3:
- fix error path in appletbdrm
v2:
- rebase on latest upstream
Thomas Zimmermann (15):
drm/amd/display: Handle struct drm_plane_state.ignore_damage_clips
drm/i915/display: Handle struct drm_plane_state.ignore_damage_clips
drm/vboxvideo: Handle struct drm_plane_state.ignore_damage_clips
drm/vmwgfx: Handle struct drm_plane_state.ignore_damage_clips
drm/appletbdrm: Allocate request/response buffers in begin_fb_access
drm/damage-helper: Clear ignore_damage_clips in plane-state
duplication
drm/damage-helper: Do not alter damage clips on modeset, but ignore
them
drm/atomic-helpers: Evaluate plane damage after atomic_check
drm/ingenic: Remove calls to drm_atomic_helper_check_plane_damage()
drm/atomic_helper: Do not evaluate plane damage before atomic_check
drm/damage-helper: Test src coord in
drm_atomic_helper_check_plane_damage()
drm/damage-helper: Remove old state from
drm_atomic_helper_damage_iter_init()
drm/damage-helper: Remove old state from
drm_atomic_helper_damage_merged()
drm/damage-helper: Rename state parameters in damage helpers
drm/vmwgfx: Remove unused field struct
vmwgfx_du_update_plane.old_state
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 +-
drivers/gpu/drm/ast/ast_cursor.c | 3 +-
drivers/gpu/drm/ast/ast_mode.c | 2 +-
drivers/gpu/drm/drm_atomic_helper.c | 6 +-
drivers/gpu/drm/drm_atomic_state_helper.c | 1 +
drivers/gpu/drm/drm_damage_helper.c | 44 ++--
drivers/gpu/drm/drm_fb_dma_helper.c | 2 +-
drivers/gpu/drm/drm_mipi_dbi.c | 3 +-
drivers/gpu/drm/gud/gud_pipe.c | 3 +-
drivers/gpu/drm/hyperv/hyperv_drm_modeset.c | 3 +-
drivers/gpu/drm/i915/display/intel_plane.c | 11 +-
drivers/gpu/drm/i915/display/intel_psr.c | 8 +-
drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 3 -
drivers/gpu/drm/ingenic/ingenic-ipu.c | 8 +-
drivers/gpu/drm/mgag200/mgag200_mode.c | 3 +-
drivers/gpu/drm/sitronix/st7571.c | 3 +-
drivers/gpu/drm/sitronix/st7586.c | 3 +-
drivers/gpu/drm/sitronix/st7920.c | 3 +-
drivers/gpu/drm/solomon/ssd130x.c | 9 +-
drivers/gpu/drm/sysfb/drm_sysfb_modeset.c | 3 +-
.../gpu/drm/tests/drm_damage_helper_test.c | 200 +++---------------
drivers/gpu/drm/tiny/appletbdrm.c | 59 +++---
drivers/gpu/drm/tiny/bochs.c | 3 +-
drivers/gpu/drm/tiny/cirrus-qemu.c | 2 +-
drivers/gpu/drm/tiny/gm12u320.c | 2 +-
drivers/gpu/drm/tiny/ili9225.c | 3 +-
drivers/gpu/drm/tiny/repaper.c | 2 +-
drivers/gpu/drm/tiny/sharp-memory.c | 3 +-
drivers/gpu/drm/udl/udl_modeset.c | 3 +-
drivers/gpu/drm/vboxvideo/vbox_mode.c | 11 +-
drivers/gpu/drm/virtio/virtgpu_plane.c | 2 +-
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 5 +-
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 2 -
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 9 +-
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 12 +-
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 15 +-
include/drm/drm_damage_helper.h | 9 +-
37 files changed, 148 insertions(+), 325 deletions(-)
base-commit: fc59f76558703febba8056be87d1c97d14f7485e
--
2.54.0
^ permalink raw reply
* [PATCH v5 01/15] drm/amd/display: Handle struct drm_plane_state.ignore_damage_clips
From: Thomas Zimmermann @ 2026-06-10 15:18 UTC (permalink / raw)
To: mripard, maarten.lankhorst, airlied, airlied, simona, admin,
gargaditya08, paul, jani.nikula, mhklkml, zack.rusin,
bcm-kernel-feedback-list, harry.wentland, sunpeng.li, siqueira,
alexander.deucher, rodrigo.vivi, joonas.lahtinen, tursulin,
javierm, dmitry.osipenko, gurchetansingh, olvaffe
Cc: dri-devel, linux-hyperv, intel-gfx, intel-xe, linux-mips,
virtualization, amd-gfx, Thomas Zimmermann, Zack Rusin, stable
In-Reply-To: <20260610152505.260172-1-tzimmermann@suse.de>
The mode-setting pipeline can disabled damage clippings for a commit
by setting ignore_damage_clips in struct drm_plane_state. The commit
will then do a full display update.
Test the flag in DCN code and do a full update in DCN code if it has
been set.
Commit 35ed38d58257 ("drm: Allow drivers to indicate the damage helpers
to ignore damage clips") introduced ignore_damage_clips to selectively
ignore damage clipping in certain framebuffer changes. This driver does
not do that, but DRM's damage iterator will soon rely on the flag.
Therefore supporting it here as well make sense for consistency.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Fixes: 35ed38d58257 ("drm: Allow drivers to indicate the damage helpers to ignore damage clips")
Cc: Javier Martinez Canillas <javierm@redhat.com>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Zack Rusin <zackr@vmware.com>
Cc: dri-devel@lists.freedesktop.org
Cc: <stable@vger.kernel.org> # v6.8+
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 0e20194e6662..4cbb27f65a0b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6614,8 +6614,8 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
{
struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state);
struct rect *dirty_rects = flip_addrs->dirty_rects;
- u32 num_clips;
- struct drm_mode_rect *clips;
+ u32 num_clips = 0;
+ struct drm_mode_rect *clips = NULL;
bool bb_changed;
bool fb_changed;
u32 i = 0;
@@ -6631,8 +6631,10 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
if (new_plane_state->rotation != DRM_MODE_ROTATE_0)
goto ffu;
- num_clips = drm_plane_get_damage_clips_count(new_plane_state);
- clips = drm_plane_get_damage_clips(new_plane_state);
+ if (!new_plane_state->ignore_damage_clips) {
+ num_clips = drm_plane_get_damage_clips_count(new_plane_state);
+ clips = drm_plane_get_damage_clips(new_plane_state);
+ }
if (num_clips && (!amdgpu_damage_clips || (amdgpu_damage_clips < 0 &&
is_psr_su)))
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v3 4/4] scsi: use percpu counters for iostat counters in struct scsi_device
From: Hannes Reinecke @ 2026-06-10 6:21 UTC (permalink / raw)
To: Sumit Saxena, Martin K . Petersen, Jens Axboe
Cc: James E . J . Bottomley, linux-scsi, linux-block, Adam Radford,
Khalid Aziz, Adaptec OEM Raid Solutions, Matthew Wilcox,
Hannes Reinecke, Juergen E . Fischer, Russell King,
linux-arm-kernel, Finn Thain, Michael Schmitz, Anil Gurumurthy,
Sudarsana Kalluru, Oliver Neukum, Ali Akcaagac, Jamie Lenehan,
Ram Vegesna, target-devel, Bradley Grove, Satish Kharat,
Sesidhar Baddela, Karan Tilak Kumar, Yihang Li, Don Brace,
storagedev, HighPoint Linux Team, Tyrel Datwyler,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy, linuxppc-dev, Brian King, Lee Duncan,
Chris Leech, Mike Christie, open-iscsi, Justin Tee, Paul Ely,
Kashyap Desai, Shivasharan S, Chandrakanth Patil,
megaraidlinux.pdl, Sathya Prakash Veerichetty, Sreekanth Reddy,
mpi3mr-linuxdrv.pdl, Suganath Prabu Subramani, Ranjan Kumar,
MPT-FusionLinux.pdl, Daniel Palmer, GOTO Masanori, YOKOTA Hiroshi,
Jack Wang, Geoff Levand, Michael Reed, Nilesh Javali,
GR-QLogic-Storage-Upstream, Narsimhulu Musini, K . Y . Srinivasan,
Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, linux-hyperv,
Michael S . Tsirkin, Jason Wang, Paolo Bonzini, Stefan Hajnoczi,
Eugenio Perez, virtualization, Vishal Bhakta,
bcm-kernel-feedback-list, Juergen Gross, Stefano Stabellini,
Oleksandr Tyshchenko, xen-devel, John Garry
In-Reply-To: <20260609121806.2121755-5-sumit.saxena@broadcom.com>
On 6/9/26 14:18, Sumit Saxena wrote:
> iorequest_cnt and iodone_cnt are updated on every command dispatch and
> completion, often from different CPUs on high queue depth workloads.
> Using adjacent atomic_t fields causes cache line contention between the
> submission and completion paths.
>
> Extend the same treatment to ioerr_cnt and iotmo_cnt so all four iostat
> counters in struct scsi_device use struct percpu_counter.
>
> Suggested-by: John Garry <john.g.garry@oracle.com>
> Signed-off-by: Sumit Saxena <sumit.saxena@broadcom.com>
> ---
> drivers/scsi/scsi_error.c | 4 ++--
> drivers/scsi/scsi_lib.c | 10 +++++-----
> drivers/scsi/scsi_scan.c | 8 ++++++++
> drivers/scsi/scsi_sysfs.c | 23 ++++++++++++++---------
> drivers/scsi/sd.c | 2 +-
> include/scsi/scsi_device.h | 9 +++++----
> 6 files changed, 35 insertions(+), 21 deletions(-)
>
Good idea.
Reviewed-by: Hannes Reinecke <hare@kernel.org>
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare@suse.de +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich
^ permalink raw reply
* Re: [PATCH v3 3/4] block: drop shared-tag fairness throttling
From: Hannes Reinecke @ 2026-06-10 6:18 UTC (permalink / raw)
To: Sumit Saxena, Martin K . Petersen, Jens Axboe
Cc: James E . J . Bottomley, linux-scsi, linux-block, Adam Radford,
Khalid Aziz, Adaptec OEM Raid Solutions, Matthew Wilcox,
Hannes Reinecke, Juergen E . Fischer, Russell King,
linux-arm-kernel, Finn Thain, Michael Schmitz, Anil Gurumurthy,
Sudarsana Kalluru, Oliver Neukum, Ali Akcaagac, Jamie Lenehan,
Ram Vegesna, target-devel, Bradley Grove, Satish Kharat,
Sesidhar Baddela, Karan Tilak Kumar, Yihang Li, Don Brace,
storagedev, HighPoint Linux Team, Tyrel Datwyler,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy, linuxppc-dev, Brian King, Lee Duncan,
Chris Leech, Mike Christie, open-iscsi, Justin Tee, Paul Ely,
Kashyap Desai, Shivasharan S, Chandrakanth Patil,
megaraidlinux.pdl, Sathya Prakash Veerichetty, Sreekanth Reddy,
mpi3mr-linuxdrv.pdl, Suganath Prabu Subramani, Ranjan Kumar,
MPT-FusionLinux.pdl, Daniel Palmer, GOTO Masanori, YOKOTA Hiroshi,
Jack Wang, Geoff Levand, Michael Reed, Nilesh Javali,
GR-QLogic-Storage-Upstream, Narsimhulu Musini, K . Y . Srinivasan,
Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, linux-hyperv,
Michael S . Tsirkin, Jason Wang, Paolo Bonzini, Stefan Hajnoczi,
Eugenio Perez, virtualization, Vishal Bhakta,
bcm-kernel-feedback-list, Juergen Gross, Stefano Stabellini,
Oleksandr Tyshchenko, xen-devel, Bart Van Assche
In-Reply-To: <20260609121806.2121755-4-sumit.saxena@broadcom.com>
On 6/9/26 14:18, Sumit Saxena wrote:
> From: Bart Van Assche <bvanassche@acm.org>
>
> Original patch [1] by Bart Van Assche; this version is rebased onto the
> current tree. In testing it improves IOPS by roughly 16-18% by removing
> the fair-sharing throttle on shared tag queues.
>
> This patch removes the following code and structure members:
> - The function hctx_may_queue().
> - blk_mq_hw_ctx.nr_active and request_queue.nr_active_requests_shared_tags
> and also all the code that modifies these two member variables.
>
> [1]: https://lore.kernel.org/linux-block/20240529213921.3166462-1-bvanassche@acm.org/
>
> Signed-off-by: Bart Van Assche <bvanassche@acm.org>
> Signed-off-by: Sumit Saxena <sumit.saxena@broadcom.com>
> ---
> block/blk-core.c | 2 -
> block/blk-mq-debugfs.c | 22 ++++++++-
> block/blk-mq-tag.c | 4 --
> block/blk-mq.c | 17 +------
> block/blk-mq.h | 100 -----------------------------------------
> include/linux/blk-mq.h | 6 ---
> include/linux/blkdev.h | 2 -
> 7 files changed, 22 insertions(+), 131 deletions(-)
>
What tests did you perform?
I'm pretty sure you see an improvement when having just a few drives,
but what about having a lot of them (ie tens of drives)?
The whole point of this was to increase fairness between drives, so
of course removing it will make an individual drive going faster ...
Maybe it's an idea to move the fairness algorithm into an I/O scheduler;
that way we can keep the original behaviour yet get the performance
increase if people want it.
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare@suse.de +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich
^ permalink raw reply
* Re: [PATCH v3 3/4] block: drop shared-tag fairness throttling
From: Christoph Hellwig @ 2026-06-10 6:14 UTC (permalink / raw)
To: Sumit Saxena
Cc: Martin K . Petersen, Jens Axboe, James E . J . Bottomley,
linux-scsi, linux-block, Adam Radford, Khalid Aziz,
Adaptec OEM Raid Solutions, Matthew Wilcox, Hannes Reinecke,
Juergen E . Fischer, Russell King, linux-arm-kernel, Finn Thain,
Michael Schmitz, Anil Gurumurthy, Sudarsana Kalluru,
Oliver Neukum, Ali Akcaagac, Jamie Lenehan, Ram Vegesna,
target-devel, Bradley Grove, Satish Kharat, Sesidhar Baddela,
Karan Tilak Kumar, Yihang Li, Don Brace, storagedev,
HighPoint Linux Team, Tyrel Datwyler, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Christophe Leroy, linuxppc-dev,
Brian King, Lee Duncan, Chris Leech, Mike Christie, open-iscsi,
Justin Tee, Paul Ely, Kashyap Desai, Shivasharan S,
Chandrakanth Patil, megaraidlinux.pdl, Sathya Prakash Veerichetty,
Sreekanth Reddy, mpi3mr-linuxdrv.pdl, Suganath Prabu Subramani,
Ranjan Kumar, MPT-FusionLinux.pdl, Daniel Palmer, GOTO Masanori,
YOKOTA Hiroshi, Jack Wang, Geoff Levand, Michael Reed,
Nilesh Javali, GR-QLogic-Storage-Upstream, Narsimhulu Musini,
K . Y . Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li,
linux-hyperv, Michael S . Tsirkin, Jason Wang, Paolo Bonzini,
Stefan Hajnoczi, Eugenio Perez, virtualization, Vishal Bhakta,
bcm-kernel-feedback-list, Juergen Gross, Stefano Stabellini,
Oleksandr Tyshchenko, xen-devel, Bart Van Assche
In-Reply-To: <20260609121806.2121755-4-sumit.saxena@broadcom.com>
Just dropping the fairness was rejected before and there is no
explanation here on why any of that has changed.
On Tue, Jun 09, 2026 at 05:48:02PM +0530, Sumit Saxena wrote:
> From: Bart Van Assche <bvanassche@acm.org>
>
> Original patch [1] by Bart Van Assche; this version is rebased onto the
> current tree. In testing it improves IOPS by roughly 16-18% by removing
> the fair-sharing throttle on shared tag queues.
>
> This patch removes the following code and structure members:
> - The function hctx_may_queue().
> - blk_mq_hw_ctx.nr_active and request_queue.nr_active_requests_shared_tags
> and also all the code that modifies these two member variables.
.. and besides that, this commit message is still entirely useless
as it doesn't explain any of the thoughts of why this change is safe
and desirable. While the mechanics above are totally obvious from
the code change itself.
^ permalink raw reply
* Re: [PATCH v3 1/4] scsi: scan: allocate sdev and starget on the NUMA node of the host adapter
From: Hannes Reinecke @ 2026-06-10 6:00 UTC (permalink / raw)
To: Sumit Saxena, Martin K . Petersen, Jens Axboe
Cc: James E . J . Bottomley, linux-scsi, linux-block, Adam Radford,
Khalid Aziz, Adaptec OEM Raid Solutions, Matthew Wilcox,
Juergen E . Fischer, Russell King, linux-arm-kernel, Finn Thain,
Michael Schmitz, Anil Gurumurthy, Sudarsana Kalluru,
Oliver Neukum, Ali Akcaagac, Jamie Lenehan, Ram Vegesna,
target-devel, Bradley Grove, Satish Kharat, Sesidhar Baddela,
Karan Tilak Kumar, Yihang Li, Don Brace, storagedev,
HighPoint Linux Team, Tyrel Datwyler, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Christophe Leroy, linuxppc-dev,
Brian King, Lee Duncan, Chris Leech, Mike Christie, open-iscsi,
Justin Tee, Paul Ely, Kashyap Desai, Shivasharan S,
Chandrakanth Patil, megaraidlinux.pdl, Sathya Prakash Veerichetty,
Sreekanth Reddy, mpi3mr-linuxdrv.pdl, Suganath Prabu Subramani,
Ranjan Kumar, MPT-FusionLinux.pdl, Daniel Palmer, GOTO Masanori,
YOKOTA Hiroshi, Jack Wang, Geoff Levand, Michael Reed,
Nilesh Javali, GR-QLogic-Storage-Upstream, Narsimhulu Musini,
K . Y . Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li,
linux-hyperv, Michael S . Tsirkin, Jason Wang, Paolo Bonzini,
Stefan Hajnoczi, Eugenio Perez, virtualization, Vishal Bhakta,
bcm-kernel-feedback-list, Juergen Gross, Stefano Stabellini,
Oleksandr Tyshchenko, xen-devel, James Rizzo
In-Reply-To: <20260609121806.2121755-2-sumit.saxena@broadcom.com>
On 6/9/26 14:18, Sumit Saxena wrote:
> From: James Rizzo <james.rizzo@broadcom.com>
>
> When a host adapter is attached to a specific NUMA node, allocating
> scsi_device and scsi_target via kzalloc() may place them on a remote
> node. All hot-path I/O accesses to these structures then cross the NUMA
> interconnect, adding latency and consuming inter-node bandwidth.
>
> Use kzalloc_node() with dev_to_node(shost->dma_dev) so allocations land
> on the same node as the HBA, reducing cross-node traffic and improving
> I/O performance on NUMA systems.
>
> Signed-off-by: James Rizzo <james.rizzo@broadcom.com>
> Signed-off-by: Sumit Saxena <sumit.saxena@broadcom.com>
> ---
> drivers/scsi/scsi_scan.c | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
Reviewed-by: Hannes Reinecke <hare@kernel.org>
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare@suse.com +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich
^ permalink raw reply
* Re: [PATCH v3 2/4] scsi: host: allocate struct Scsi_Host on the NUMA node of the host adapter
From: Hannes Reinecke @ 2026-06-10 5:59 UTC (permalink / raw)
To: Sumit Saxena, Martin K . Petersen, Jens Axboe
Cc: James E . J . Bottomley, linux-scsi, linux-block, Adam Radford,
Khalid Aziz, Adaptec OEM Raid Solutions, Matthew Wilcox,
Juergen E . Fischer, Russell King, linux-arm-kernel, Finn Thain,
Michael Schmitz, Anil Gurumurthy, Sudarsana Kalluru,
Oliver Neukum, Ali Akcaagac, Jamie Lenehan, Ram Vegesna,
target-devel, Bradley Grove, Satish Kharat, Sesidhar Baddela,
Karan Tilak Kumar, Yihang Li, Don Brace, storagedev,
HighPoint Linux Team, Tyrel Datwyler, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Christophe Leroy, linuxppc-dev,
Brian King, Lee Duncan, Chris Leech, Mike Christie, open-iscsi,
Justin Tee, Paul Ely, Kashyap Desai, Shivasharan S,
Chandrakanth Patil, megaraidlinux.pdl, Sathya Prakash Veerichetty,
Sreekanth Reddy, mpi3mr-linuxdrv.pdl, Suganath Prabu Subramani,
Ranjan Kumar, MPT-FusionLinux.pdl, Daniel Palmer, GOTO Masanori,
YOKOTA Hiroshi, Jack Wang, Geoff Levand, Michael Reed,
Nilesh Javali, GR-QLogic-Storage-Upstream, Narsimhulu Musini,
K . Y . Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li,
linux-hyperv, Michael S . Tsirkin, Jason Wang, Paolo Bonzini,
Stefan Hajnoczi, Eugenio Perez, virtualization, Vishal Bhakta,
bcm-kernel-feedback-list, Juergen Gross, Stefano Stabellini,
Oleksandr Tyshchenko, xen-devel, John Garry
In-Reply-To: <20260609121806.2121755-3-sumit.saxena@broadcom.com>
On 6/9/26 14:18, Sumit Saxena wrote:
> scsi_host_alloc() used kzalloc(), which always picks an arbitrary node.
> Extend the function to accept a 'struct device *dev' parameter and use
> kzalloc_node() with dev_to_node(dev) so the Scsi_Host struct lands on
> the same NUMA node as the HBA, mirroring the treatment already applied
> to struct scsi_device, struct scsi_target, and shost_data.
>
> When dev is NULL (legacy ISA/platform drivers without a dma_dev) the
> allocation falls back to NUMA_NO_NODE, preserving existing behaviour.
>
> Update all in-tree callers:
> - PCI-based HBA drivers pass &pdev->dev (or the equivalent struct
> member such as &phba->pcidev->dev, &h->pdev->dev, &ha->pdev->dev)
> so their host struct is placed on the adapter's node.
> - Non-PCI drivers (ISA, Amiga, ARM PCMCIA, virtio, Hyper-V, PS3, …)
> pass NULL.
> - libfc's libfc_host_alloc() inline helper passes NULL; FC drivers
> that want NUMA awareness can open-code the call with their pdev.
>
> Suggested-by: John Garry <john.g.garry@oracle.com>
> Signed-off-by: Sumit Saxena <sumit.saxena@broadcom.com>
> ---
> drivers/scsi/3w-9xxx.c | 2 +-
> drivers/scsi/3w-sas.c | 2 +-
> drivers/scsi/3w-xxxx.c | 2 +-
> drivers/scsi/53c700.c | 2 +-
> drivers/scsi/BusLogic.c | 2 +-
> drivers/scsi/a100u2w.c | 2 +-
> drivers/scsi/a2091.c | 2 +-
> drivers/scsi/a3000.c | 2 +-
> drivers/scsi/aacraid/linit.c | 2 +-
> drivers/scsi/advansys.c | 6 +++---
> drivers/scsi/aha152x.c | 2 +-
> drivers/scsi/aha1542.c | 2 +-
> drivers/scsi/aha1740.c | 2 +-
> drivers/scsi/aic7xxx/aic79xx_osm.c | 2 +-
> drivers/scsi/aic7xxx/aic7xxx_osm.c | 2 +-
> drivers/scsi/aic94xx/aic94xx_init.c | 2 +-
> drivers/scsi/am53c974.c | 2 +-
> drivers/scsi/arcmsr/arcmsr_hba.c | 3 ++-
> drivers/scsi/arm/acornscsi.c | 2 +-
> drivers/scsi/arm/arxescsi.c | 2 +-
> drivers/scsi/arm/cumana_1.c | 2 +-
> drivers/scsi/arm/cumana_2.c | 2 +-
> drivers/scsi/arm/eesox.c | 2 +-
> drivers/scsi/arm/oak.c | 2 +-
> drivers/scsi/arm/powertec.c | 2 +-
> drivers/scsi/atari_scsi.c | 2 +-
> drivers/scsi/atp870u.c | 2 +-
> drivers/scsi/bfa/bfad_im.c | 2 +-
> drivers/scsi/csiostor/csio_init.c | 4 ++--
> drivers/scsi/dc395x.c | 2 +-
> drivers/scsi/dmx3191d.c | 2 +-
> drivers/scsi/elx/efct/efct_xport.c | 4 ++--
> drivers/scsi/esas2r/esas2r_main.c | 2 +-
> drivers/scsi/fdomain.c | 2 +-
> drivers/scsi/fnic/fnic_main.c | 2 +-
> drivers/scsi/g_NCR5380.c | 2 +-
> drivers/scsi/gvp11.c | 2 +-
> drivers/scsi/hisi_sas/hisi_sas_main.c | 2 +-
> drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 +-
> drivers/scsi/hosts.c | 6 ++++--
> drivers/scsi/hpsa.c | 2 +-
> drivers/scsi/hptiop.c | 2 +-
> drivers/scsi/ibmvscsi/ibmvfc.c | 2 +-
> drivers/scsi/ibmvscsi/ibmvscsi.c | 2 +-
> drivers/scsi/imm.c | 2 +-
> drivers/scsi/initio.c | 2 +-
> drivers/scsi/ipr.c | 2 +-
> drivers/scsi/ips.c | 2 +-
> drivers/scsi/isci/init.c | 2 +-
> drivers/scsi/jazz_esp.c | 2 +-
> drivers/scsi/libiscsi.c | 2 +-
> drivers/scsi/lpfc/lpfc_init.c | 2 +-
> drivers/scsi/mac53c94.c | 2 +-
> drivers/scsi/mac_esp.c | 2 +-
> drivers/scsi/mac_scsi.c | 2 +-
> drivers/scsi/megaraid.c | 2 +-
> drivers/scsi/megaraid/megaraid_mbox.c | 2 +-
> drivers/scsi/megaraid/megaraid_sas_base.c | 2 +-
> drivers/scsi/mesh.c | 2 +-
> drivers/scsi/mpi3mr/mpi3mr_os.c | 2 +-
> drivers/scsi/mpt3sas/mpt3sas_scsih.c | 4 ++--
> drivers/scsi/mvme147.c | 2 +-
> drivers/scsi/mvsas/mv_init.c | 2 +-
> drivers/scsi/mvumi.c | 2 +-
> drivers/scsi/myrb.c | 2 +-
> drivers/scsi/myrs.c | 2 +-
> drivers/scsi/ncr53c8xx.c | 2 +-
> drivers/scsi/nsp32.c | 2 +-
> drivers/scsi/pcmcia/nsp_cs.c | 2 +-
> drivers/scsi/pcmcia/qlogic_stub.c | 2 +-
> drivers/scsi/pcmcia/sym53c500_cs.c | 2 +-
> drivers/scsi/pm8001/pm8001_init.c | 2 +-
> drivers/scsi/pmcraid.c | 2 +-
> drivers/scsi/ppa.c | 2 +-
> drivers/scsi/ps3rom.c | 2 +-
> drivers/scsi/qla1280.c | 2 +-
> drivers/scsi/qla2xxx/qla_mid.c | 2 +-
> drivers/scsi/qla2xxx/qla_os.c | 2 +-
> drivers/scsi/qlogicfas.c | 2 +-
> drivers/scsi/qlogicpti.c | 2 +-
> drivers/scsi/scsi_debug.c | 2 +-
> drivers/scsi/sgiwd93.c | 2 +-
> drivers/scsi/smartpqi/smartpqi_init.c | 2 +-
> drivers/scsi/snic/snic_main.c | 2 +-
> drivers/scsi/stex.c | 2 +-
> drivers/scsi/storvsc_drv.c | 2 +-
> drivers/scsi/sun3_scsi.c | 2 +-
> drivers/scsi/sun3x_esp.c | 2 +-
> drivers/scsi/sun_esp.c | 2 +-
> drivers/scsi/sym53c8xx_2/sym_glue.c | 2 +-
> drivers/scsi/virtio_scsi.c | 2 +-
> drivers/scsi/vmw_pvscsi.c | 2 +-
> drivers/scsi/wd719x.c | 2 +-
> drivers/scsi/xen-scsifront.c | 2 +-
> drivers/scsi/zorro_esp.c | 2 +-
> include/scsi/libfc.h | 2 +-
> include/scsi/scsi_host.h | 3 ++-
> 97 files changed, 107 insertions(+), 103 deletions(-)
>
Quite a lot of churn for such a (relatively) simple change.
I think it might be better to introduce a new function
(scsi_host_alloc_node() ?) with the additional parameter,
and make scsi_host_alloc() a wrapper around that.
That will reduce the size of this patch immensely.
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare@suse.com +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich
^ permalink raw reply
* Re: [PATCH net-next v2] net: mana: Cache MANA_QUERY_LINK_CONFIG result to avoid repeated HWC queries
From: patchwork-bot+netdevbpf @ 2026-06-10 1:10 UTC (permalink / raw)
To: Erni Sri Satya Vennela
Cc: kys, haiyangz, wei.liu, decui, longli, andrew+netdev, davem,
edumazet, kuba, pabeni, kotaranov, horms, dipayanroy, kees,
linux-hyperv, netdev, linux-kernel, linux-rdma
In-Reply-To: <20260606133301.2180073-1-ernis@linux.microsoft.com>
Hello:
This patch was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Sat, 6 Jun 2026 06:32:55 -0700 you wrote:
> mana_query_link_cfg() sends an HWC command to firmware on every call,
> but the link speed and QoS values it returns only change when the
> driver explicitly calls mana_set_bw_clamp(). This function is called
> not only by userspace via ethtool get_link_ksettings, but also
> periodically by hv_netvsc through netvsc_get_link_ksettings and by
> the sysfs speed_show attribute via dev_attr_show, resulting in
> unnecessary HWC traffic every few minutes.
>
> [...]
Here is the summary with links:
- [net-next,v2] net: mana: Cache MANA_QUERY_LINK_CONFIG result to avoid repeated HWC queries
https://git.kernel.org/netdev/net-next/c/8e0ffcc926f4
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH net-next] net: mana: Add support for PF device 0x00C1
From: patchwork-bot+netdevbpf @ 2026-06-10 1:00 UTC (permalink / raw)
To: Haiyang Zhang
Cc: linux-hyperv, netdev, kys, haiyangz, wei.liu, decui, longli,
andrew+netdev, davem, edumazet, kuba, pabeni, kotaranov, horms,
shradhagupta, ernis, dipayanroy, linux-kernel, linux-rdma,
paulros
In-Reply-To: <20260605212302.2135499-1-haiyangz@linux.microsoft.com>
Hello:
This patch was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Fri, 5 Jun 2026 14:22:56 -0700 you wrote:
> From: Haiyang Zhang <haiyangz@microsoft.com>
>
> Update the device id table to include the new device id 0x00C1.
> This device's BAR layout is similar to VF's, update the function,
> mana_gd_init_registers(), accordingly.
>
> Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
>
> [...]
Here is the summary with links:
- [net-next] net: mana: Add support for PF device 0x00C1
https://git.kernel.org/netdev/net-next/c/53a65db20a4f
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH net-next v12 1/6] net: mana: Create separate EQs for each vPort
From: patchwork-bot+netdevbpf @ 2026-06-10 0:40 UTC (permalink / raw)
To: Long Li
Cc: kotaranov, kuba, davem, pabeni, edumazet, andrew+netdev, jgg,
leon, haiyangz, kys, wei.liu, decui, shradhagupta, horms, netdev,
linux-rdma, linux-hyperv, linux-kernel
In-Reply-To: <20260605005717.2059954-2-longli@microsoft.com>
Hello:
This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Thu, 4 Jun 2026 17:57:10 -0700 you wrote:
> To prepare for assigning vPorts to dedicated MSI-X vectors, remove EQ
> sharing among the vPorts and create dedicated EQs for each vPort.
>
> Move the EQ definition from struct mana_context to struct mana_port_context
> and update related support functions. Export mana_create_eq() and
> mana_destroy_eq() for use by the MANA RDMA driver.
>
> [...]
Here is the summary with links:
- [net-next,v12,1/6] net: mana: Create separate EQs for each vPort
https://git.kernel.org/netdev/net-next/c/fa1a3b7bcd16
- [net-next,v12,2/6] net: mana: Query device capabilities and configure MSI-X sharing for EQs
https://git.kernel.org/netdev/net-next/c/d7c253d61488
- [net-next,v12,3/6] net: mana: Introduce GIC context with refcounting for interrupt management
https://git.kernel.org/netdev/net-next/c/d478457fc1b7
- [net-next,v12,4/6] net: mana: Use GIC functions to allocate global EQs
https://git.kernel.org/netdev/net-next/c/346c277d1db8
- [net-next,v12,5/6] net: mana: Allocate interrupt context for each EQ when creating vPort
https://git.kernel.org/netdev/net-next/c/487af6f5391e
- [net-next,v12,6/6] RDMA/mana_ib: Allocate interrupt contexts on EQs
https://git.kernel.org/netdev/net-next/c/062b2b051f14
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH v4 02/47] x86/tsc: Add a standalone helpers for getting TSC info from CPUID.0x15
From: Sean Christopherson @ 2026-06-09 19:28 UTC (permalink / raw)
To: Borislav Petkov
Cc: Paolo Bonzini, Thomas Gleixner, Ingo Molnar, Dave Hansen, x86,
Kiryl Shutsemau, K. Y. Srinivasan, Haiyang Zhang, Wei Liu,
Dexuan Cui, Long Li, Ajay Kaher, Alexey Makhalov, Jan Kiszka,
Andy Lutomirski, Peter Zijlstra, Juergen Gross, Daniel Lezcano,
John Stultz, H. Peter Anvin, Rick Edgecombe, Vitaly Kuznetsov,
Broadcom internal kernel review list, Boris Ostrovsky,
Stephen Boyd, kvm, linux-kernel, linux-coco, linux-hyperv,
virtualization, xen-devel, David Woodhouse, Tom Lendacky,
Nikunj A Dadhania, David Woodhouse, Michael Kelley,
Thomas Gleixner
In-Reply-To: <20260602034916.GGah5SvARd77mkvxe3@fat_crate.local>
On Mon, Jun 01, 2026, Borislav Petkov wrote:
> On Fri, May 29, 2026 at 07:43:49AM -0700, Sean Christopherson wrote:
> > +static int cpuid_get_tsc_info(struct cpuid_tsc_info *info)
> > +{
> > + unsigned int ecx_hz, edx;
> > +
> > + memset(info, 0, sizeof(*info));
>
> Let's not clear this unnecessarily...
>
> > +
> > + if (boot_cpu_data.cpuid_level < CPUID_LEAF_TSC)
> > + return -ENOENT;
>
> ... just to return here...
>
> > +
> > + /* CPUID 15H TSC/Crystal ratio, plus optionally Crystal Hz */
> > + cpuid(CPUID_LEAF_TSC, &info->denominator, &info->numerator, &ecx_hz, &edx);
> > +
> > + if (!info->denominator || !info->numerator)
> > + return -ENOENT;
>
> ... or here.
>
> We wanna clear it here, when we'll return success.
Actually, if we take the approach of relying on the user to check the return
code, then there's no need to zero the struct since all fields will be explicitly
written, especially if we drop the "tsc_khz" field. I was zeroing the field
purely as defense in depth.
^ permalink raw reply
* Re: [PATCH v4 01/47] x86/tsc: Never re-calibrate TSC frequency if its exact timing is known
From: Thomas Gleixner @ 2026-06-09 19:27 UTC (permalink / raw)
To: Sean Christopherson
Cc: Paolo Bonzini, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
Kiryl Shutsemau, K. Y. Srinivasan, Haiyang Zhang, Wei Liu,
Dexuan Cui, Long Li, Ajay Kaher, Alexey Makhalov, Jan Kiszka,
Andy Lutomirski, Peter Zijlstra, Juergen Gross, Daniel Lezcano,
John Stultz, H. Peter Anvin, Rick Edgecombe, Vitaly Kuznetsov,
Broadcom internal kernel review list, Boris Ostrovsky,
Stephen Boyd, kvm, linux-kernel, linux-coco, linux-hyperv,
virtualization, xen-devel, David Woodhouse, Tom Lendacky,
Nikunj A Dadhania, David Woodhouse, Michael Kelley
In-Reply-To: <aihKj-0nP7bUbNHH@google.com>
On Tue, Jun 09 2026 at 10:17, Sean Christopherson wrote:
> On Fri, Jun 05, 2026, Thomas Gleixner wrote:
>> On Fri, Jun 05 2026 at 11:04, Sean Christopherson wrote:
>> But we also should have a check in the TSC init code somewhere which
>> validates that X86_FEATURE_CONSTANT_TSC is set when
>> X86_FEATURE_TSC_KNOWN_FREQ is set. X86_FEATURE_TSC_KNOWN_FREQ is useless
>> w/o X86_FEATURE_CONSTANT_TSC.
>
> Ugh, any objection to punting on this for now? KVM and Xen guests will trigger
> TSC_KNOWN_FREQ without CONSTANT_TSC, thanks to commits:
>
> e10f78050323 ("kvmclock: fix TSC calibration for nested guests")
> 898ec52d2ba0 ("x86/xen/time: Set the X86_FEATURE_TSC_KNOWN_FREQ flag in xen_tsc_khz()")
>
> Hyper-V guests might as well? Hyper-V's handling of TSC is weird, even for a
> hypervisor.
Hypervisors are ranked by weirdness? I ranked them by insanity so far.
> Even when the frequency is provided in CPUID by the hypervisor, QEMU at least
> requires a fairly explicit opt-in to advertise CONSTANT_TSC, presumably to try
> to prevent users from shooting themselves in the foot.
Bah. We really should have enforced the dependency when we introduced
KNOWN_FREQ. But that ship has sailed.
Though for correctness sake this should be fixed at some point in the
foreseeable future.
Thanks,
tglx
^ permalink raw reply
* Re: [RFC PATCH 3/6] arm64: hyperv: Add per-CPU RSI host call infrastructure for CCA Realms
From: sashiko-bot @ 2026-06-09 18:51 UTC (permalink / raw)
To: Kameron Carr; +Cc: linux-hyperv
In-Reply-To: <20260609181030.2378391-4-kameroncarr@linux.microsoft.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] The generic hypercall wrappers (`hv_do_hypercall`, `hv_do_fast_hypercall8`, `hv_do_fast_hypercall16`) were not updated to use the RSI_HOST_CALL interface, breaking hypercalls for CCA Realms.
- [High] Missing NULL pointer check for the dynamically allocated per-CPU `hostcall` buffer in `hv_set_vpreg()` and `hv_get_vpreg_128()` can cause a recursive crash during a panic.
- [Low] Complex error handling and cleanup logic for early boot memory allocation failures violates subsystem guidelines.
--
commit 286a7465cb0cf6433c1d0e69d74a2bf4a0c1a935
Author: Kameron Carr <kameroncarr@linux.microsoft.com>
arm64: hyperv: Add per-CPU RSI host call infrastructure for CCA Realms
This patch introduces the hyperv_pcpu_hostcall_struct to support Arm CCA
Realms, which must route hypercalls through the RSI_HOST_CALL interface.
It allocates this per-CPU structure for the boot CPU and secondary CPUs.
> Arm CCA Realms cannot issue Hyper-V hypercalls via HVC; the guest must
> route them through the RSI_HOST_CALL interface, which takes the IPA of a
> per-CPU rsi_host_call structure as its argument.
[Severity: High]
Does this patch miss updating the generic hypercall wrappers?
Looking at hv_do_hypercall() in arch/arm64/hyperv/hv_core.c, it still issues
an HVC instruction unconditionally via arm_smccc_1_1_hvc().
Since these generic functions are heavily used throughout the Hyper-V stack
(including early initialization like hv_get_partition_id()), could a CCA
Realm guest crash when it inadvertently executes the trapped HVC instruction?
> diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
> index 4fdc26ade1d74..08fec82691683 100644
> --- a/arch/arm64/hyperv/mshyperv.c
> +++ b/arch/arm64/hyperv/mshyperv.c
[ ... ]
> @@ -60,6 +66,46 @@ static bool __init hyperv_detect_via_acpi(void)
>
> #endif
>
> +static void hv_hostcall_free(void)
> +{
> + int cpu;
> +
> + if (!hyperv_pcpu_hostcall_struct)
> + return;
> +
> + for_each_possible_cpu(cpu)
> + kfree(*per_cpu_ptr(hyperv_pcpu_hostcall_struct, cpu));
> + free_percpu(hyperv_pcpu_hostcall_struct);
> + hyperv_pcpu_hostcall_struct = NULL;
> +}
> +
> +static int hv_cpu_init(unsigned int cpu)
> +{
> + void **hostcall_struct;
> + gfp_t flags;
> + void *mem;
> +
> + if (hyperv_pcpu_hostcall_struct) {
> + /* hv_cpu_init() can be called with IRQs disabled from hv_resume() */
> + flags = irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL;
> +
> + hostcall_struct = (void **)this_cpu_ptr(hyperv_pcpu_hostcall_struct);
> + /*
> + * The hostcall_struct memory is not freed when the CPU
> + * goes offline. If a previously offlined CPU is brought
> + * back online, the memory is reused here.
> + */
> + if (!*hostcall_struct) {
> + mem = kzalloc_obj(struct rsi_host_call, flags);
> + if (!mem)
> + return -ENOMEM;
> + *hostcall_struct = mem;
> + }
[Severity: High]
Is it safe to assume this pointer is always initialized during a panic?
If a secondary CPU panics before or during its bringup phase, its per-CPU
hostcall_struct pointer remains NULL.
The globally registered Hyper-V panic notifier runs on the panicking CPU and
calls hv_set_vpreg() and hv_get_vpreg_128(). These functions unconditionally
fetch the local pointer and perform an unprotected memset(hostcall, 0,
sizeof(*hostcall)).
Additionally, if cpuhp_setup_state() fails later during initialization,
hv_hostcall_free() clears hyperv_pcpu_hostcall_struct to NULL. Since
hv_common_free() does not unregister the panic notifiers, a subsequent
panic would cause this_cpu_ptr(NULL) to evaluate to __my_cpu_offset.
Could doing a memset() on these uninitialized pointers trigger a double
fault in the panic handler or memory corruption, losing the crash report
entirely?
> + }
> +
> + return hv_common_cpu_init(cpu);
> +}
[ ... ]
> @@ -85,6 +133,27 @@ static int __init hyperv_init(void)
> if (!hyperv_detect_via_acpi() && !hyperv_detect_via_smccc())
> return 0;
>
> + /*
> + * The RSI host-call buffer is only ever used when
> + * is_realm_world() is true. Skip the per-CPU allocation on
> + * non-Realm guests.
> + */
> + if (is_realm_world()) {
> + hyperv_pcpu_hostcall_struct = alloc_percpu(void *);
> + if (!hyperv_pcpu_hostcall_struct)
> + return -ENOMEM;
> +
> + hostcall_struct = (void **)this_cpu_ptr(hyperv_pcpu_hostcall_struct);
> + if (!*hostcall_struct) {
> + mem = kzalloc_obj(struct rsi_host_call);
> + if (!mem) {
> + ret = -ENOMEM;
> + goto free_hostcall_mem;
[Severity: Low]
Is this complex error handling and cleanup logic necessary here?
Since hyperv_init() is an early_initcall, physical memory should be
available. A failure at this stage typically implies the system cannot
boot anyway, making this teardown logic unnecessary dead code.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260609181030.2378391-1-kameroncarr@linux.microsoft.com?part=3
^ permalink raw reply
* Re: [RFC PATCH 5/6] arm64: hyperv: Route hypercalls through RSI host call in CCA Realms
From: sashiko-bot @ 2026-06-09 18:50 UTC (permalink / raw)
To: Kameron Carr; +Cc: linux-hyperv
In-Reply-To: <20260609181030.2378391-6-kameroncarr@linux.microsoft.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] NMI/FIQ Reentrancy Data Corruption in Realm Hypercalls
- [High] Uninitialized Access / Missing NULL Check on Per-CPU Hostcall Pointer
- [High] Hardware ABI Violation / Unsafe Memory Allocation for rsi_host_call
--
commit 17e33243e24b87deba9b6417fd0671d6c8f9140b
Author: Kameron Carr <kameroncarr@linux.microsoft.com>
arm64: hyperv: Route hypercalls through RSI host call in CCA Realms
Modify the five hypercall wrapper functions to check is_realm_world()
and use the per-CPU rsi_host_call structure when inside a Realm.
> diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c
> index e33a9e3c366a1..1759998ef2667 100644
> --- a/arch/arm64/hyperv/hv_core.c
> +++ b/arch/arm64/hyperv/hv_core.c
[ ... ]
> @@ -25,12 +26,32 @@ u64 hv_do_hypercall(u64 control, void *input, void *output)
> struct arm_smccc_res res;
> u64 input_address;
> u64 output_address;
> + struct rsi_host_call *hostcall;
> + unsigned long flags;
> + u64 ret;
>
> input_address = input ? virt_to_phys(input) : 0;
> output_address = output ? virt_to_phys(output) : 0;
>
> - arm_smccc_1_1_hvc(HV_FUNC_ID, control,
> - input_address, output_address, &res);
> + if (is_realm_world()) {
> + local_irq_save(flags);
> + hostcall = *this_cpu_ptr(hyperv_pcpu_hostcall_struct);
> + memset(hostcall, 0, sizeof(*hostcall));
[Severity: High]
Could hostcall be NULL here?
If a hypercall is issued before the per-CPU structure is allocated for the
local CPU (such as during early boot, early AP bring-up, or broadcast TLB
flushes), won't passing this to memset() cause a NULL pointer dereference?
[Severity: High]
Since hypercall arguments are now passed using a shared per-CPU memory
structure instead of registers, is there a risk of reentrancy corruption?
local_irq_save() disables IRQs, but it does not mask NMIs or synchronous
exceptions. If an NMI or exception interrupts this code after the memset()
and issues another hypercall (like a crash IPI via hv_do_fast_hypercall8()),
won't the nested hypercall overwrite this shared hostcall buffer?
When the exception returns, the interrupted hypercall would then execute
using the corrupted arguments or read the wrong return status.
> + hostcall->gprs[0] = HV_FUNC_ID;
> + hostcall->gprs[1] = control;
> + hostcall->gprs[2] = input_address;
> + hostcall->gprs[3] = output_address;
> +
> + if (rsi_host_call(virt_to_phys(hostcall)) == RSI_SUCCESS)
[Severity: High]
Is the 256-byte alignment required by the RMM guaranteed for this physical
address?
While the struct declaration might include an alignment attribute, dynamic
allocations don't always guarantee 256-byte physical alignment. For
instance, standard allocations only guarantee alignment up to
ARCH_KMALLOC_MINALIGN, and debugging features like CONFIG_SLUB_DEBUG can
shift object payloads, breaking natural power-of-two alignment.
Would passing an unaligned physical address here cause the RMM to reject
the call or inject a synchronous alignment fault into the Realm guest?
> + ret = hostcall->gprs[0];
> + else
> + ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
> + local_irq_restore(flags);
> + return ret;
> + }
> +
> arm_smccc_1_1_hvc(HV_FUNC_ID, control, input_address,
> output_address, &res);
> return res.a0;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260609181030.2378391-1-kameroncarr@linux.microsoft.com?part=5
^ permalink raw reply
* Re: [RFC PATCH 4/6] Drivers: hv: Mark shared memory as decrypted for CCA Realms
From: sashiko-bot @ 2026-06-09 18:27 UTC (permalink / raw)
To: Kameron Carr; +Cc: linux-hyperv
In-Reply-To: <20260609181030.2378391-5-kameroncarr@linux.microsoft.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Critical] Calling `set_memory_decrypted()` on a `HV_HYP_PAGE_SIZE` kmalloc buffer causes out-of-bounds memory decryption or silent failure when `PAGE_SIZE > 4096`.
- [High] Passing an MTE-tagged `kmalloc` pointer directly to `set_memory_decrypted()` without untagging it causes address validation failures and breaks CPU initialization.
--
commit 3df67c547c1f3625047cb1aee50d949f7179dd45
Author: Kameron Carr <kameroncarr@linux.microsoft.com>
Drivers: hv: Mark shared memory as decrypted for CCA Realms
In hv_common_cpu_init(), the per-CPU hypercall input/output pages need
to be marked as decrypted (shared) for confidential VM isolation types.
This is already done for SNP and TDX isolation; extend the same handling
to Arm CCA Realm guests so that the host hypervisor can access the
shared hypercall buffers.
[ ... ]
> diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
> index 6b67ac6167891..010c7d98b5de1 100644
> --- a/drivers/hv/hv_common.c
> +++ b/drivers/hv/hv_common.c
> @@ -499,7 +499,8 @@ int hv_common_cpu_init(unsigned int cpu)
> }
>
> if (!ms_hyperv.paravisor_present &&
> - (hv_isolation_type_snp() || hv_isolation_type_tdx())) {
> + (hv_isolation_type_snp() || hv_isolation_type_tdx() ||
> + hv_isolation_type_cca())) {
> ret = set_memory_decrypted((unsigned long)mem, pgcount);
[Severity: Critical]
Will this decrypt out-of-bounds memory or fail if PAGE_SIZE is larger than
4096 bytes on ARM64?
The buffer mem is allocated in hv_common_cpu_init() as 1 or 2 Hyper-V
4KB pages:
mem = kmalloc_array(pgcount, HV_HYP_PAGE_SIZE, flags);
However, set_memory_decrypted() expects pgcount to be the number of system
pages. On ARM64 kernels configured with 16KB or 64KB pages, passing pgcount
will decrypt 16KB-128KB of memory, potentially overrunning the 4KB or
8KB allocation and exposing unrelated adjacent slab memory to the hypervisor.
Additionally, if the kmalloc buffer is not aligned to the system PAGE_SIZE,
set_memory_decrypted() will trigger a WARN_ON(!PAGE_ALIGNED(addr)) and silently
return 0 without decrypting anything, leaving the hypercall page encrypted.
[Severity: High]
Does this code handle MTE tags correctly when passing mem to
set_memory_decrypted()?
On ARM64 with MTE enabled (CONFIG_KASAN_HW_TAGS), kmalloc_array() returns
an MTE-tagged pointer. The ARM64 set_memory_decrypted() implementation
validates the address using __is_lm_address(addr):
arch/arm64/mm/pageattr.c:__set_memory_enc_dec() {
...
if (!__is_lm_address(addr))
return -EINVAL;
...
}
Because __is_lm_address() performs software-side arithmetic without stripping
the tag, the MTE tag bits cause an arithmetic wrap-around. This evaluates
to false, returning -EINVAL and failing the CPU initialization process.
> if (ret) {
> /* It may be unsafe to free 'mem' */
> return ret;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260609181030.2378391-1-kameroncarr@linux.microsoft.com?part=4
^ permalink raw reply
* Re: [RFC PATCH 2/6] firmware: smccc: Detect hypervisor via RSI host call in CCA Realms
From: sashiko-bot @ 2026-06-09 18:24 UTC (permalink / raw)
To: Kameron Carr; +Cc: linux-hyperv
In-Reply-To: <20260609181030.2378391-3-kameroncarr@linux.microsoft.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Host call structure `uuid_hc` is allocated in protected memory, which will cause the RMM to reject the RSI_HOST_CALL.
--
commit ec503a8b7982b956b2d7e06ff213250087e22275
Author: Kameron Carr <kameroncarr@linux.microsoft.com>
firmware: smccc: Detect hypervisor via RSI host call in CCA Realms
Modify arm_smccc_hypervisor_has_uuid() to check is_realm_world() and use
rsi_host_call() to query the hypervisor vendor UUID when inside a Realm.
This introduces a file-static rsi_host_call buffer serialized by a spinlock
to handle the request.
> diff --git a/drivers/firmware/smccc/smccc.c b/drivers/firmware/smccc/smccc.c
> index bdee057db2fd3..6b465e65472b0 100644
> --- a/drivers/firmware/smccc/smccc.c
> +++ b/drivers/firmware/smccc/smccc.c
[ ... ]
> @@ -67,12 +73,45 @@ s32 arm_smccc_get_soc_id_revision(void)
> }
> EXPORT_SYMBOL_GPL(arm_smccc_get_soc_id_revision);
>
> +#ifdef CONFIG_ARM64
> +static struct rsi_host_call uuid_hc;
> +static DEFINE_SPINLOCK(uuid_hc_lock);
> +
> +/*
> + * Helper function to get the hypervisor UUID via an RsiHostCall.
> + */
> +static bool arm_smccc_realm_get_hypervisor_uuid(struct arm_smccc_res *res)
> +{
> + guard(spinlock_irqsave)(&uuid_hc_lock);
> +
> + memset(&uuid_hc, 0, sizeof(uuid_hc));
> + uuid_hc.gprs[0] = ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID;
> +
> + if (rsi_host_call(__pa_symbol(&uuid_hc)) != RSI_SUCCESS)
[Severity: High]
Will the RMM reject this host call because uuid_hc is located in protected
memory?
In ARM CCA (Realms), the memory passed to the RMM for an RSI_HOST_CALL
needs to be in the unprotected (shared) state, as the untrusted host
hypervisor must be able to read and write to it.
Since uuid_hc is statically allocated, it resides in the kernel's protected
BSS section. Calling rsi_host_call() with this physical address will likely
result in RSI_ERROR_INPUT and break hypervisor UUID discovery.
Additionally, because memory decryption operates at page granularity, applying
set_memory_decrypted() to a static variable would decrypt adjacent, unrelated
kernel data and expose it to the untrusted host.
Should this instead use a dedicated, dynamically allocated page that is safely
marked as decrypted?
> + return false;
> +
> + res->a0 = uuid_hc.gprs[0];
> + res->a1 = uuid_hc.gprs[1];
> + res->a2 = uuid_hc.gprs[2];
> + res->a3 = uuid_hc.gprs[3];
> + return true;
> +}
> +#endif
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260609181030.2378391-1-kameroncarr@linux.microsoft.com?part=2
^ permalink raw reply
* Re: [RFC PATCH 1/6] arm64: rsi: Add RSI host call structure and helper function
From: sashiko-bot @ 2026-06-09 18:20 UTC (permalink / raw)
To: Kameron Carr; +Cc: linux-hyperv
In-Reply-To: <20260609181030.2378391-2-kameroncarr@linux.microsoft.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] The `struct rsi_host_call` ABI definition relies on implicit compiler padding, failing to explicitly represent the RES0 field required by the CCA RMM specification.
--
commit 8a89052b48f09110c7f3fe9050a30fbf2d54c237
Author: Kameron Carr <kameroncarr@linux.microsoft.com>
arm64: rsi: Add RSI host call structure and helper function
This commit introduces the rsi_host_call structure and a helper function to
facilitate hypercall routing through the RSI interface for Hyper-V guests in
an Arm CCA Realm.
> diff --git a/arch/arm64/include/asm/rsi_smc.h b/arch/arm64/include/asm/rsi_smc.h
> index e19253f96c940..ffea93340ed7f 100644
> --- a/arch/arm64/include/asm/rsi_smc.h
> +++ b/arch/arm64/include/asm/rsi_smc.h
[ ... ]
> @@ -142,6 +142,12 @@ struct realm_config {
> */
> } __aligned(0x1000);
>
> +struct rsi_host_call {
> + u16 immediate;
> + u64 gprs[31];
> +} __aligned(256);
[Severity: Low]
This isn't a bug, but does this structure definition leave a 6-byte implicit
padding hole between immediate and gprs?
The Arm CCA RMM specification requires this 48-bit region to be reserved and
zeroed. While current allocations might safely zero this memory, could a
future stack allocation of this structure leave the padding bytes
uninitialized?
Would it be safer to add an explicit padding field to enforce the correct
layout and prevent potential leaks of uninitialized Realm memory to the
untrusted Host?
> +static_assert(sizeof(struct rsi_host_call) == 256);
> +
> #endif /* __ASSEMBLER__ */
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260609181030.2378391-1-kameroncarr@linux.microsoft.com?part=1
^ permalink raw reply
* [RFC PATCH 6/6] arm64: hyperv: Implement hv_is_isolation_supported() for CCA Realms
From: Kameron Carr @ 2026-06-09 18:10 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, longli
Cc: catalin.marinas, will, mark.rutland, lpieralisi, sudeep.holla,
arnd, thuth, linux-hyperv, linux-arm-kernel, linux-kernel,
linux-arch, mhklinux
In-Reply-To: <20260609181030.2378391-1-kameroncarr@linux.microsoft.com>
Provide an arm64 implementation of hv_is_isolation_supported() that
overrides the __weak default in drivers/hv/hv_common.c.
The implementation deliberately does not depend on
hv_is_hyperv_initialized() because hv_common_init() consults
hv_is_isolation_supported() before hyperv_initialized is set.
Signed-off-by: Kameron Carr <kameroncarr@linux.microsoft.com>
---
arch/arm64/hyperv/mshyperv.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
index b595b2b9bdbbb..b9b1c2f8e3ec7 100644
--- a/arch/arm64/hyperv/mshyperv.c
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -213,3 +213,8 @@ bool hv_isolation_type_cca(void)
{
return is_realm_world();
}
+
+bool hv_is_isolation_supported(void)
+{
+ return is_realm_world();
+}
--
2.45.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox