* [PATCH 0/3] don't allow changes to inactive colorops
@ 2026-05-26 14:17 Melissa Wen
2026-05-26 14:17 ` [PATCH 1/3] drm/atomic: only add states of active or transient active colorops Melissa Wen
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Melissa Wen @ 2026-05-26 14:17 UTC (permalink / raw)
To: airlied, maarten.lankhorst, mripard, simona, tzimmermann
Cc: Alex Hung, Simon Ser, Uma Shankar, Chaitanya Kumar Borah,
Xaver Hugl, Pekka Paalanen, Louis Chauvet, Matthew Schwartz,
John Harrison, Rodrigo Siqueira, amd-gfx, kernel-dev, Rob Clark,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul,
Marijn Suijten, linux-arm-msm, freedreno, intel-xe, intel-gfx,
dri-devel
This series is a follow-up of what was discussed in [1] and on #wayland
IRC channel regarding policy and userspace expectations on changes in
colorop properties and the current status of the color pipeline in which
the colorop is part of. In short, we agreed that userspace can change
properties of colorops that are currently part of an active color
pipeline or when the pipeline is switching status in the same commit.
However, userspace cannot change colorop properties of inactive color
pipeline in the expactation that it will be activated at some point in
the future.
Userspace also expects persistence of color pipeline already set, even
if it becomes inactive for a while, when activated, colorop settings
previouly set should be preserved.
In addition, I found some bugs on IGT tests when this policy is applied.
So I sent some bug fixes [2]. The rest of the series in [1] was detached
in [3] since there is no dependecy between them.
[1] https://lore.kernel.org/dri-devel/20260519211111.228303-1-mwen@igalia.com/
[2] https://lore.kernel.org/dri-devel/20260525100524.304263-1-mwen@igalia.com/
[3] https://lore.kernel.org/igt-dev/20260526140752.503380-1-mwen@igalia.com/
Melissa Wen (3):
drm/atomic: only add states of active or transient active colorops
drm/atomic: duplicate state of all colorops
drm/atomic: reject colorop update from inactive color pipeline
drivers/gpu/drm/drm_atomic.c | 126 ++++++++++++++++++++++++++--
drivers/gpu/drm/drm_atomic_helper.c | 9 +-
2 files changed, 120 insertions(+), 15 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH 1/3] drm/atomic: only add states of active or transient active colorops 2026-05-26 14:17 [PATCH 0/3] don't allow changes to inactive colorops Melissa Wen @ 2026-05-26 14:17 ` Melissa Wen 2026-05-26 23:02 ` Alex Hung 2026-05-26 14:17 ` [PATCH 2/3] drm/atomic: duplicate state of all colorops Melissa Wen 2026-05-26 14:17 ` [PATCH 3/3] drm/atomic: reject colorop update from inactive color pipeline Melissa Wen 2 siblings, 1 reply; 12+ messages in thread From: Melissa Wen @ 2026-05-26 14:17 UTC (permalink / raw) To: airlied, maarten.lankhorst, mripard, simona, tzimmermann Cc: Alex Hung, Simon Ser, Uma Shankar, Chaitanya Kumar Borah, Xaver Hugl, Pekka Paalanen, Louis Chauvet, Matthew Schwartz, John Harrison, Rodrigo Siqueira, amd-gfx, kernel-dev, Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten, linux-arm-msm, freedreno, intel-xe, intel-gfx, dri-devel Only consider affected colorop states those that are part of an active color pipeline or a pipeline that is about to be activated or deactivated in the same atomic commit, i.e., colorop is in the chain of old/new plane color pipeline property. To cover color_pipeline deactivation, remove the condition for plane_state->color_pipeline. Signed-off-by: Melissa Wen <mwen@igalia.com> --- drivers/gpu/drm/drm_atomic.c | 67 +++++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 170de30c28ae..4fb3a23e862a 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -812,6 +812,59 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, return 0; } +/* + * This function walks old and new plane state color pipelines and adds all + * colorops in use by @plane to the atomic configuration @state. This is useful + * when an atomic commit needs to check all currently enabled or about to be + * enabled colorop on @plane, e.g. when changing the mode. This also avoids + * including colorop states that are not part of the atomic state. + * + * Returns: + * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK + * then the w/w mutex code has detected a deadlock and the entire atomic + * sequence must be restarted. All other errors are fatal. + */ +static int +drm_atomic_add_pipeline_colorops(struct drm_atomic_commit *state, + struct drm_plane *plane) +{ + struct drm_colorop *colorop; + struct drm_colorop_state *colorop_state; + struct drm_plane_state *new_plane_state, *old_plane_state; + + new_plane_state = drm_atomic_get_new_plane_state(state, plane); + old_plane_state = drm_atomic_get_old_plane_state(state, plane); + + if (WARN_ON(!new_plane_state || !old_plane_state)) + return -EINVAL; + + drm_dbg_atomic(plane->dev, + "Adding old+new pipeline colorops for [PLANE:%d:%s]\n", + plane->base.id, plane->name); + + for (colorop = new_plane_state->color_pipeline; + colorop; + colorop = colorop->next) { + colorop_state = drm_atomic_get_colorop_state(state, colorop); + if (IS_ERR(colorop_state)) + return PTR_ERR(colorop_state); + } + + /* Same color pipeline as new; no point walking old. */ + if (new_plane_state->color_pipeline == old_plane_state->color_pipeline) + return 0; + + for (colorop = old_plane_state->color_pipeline; + colorop; + colorop = colorop->next) { + colorop_state = drm_atomic_get_colorop_state(state, colorop); + if (IS_ERR(colorop_state)) + return PTR_ERR(colorop_state); + } + + return 0; +} + static void drm_atomic_colorop_print_state(struct drm_printer *p, const struct drm_colorop_state *state) { @@ -1591,11 +1644,9 @@ drm_atomic_add_affected_planes(struct drm_atomic_commit *state, if (IS_ERR(plane_state)) return PTR_ERR(plane_state); - if (plane_state->color_pipeline) { - ret = drm_atomic_add_affected_colorops(state, plane); - if (ret) - return ret; - } + ret = drm_atomic_add_pipeline_colorops(state, plane); + if (ret) + return ret; } return 0; } @@ -1607,10 +1658,8 @@ EXPORT_SYMBOL(drm_atomic_add_affected_planes); * @plane: DRM plane * * This function walks the current configuration and adds all colorops - * currently used by @plane to the atomic configuration @state. This is useful - * when an atomic commit also needs to check all currently enabled colorop on - * @plane, e.g. when changing the mode. It's also useful when re-enabling a plane - * to avoid special code to force-enable all colorops. + * currently used by @plane to the atomic configuration @state. It's useful + * when re-enabling a plane to avoid special code to force-enable all colorops. * * Since acquiring a colorop state will always also acquire the w/w mutex of the * current plane for that colorop (if there is any) adding all the colorop states for -- 2.53.0 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] drm/atomic: only add states of active or transient active colorops 2026-05-26 14:17 ` [PATCH 1/3] drm/atomic: only add states of active or transient active colorops Melissa Wen @ 2026-05-26 23:02 ` Alex Hung 2026-05-29 13:46 ` Jani Nikula 0 siblings, 1 reply; 12+ messages in thread From: Alex Hung @ 2026-05-26 23:02 UTC (permalink / raw) To: Melissa Wen, airlied, maarten.lankhorst, mripard, simona, tzimmermann Cc: Simon Ser, Uma Shankar, Chaitanya Kumar Borah, Xaver Hugl, Pekka Paalanen, Louis Chauvet, Matthew Schwartz, John Harrison, Rodrigo Siqueira, amd-gfx, kernel-dev, Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten, linux-arm-msm, freedreno, intel-xe, intel-gfx, dri-devel On 5/26/26 08:17, Melissa Wen wrote: > Only consider affected colorop states those that are part of an active > color pipeline or a pipeline that is about to be activated or > deactivated in the same atomic commit, i.e., colorop is in the chain of > old/new plane color pipeline property. To cover color_pipeline > deactivation, remove the condition for plane_state->color_pipeline. > > Signed-off-by: Melissa Wen <mwen@igalia.com> > --- > drivers/gpu/drm/drm_atomic.c | 67 +++++++++++++++++++++++++++++++----- > 1 file changed, 58 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c > index 170de30c28ae..4fb3a23e862a 100644 > --- a/drivers/gpu/drm/drm_atomic.c > +++ b/drivers/gpu/drm/drm_atomic.c > @@ -812,6 +812,59 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, > return 0; > } > > +/* > + * This function walks old and new plane state color pipelines and adds all > + * colorops in use by @plane to the atomic configuration @state. This is useful > + * when an atomic commit needs to check all currently enabled or about to be > + * enabled colorop on @plane, e.g. when changing the mode. This also avoids > + * including colorop states that are not part of the atomic state. > + * > + * Returns: > + * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK > + * then the w/w mutex code has detected a deadlock and the entire atomic > + * sequence must be restarted. All other errors are fatal. > + */ > +static int > +drm_atomic_add_pipeline_colorops(struct drm_atomic_commit *state, > + struct drm_plane *plane) > +{ > + struct drm_colorop *colorop; > + struct drm_colorop_state *colorop_state; > + struct drm_plane_state *new_plane_state, *old_plane_state; > + > + new_plane_state = drm_atomic_get_new_plane_state(state, plane); > + old_plane_state = drm_atomic_get_old_plane_state(state, plane); > + > + if (WARN_ON(!new_plane_state || !old_plane_state)) > + return -EINVAL; > + > + drm_dbg_atomic(plane->dev, > + "Adding old+new pipeline colorops for [PLANE:%d:%s]\n", > + plane->base.id, plane->name); > + > + for (colorop = new_plane_state->color_pipeline; > + colorop; > + colorop = colorop->next) { This for-loop is used 5 times in this patchset. How about a macro in drm_colorop.h? #define drm_for_each_colorop_in_pipeline(colorop, pipeline) \ for ((colorop) = (pipeline); (colorop); (colorop) = (colorop)->next) > + colorop_state = drm_atomic_get_colorop_state(state, colorop); > + if (IS_ERR(colorop_state)) > + return PTR_ERR(colorop_state); > + } > + > + /* Same color pipeline as new; no point walking old. */ > + if (new_plane_state->color_pipeline == old_plane_state->color_pipeline) > + return 0; > + > + for (colorop = old_plane_state->color_pipeline; > + colorop; > + colorop = colorop->next) { > + colorop_state = drm_atomic_get_colorop_state(state, colorop); > + if (IS_ERR(colorop_state)) > + return PTR_ERR(colorop_state); > + } > + > + return 0; > +} > + > static void drm_atomic_colorop_print_state(struct drm_printer *p, > const struct drm_colorop_state *state) > { > @@ -1591,11 +1644,9 @@ drm_atomic_add_affected_planes(struct drm_atomic_commit *state, > if (IS_ERR(plane_state)) > return PTR_ERR(plane_state); > > - if (plane_state->color_pipeline) { > - ret = drm_atomic_add_affected_colorops(state, plane); > - if (ret) > - return ret; > - } > + ret = drm_atomic_add_pipeline_colorops(state, plane); > + if (ret) > + return ret; > } > return 0; > } > @@ -1607,10 +1658,8 @@ EXPORT_SYMBOL(drm_atomic_add_affected_planes); > * @plane: DRM plane > * > * This function walks the current configuration and adds all colorops > - * currently used by @plane to the atomic configuration @state. This is useful > - * when an atomic commit also needs to check all currently enabled colorop on > - * @plane, e.g. when changing the mode. It's also useful when re-enabling a plane > - * to avoid special code to force-enable all colorops. > + * currently used by @plane to the atomic configuration @state. It's useful > + * when re-enabling a plane to avoid special code to force-enable all colorops. > * > * Since acquiring a colorop state will always also acquire the w/w mutex of the > * current plane for that colorop (if there is any) adding all the colorop states for ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] drm/atomic: only add states of active or transient active colorops 2026-05-26 23:02 ` Alex Hung @ 2026-05-29 13:46 ` Jani Nikula 2026-06-01 9:24 ` Borah, Chaitanya Kumar 0 siblings, 1 reply; 12+ messages in thread From: Jani Nikula @ 2026-05-29 13:46 UTC (permalink / raw) To: Alex Hung, Melissa Wen, airlied, maarten.lankhorst, mripard, simona, tzimmermann Cc: Simon Ser, Uma Shankar, Chaitanya Kumar Borah, Xaver Hugl, Pekka Paalanen, Louis Chauvet, Matthew Schwartz, John Harrison, Rodrigo Siqueira, amd-gfx, kernel-dev, Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten, linux-arm-msm, freedreno, intel-xe, intel-gfx, dri-devel On Tue, 26 May 2026, Alex Hung <alex.hung@amd.com> wrote: > On 5/26/26 08:17, Melissa Wen wrote: >> Only consider affected colorop states those that are part of an active >> color pipeline or a pipeline that is about to be activated or >> deactivated in the same atomic commit, i.e., colorop is in the chain of >> old/new plane color pipeline property. To cover color_pipeline >> deactivation, remove the condition for plane_state->color_pipeline. >> >> Signed-off-by: Melissa Wen <mwen@igalia.com> >> --- >> drivers/gpu/drm/drm_atomic.c | 67 +++++++++++++++++++++++++++++++----- >> 1 file changed, 58 insertions(+), 9 deletions(-) >> >> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c >> index 170de30c28ae..4fb3a23e862a 100644 >> --- a/drivers/gpu/drm/drm_atomic.c >> +++ b/drivers/gpu/drm/drm_atomic.c >> @@ -812,6 +812,59 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, >> return 0; >> } >> >> +/* >> + * This function walks old and new plane state color pipelines and adds all >> + * colorops in use by @plane to the atomic configuration @state. This is useful >> + * when an atomic commit needs to check all currently enabled or about to be >> + * enabled colorop on @plane, e.g. when changing the mode. This also avoids >> + * including colorop states that are not part of the atomic state. >> + * >> + * Returns: >> + * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK >> + * then the w/w mutex code has detected a deadlock and the entire atomic >> + * sequence must be restarted. All other errors are fatal. >> + */ >> +static int >> +drm_atomic_add_pipeline_colorops(struct drm_atomic_commit *state, >> + struct drm_plane *plane) >> +{ >> + struct drm_colorop *colorop; >> + struct drm_colorop_state *colorop_state; >> + struct drm_plane_state *new_plane_state, *old_plane_state; >> + >> + new_plane_state = drm_atomic_get_new_plane_state(state, plane); >> + old_plane_state = drm_atomic_get_old_plane_state(state, plane); >> + >> + if (WARN_ON(!new_plane_state || !old_plane_state)) >> + return -EINVAL; >> + >> + drm_dbg_atomic(plane->dev, >> + "Adding old+new pipeline colorops for [PLANE:%d:%s]\n", >> + plane->base.id, plane->name); >> + >> + for (colorop = new_plane_state->color_pipeline; >> + colorop; >> + colorop = colorop->next) { > > This for-loop is used 5 times in this patchset. How about a macro in > drm_colorop.h? > > #define drm_for_each_colorop_in_pipeline(colorop, pipeline) \ > for ((colorop) = (pipeline); (colorop); (colorop) = (colorop)->next) Is there a reason struct drm_colorop reinvents lists and doesn't have struct list_head node? BR, Jani. > >> + colorop_state = drm_atomic_get_colorop_state(state, colorop); >> + if (IS_ERR(colorop_state)) >> + return PTR_ERR(colorop_state); >> + } >> + >> + /* Same color pipeline as new; no point walking old. */ >> + if (new_plane_state->color_pipeline == old_plane_state->color_pipeline) >> + return 0; >> + >> + for (colorop = old_plane_state->color_pipeline; >> + colorop; >> + colorop = colorop->next) { >> + colorop_state = drm_atomic_get_colorop_state(state, colorop); >> + if (IS_ERR(colorop_state)) >> + return PTR_ERR(colorop_state); >> + } >> + >> + return 0; >> +} >> + >> static void drm_atomic_colorop_print_state(struct drm_printer *p, >> const struct drm_colorop_state *state) >> { >> @@ -1591,11 +1644,9 @@ drm_atomic_add_affected_planes(struct drm_atomic_commit *state, >> if (IS_ERR(plane_state)) >> return PTR_ERR(plane_state); >> >> - if (plane_state->color_pipeline) { >> - ret = drm_atomic_add_affected_colorops(state, plane); >> - if (ret) >> - return ret; >> - } >> + ret = drm_atomic_add_pipeline_colorops(state, plane); >> + if (ret) >> + return ret; >> } >> return 0; >> } >> @@ -1607,10 +1658,8 @@ EXPORT_SYMBOL(drm_atomic_add_affected_planes); >> * @plane: DRM plane >> * >> * This function walks the current configuration and adds all colorops >> - * currently used by @plane to the atomic configuration @state. This is useful >> - * when an atomic commit also needs to check all currently enabled colorop on >> - * @plane, e.g. when changing the mode. It's also useful when re-enabling a plane >> - * to avoid special code to force-enable all colorops. >> + * currently used by @plane to the atomic configuration @state. It's useful >> + * when re-enabling a plane to avoid special code to force-enable all colorops. >> * >> * Since acquiring a colorop state will always also acquire the w/w mutex of the >> * current plane for that colorop (if there is any) adding all the colorop states for > -- Jani Nikula, Intel ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] drm/atomic: only add states of active or transient active colorops 2026-05-29 13:46 ` Jani Nikula @ 2026-06-01 9:24 ` Borah, Chaitanya Kumar 2026-06-03 11:27 ` Melissa Wen 0 siblings, 1 reply; 12+ messages in thread From: Borah, Chaitanya Kumar @ 2026-06-01 9:24 UTC (permalink / raw) To: Jani Nikula, Alex Hung, Melissa Wen, airlied, maarten.lankhorst, mripard, simona, tzimmermann Cc: Simon Ser, Uma Shankar, Xaver Hugl, Pekka Paalanen, Louis Chauvet, Matthew Schwartz, John Harrison, Rodrigo Siqueira, amd-gfx, kernel-dev, Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten, linux-arm-msm, freedreno, intel-xe, intel-gfx, dri-devel, harry.wentland@amd.com On 5/29/2026 7:16 PM, Jani Nikula wrote: > On Tue, 26 May 2026, Alex Hung <alex.hung@amd.com> wrote: >> On 5/26/26 08:17, Melissa Wen wrote: >>> Only consider affected colorop states those that are part of an active >>> color pipeline or a pipeline that is about to be activated or >>> deactivated in the same atomic commit, i.e., colorop is in the chain of >>> old/new plane color pipeline property. To cover color_pipeline >>> deactivation, remove the condition for plane_state->color_pipeline. >>> >>> Signed-off-by: Melissa Wen <mwen@igalia.com> >>> --- >>> drivers/gpu/drm/drm_atomic.c | 67 +++++++++++++++++++++++++++++++----- >>> 1 file changed, 58 insertions(+), 9 deletions(-) >>> >>> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c >>> index 170de30c28ae..4fb3a23e862a 100644 >>> --- a/drivers/gpu/drm/drm_atomic.c >>> +++ b/drivers/gpu/drm/drm_atomic.c >>> @@ -812,6 +812,59 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, >>> return 0; >>> } >>> >>> +/* >>> + * This function walks old and new plane state color pipelines and adds all >>> + * colorops in use by @plane to the atomic configuration @state. This is useful >>> + * when an atomic commit needs to check all currently enabled or about to be >>> + * enabled colorop on @plane, e.g. when changing the mode. This also avoids >>> + * including colorop states that are not part of the atomic state. >>> + * >>> + * Returns: >>> + * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK >>> + * then the w/w mutex code has detected a deadlock and the entire atomic >>> + * sequence must be restarted. All other errors are fatal. >>> + */ >>> +static int >>> +drm_atomic_add_pipeline_colorops(struct drm_atomic_commit *state, >>> + struct drm_plane *plane) >>> +{ >>> + struct drm_colorop *colorop; >>> + struct drm_colorop_state *colorop_state; >>> + struct drm_plane_state *new_plane_state, *old_plane_state; >>> + >>> + new_plane_state = drm_atomic_get_new_plane_state(state, plane); >>> + old_plane_state = drm_atomic_get_old_plane_state(state, plane); >>> + >>> + if (WARN_ON(!new_plane_state || !old_plane_state)) >>> + return -EINVAL; >>> + >>> + drm_dbg_atomic(plane->dev, >>> + "Adding old+new pipeline colorops for [PLANE:%d:%s]\n", >>> + plane->base.id, plane->name); >>> + >>> + for (colorop = new_plane_state->color_pipeline; >>> + colorop; >>> + colorop = colorop->next) { >> >> This for-loop is used 5 times in this patchset. How about a macro in >> drm_colorop.h? >> >> #define drm_for_each_colorop_in_pipeline(colorop, pipeline) \ >> for ((colorop) = (pipeline); (colorop); (colorop) = (colorop)->next) > > Is there a reason struct drm_colorop reinvents lists and doesn't have > struct list_head node? > I believe that's because the "next" colorop is exposed as a property (of the current colorop) to userspace. Since the chain is already described by the property, a struct list_head would be redundant. Harry, others can chime in. == Chaitanya > BR, > Jani. > >> >>> + colorop_state = drm_atomic_get_colorop_state(state, colorop); >>> + if (IS_ERR(colorop_state)) >>> + return PTR_ERR(colorop_state); >>> + } >>> + >>> + /* Same color pipeline as new; no point walking old. */ >>> + if (new_plane_state->color_pipeline == old_plane_state->color_pipeline) >>> + return 0; >>> + >>> + for (colorop = old_plane_state->color_pipeline; >>> + colorop; >>> + colorop = colorop->next) { >>> + colorop_state = drm_atomic_get_colorop_state(state, colorop); >>> + if (IS_ERR(colorop_state)) >>> + return PTR_ERR(colorop_state); >>> + } >>> + >>> + return 0; >>> +} >>> + >>> static void drm_atomic_colorop_print_state(struct drm_printer *p, >>> const struct drm_colorop_state *state) >>> { >>> @@ -1591,11 +1644,9 @@ drm_atomic_add_affected_planes(struct drm_atomic_commit *state, >>> if (IS_ERR(plane_state)) >>> return PTR_ERR(plane_state); >>> >>> - if (plane_state->color_pipeline) { >>> - ret = drm_atomic_add_affected_colorops(state, plane); >>> - if (ret) >>> - return ret; >>> - } >>> + ret = drm_atomic_add_pipeline_colorops(state, plane); >>> + if (ret) >>> + return ret; >>> } >>> return 0; >>> } >>> @@ -1607,10 +1658,8 @@ EXPORT_SYMBOL(drm_atomic_add_affected_planes); >>> * @plane: DRM plane >>> * >>> * This function walks the current configuration and adds all colorops >>> - * currently used by @plane to the atomic configuration @state. This is useful >>> - * when an atomic commit also needs to check all currently enabled colorop on >>> - * @plane, e.g. when changing the mode. It's also useful when re-enabling a plane >>> - * to avoid special code to force-enable all colorops. >>> + * currently used by @plane to the atomic configuration @state. It's useful >>> + * when re-enabling a plane to avoid special code to force-enable all colorops. >>> * >>> * Since acquiring a colorop state will always also acquire the w/w mutex of the >>> * current plane for that colorop (if there is any) adding all the colorop states for >> > ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] drm/atomic: only add states of active or transient active colorops 2026-06-01 9:24 ` Borah, Chaitanya Kumar @ 2026-06-03 11:27 ` Melissa Wen 2026-06-09 17:23 ` John Harrison 0 siblings, 1 reply; 12+ messages in thread From: Melissa Wen @ 2026-06-03 11:27 UTC (permalink / raw) To: Borah, Chaitanya Kumar, Jani Nikula, Alex Hung, airlied, maarten.lankhorst, mripard, simona, tzimmermann Cc: Simon Ser, Uma Shankar, Xaver Hugl, Pekka Paalanen, Louis Chauvet, Matthew Schwartz, John Harrison, Rodrigo Siqueira, amd-gfx, kernel-dev, Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten, linux-arm-msm, freedreno, intel-xe, intel-gfx, dri-devel, harry.wentland@amd.com On 01/06/2026 11:24, Borah, Chaitanya Kumar wrote: > > > On 5/29/2026 7:16 PM, Jani Nikula wrote: >> On Tue, 26 May 2026, Alex Hung <alex.hung@amd.com> wrote: >>> On 5/26/26 08:17, Melissa Wen wrote: >>>> Only consider affected colorop states those that are part of an active >>>> color pipeline or a pipeline that is about to be activated or >>>> deactivated in the same atomic commit, i.e., colorop is in the >>>> chain of >>>> old/new plane color pipeline property. To cover color_pipeline >>>> deactivation, remove the condition for plane_state->color_pipeline. >>>> >>>> Signed-off-by: Melissa Wen <mwen@igalia.com> >>>> --- >>>> drivers/gpu/drm/drm_atomic.c | 67 >>>> +++++++++++++++++++++++++++++++----- >>>> 1 file changed, 58 insertions(+), 9 deletions(-) >>>> >>>> diff --git a/drivers/gpu/drm/drm_atomic.c >>>> b/drivers/gpu/drm/drm_atomic.c >>>> index 170de30c28ae..4fb3a23e862a 100644 >>>> --- a/drivers/gpu/drm/drm_atomic.c >>>> +++ b/drivers/gpu/drm/drm_atomic.c >>>> @@ -812,6 +812,59 @@ static int drm_atomic_plane_check(const struct >>>> drm_plane_state *old_plane_state, >>>> return 0; >>>> } >>>> +/* >>>> + * This function walks old and new plane state color pipelines and >>>> adds all >>>> + * colorops in use by @plane to the atomic configuration @state. >>>> This is useful >>>> + * when an atomic commit needs to check all currently enabled or >>>> about to be >>>> + * enabled colorop on @plane, e.g. when changing the mode. This >>>> also avoids >>>> + * including colorop states that are not part of the atomic state. >>>> + * >>>> + * Returns: >>>> + * 0 on success or can fail with -EDEADLK or -ENOMEM. When the >>>> error is EDEADLK >>>> + * then the w/w mutex code has detected a deadlock and the entire >>>> atomic >>>> + * sequence must be restarted. All other errors are fatal. >>>> + */ >>>> +static int >>>> +drm_atomic_add_pipeline_colorops(struct drm_atomic_commit *state, >>>> + struct drm_plane *plane) >>>> +{ >>>> + struct drm_colorop *colorop; >>>> + struct drm_colorop_state *colorop_state; >>>> + struct drm_plane_state *new_plane_state, *old_plane_state; >>>> + >>>> + new_plane_state = drm_atomic_get_new_plane_state(state, plane); >>>> + old_plane_state = drm_atomic_get_old_plane_state(state, plane); >>>> + >>>> + if (WARN_ON(!new_plane_state || !old_plane_state)) >>>> + return -EINVAL; >>>> + >>>> + drm_dbg_atomic(plane->dev, >>>> + "Adding old+new pipeline colorops for >>>> [PLANE:%d:%s]\n", >>>> + plane->base.id, plane->name); >>>> + >>>> + for (colorop = new_plane_state->color_pipeline; >>>> + colorop; >>>> + colorop = colorop->next) { >>> >>> This for-loop is used 5 times in this patchset. How about a macro in >>> drm_colorop.h? >>> >>> #define drm_for_each_colorop_in_pipeline(colorop, pipeline) \ >>> for ((colorop) = (pipeline); (colorop); (colorop) = >>> (colorop)->next) >> >> Is there a reason struct drm_colorop reinvents lists and doesn't have >> struct list_head node? >> > > I believe that's because the "next" colorop is exposed as a property > (of the current colorop) to userspace. Since the chain is already > described by the property, a struct list_head would be redundant. Also, each color pipeline is an immutable chain of colorops where the sequence and position matter: once the chain is built, colorops are never added, removed, replaced or walked in reverse. It's a forward-only chain that ends when next == NULL, and it directly matches userspace mapping. Another point to take into account is that there is no struct drm_color_pipeline to hold a list_head yet, since each color pipeline is identified by the first colorop element in the chain. Maybe we will want a container to link a given pre-blend color pipeline to a specific post-blend color pipeline for example, but linking pre- to post-blend color pipelines is something we are still not clear about. Melissa > > Harry, others can chime in. > > == > Chaitanya > >> BR, >> Jani. >> >>> >>>> + colorop_state = drm_atomic_get_colorop_state(state, colorop); >>>> + if (IS_ERR(colorop_state)) >>>> + return PTR_ERR(colorop_state); >>>> + } >>>> + >>>> + /* Same color pipeline as new; no point walking old. */ >>>> + if (new_plane_state->color_pipeline == >>>> old_plane_state->color_pipeline) >>>> + return 0; >>>> + >>>> + for (colorop = old_plane_state->color_pipeline; >>>> + colorop; >>>> + colorop = colorop->next) { >>>> + colorop_state = drm_atomic_get_colorop_state(state, colorop); >>>> + if (IS_ERR(colorop_state)) >>>> + return PTR_ERR(colorop_state); >>>> + } >>>> + >>>> + return 0; >>>> +} >>>> + >>>> static void drm_atomic_colorop_print_state(struct drm_printer *p, >>>> const struct drm_colorop_state *state) >>>> { >>>> @@ -1591,11 +1644,9 @@ drm_atomic_add_affected_planes(struct >>>> drm_atomic_commit *state, >>>> if (IS_ERR(plane_state)) >>>> return PTR_ERR(plane_state); >>>> - if (plane_state->color_pipeline) { >>>> - ret = drm_atomic_add_affected_colorops(state, plane); >>>> - if (ret) >>>> - return ret; >>>> - } >>>> + ret = drm_atomic_add_pipeline_colorops(state, plane); >>>> + if (ret) >>>> + return ret; >>>> } >>>> return 0; >>>> } >>>> @@ -1607,10 +1658,8 @@ EXPORT_SYMBOL(drm_atomic_add_affected_planes); >>>> * @plane: DRM plane >>>> * >>>> * This function walks the current configuration and adds all >>>> colorops >>>> - * currently used by @plane to the atomic configuration @state. >>>> This is useful >>>> - * when an atomic commit also needs to check all currently enabled >>>> colorop on >>>> - * @plane, e.g. when changing the mode. It's also useful when >>>> re-enabling a plane >>>> - * to avoid special code to force-enable all colorops. >>>> + * currently used by @plane to the atomic configuration @state. >>>> It's useful >>>> + * when re-enabling a plane to avoid special code to force-enable >>>> all colorops. >>>> * >>>> * Since acquiring a colorop state will always also acquire the >>>> w/w mutex of the >>>> * current plane for that colorop (if there is any) adding all >>>> the colorop states for >>> >> > ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] drm/atomic: only add states of active or transient active colorops 2026-06-03 11:27 ` Melissa Wen @ 2026-06-09 17:23 ` John Harrison 2026-06-24 19:01 ` Harry Wentland 0 siblings, 1 reply; 12+ messages in thread From: John Harrison @ 2026-06-09 17:23 UTC (permalink / raw) To: Melissa Wen, Borah, Chaitanya Kumar, Jani Nikula, Alex Hung, airlied, maarten.lankhorst, mripard, simona, tzimmermann Cc: Simon Ser, Uma Shankar, Xaver Hugl, Pekka Paalanen, Louis Chauvet, Matthew Schwartz, Rodrigo Siqueira, amd-gfx, kernel-dev, Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten, linux-arm-msm, freedreno, intel-xe, intel-gfx, dri-devel, harry.wentland@amd.com On 6/3/26 04:27, Melissa Wen wrote: > On 01/06/2026 11:24, Borah, Chaitanya Kumar wrote: >> On 5/29/2026 7:16 PM, Jani Nikula wrote: >>> On Tue, 26 May 2026, Alex Hung <alex.hung@amd.com> wrote: >>>> On 5/26/26 08:17, Melissa Wen wrote: >>>>> Only consider affected colorop states those that are part of an >>>>> active >>>>> color pipeline or a pipeline that is about to be activated or >>>>> deactivated in the same atomic commit, i.e., colorop is in the >>>>> chain of >>>>> old/new plane color pipeline property. To cover color_pipeline >>>>> deactivation, remove the condition for plane_state->color_pipeline. >>>>> >>>>> Signed-off-by: Melissa Wen <mwen@igalia.com> >>>>> --- >>>>> drivers/gpu/drm/drm_atomic.c | 67 >>>>> +++++++++++++++++++++++++++++++----- >>>>> 1 file changed, 58 insertions(+), 9 deletions(-) >>>>> >>>>> diff --git a/drivers/gpu/drm/drm_atomic.c >>>>> b/drivers/gpu/drm/drm_atomic.c >>>>> index 170de30c28ae..4fb3a23e862a 100644 >>>>> --- a/drivers/gpu/drm/drm_atomic.c >>>>> +++ b/drivers/gpu/drm/drm_atomic.c >>>>> @@ -812,6 +812,59 @@ static int drm_atomic_plane_check(const >>>>> struct drm_plane_state *old_plane_state, >>>>> return 0; >>>>> } >>>>> +/* >>>>> + * This function walks old and new plane state color pipelines >>>>> and adds all >>>>> + * colorops in use by @plane to the atomic configuration @state. >>>>> This is useful >>>>> + * when an atomic commit needs to check all currently enabled or >>>>> about to be >>>>> + * enabled colorop on @plane, e.g. when changing the mode. This >>>>> also avoids >>>>> + * including colorop states that are not part of the atomic state. >>>>> + * >>>>> + * Returns: >>>>> + * 0 on success or can fail with -EDEADLK or -ENOMEM. When the >>>>> error is EDEADLK >>>>> + * then the w/w mutex code has detected a deadlock and the entire >>>>> atomic >>>>> + * sequence must be restarted. All other errors are fatal. >>>>> + */ >>>>> +static int >>>>> +drm_atomic_add_pipeline_colorops(struct drm_atomic_commit *state, >>>>> + struct drm_plane *plane) >>>>> +{ >>>>> + struct drm_colorop *colorop; >>>>> + struct drm_colorop_state *colorop_state; >>>>> + struct drm_plane_state *new_plane_state, *old_plane_state; >>>>> + >>>>> + new_plane_state = drm_atomic_get_new_plane_state(state, plane); >>>>> + old_plane_state = drm_atomic_get_old_plane_state(state, plane); >>>>> + >>>>> + if (WARN_ON(!new_plane_state || !old_plane_state)) >>>>> + return -EINVAL; >>>>> + >>>>> + drm_dbg_atomic(plane->dev, >>>>> + "Adding old+new pipeline colorops for >>>>> [PLANE:%d:%s]\n", >>>>> + plane->base.id, plane->name); >>>>> + >>>>> + for (colorop = new_plane_state->color_pipeline; >>>>> + colorop; >>>>> + colorop = colorop->next) { >>>> >>>> This for-loop is used 5 times in this patchset. How about a macro in >>>> drm_colorop.h? >>>> >>>> #define drm_for_each_colorop_in_pipeline(colorop, pipeline) \ >>>> for ((colorop) = (pipeline); (colorop); (colorop) = >>>> (colorop)->next) >>> >>> Is there a reason struct drm_colorop reinvents lists and doesn't have >>> struct list_head node? >>> >> >> I believe that's because the "next" colorop is exposed as a property >> (of the current colorop) to userspace. Since the chain is already >> described by the property, a struct list_head would be redundant. > > Also, each color pipeline is an immutable chain of colorops where the > sequence and position matter: once the chain is built, colorops are > never added, removed, replaced or walked in reverse. It's a > forward-only chain that ends when next == NULL, and it directly > matches userspace mapping. Another point to take into account is that > there is no struct drm_color_pipeline to hold a list_head yet, since > each color pipeline is identified by the first colorop element in the > chain. Maybe we will want a container to link a given pre-blend color > pipeline to a specific post-blend color pipeline for example, but > linking pre- to post-blend color pipelines is something we are still > not clear about. > > Melissa > "there is no struct drm_color_pipeline to hold a list_head" <-- I think this is the real reason. It is possible to convert to use a proper list structure, but the result is slightly messy. I had a quick go at it to see how messy: https://patchwork.freedesktop.org/series/168200/ John. >> >> Harry, others can chime in. >> >> == >> Chaitanya >> >>> BR, >>> Jani. >>> >>>> >>>>> + colorop_state = drm_atomic_get_colorop_state(state, >>>>> colorop); >>>>> + if (IS_ERR(colorop_state)) >>>>> + return PTR_ERR(colorop_state); >>>>> + } >>>>> + >>>>> + /* Same color pipeline as new; no point walking old. */ >>>>> + if (new_plane_state->color_pipeline == >>>>> old_plane_state->color_pipeline) >>>>> + return 0; >>>>> + >>>>> + for (colorop = old_plane_state->color_pipeline; >>>>> + colorop; >>>>> + colorop = colorop->next) { >>>>> + colorop_state = drm_atomic_get_colorop_state(state, >>>>> colorop); >>>>> + if (IS_ERR(colorop_state)) >>>>> + return PTR_ERR(colorop_state); >>>>> + } >>>>> + >>>>> + return 0; >>>>> +} >>>>> + >>>>> static void drm_atomic_colorop_print_state(struct drm_printer *p, >>>>> const struct drm_colorop_state *state) >>>>> { >>>>> @@ -1591,11 +1644,9 @@ drm_atomic_add_affected_planes(struct >>>>> drm_atomic_commit *state, >>>>> if (IS_ERR(plane_state)) >>>>> return PTR_ERR(plane_state); >>>>> - if (plane_state->color_pipeline) { >>>>> - ret = drm_atomic_add_affected_colorops(state, plane); >>>>> - if (ret) >>>>> - return ret; >>>>> - } >>>>> + ret = drm_atomic_add_pipeline_colorops(state, plane); >>>>> + if (ret) >>>>> + return ret; >>>>> } >>>>> return 0; >>>>> } >>>>> @@ -1607,10 +1658,8 @@ EXPORT_SYMBOL(drm_atomic_add_affected_planes); >>>>> * @plane: DRM plane >>>>> * >>>>> * This function walks the current configuration and adds all >>>>> colorops >>>>> - * currently used by @plane to the atomic configuration @state. >>>>> This is useful >>>>> - * when an atomic commit also needs to check all currently >>>>> enabled colorop on >>>>> - * @plane, e.g. when changing the mode. It's also useful when >>>>> re-enabling a plane >>>>> - * to avoid special code to force-enable all colorops. >>>>> + * currently used by @plane to the atomic configuration @state. >>>>> It's useful >>>>> + * when re-enabling a plane to avoid special code to force-enable >>>>> all colorops. >>>>> * >>>>> * Since acquiring a colorop state will always also acquire the >>>>> w/w mutex of the >>>>> * current plane for that colorop (if there is any) adding all >>>>> the colorop states for >>>> >>> >> > ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] drm/atomic: only add states of active or transient active colorops 2026-06-09 17:23 ` John Harrison @ 2026-06-24 19:01 ` Harry Wentland 2026-06-24 20:06 ` John Harrison 0 siblings, 1 reply; 12+ messages in thread From: Harry Wentland @ 2026-06-24 19:01 UTC (permalink / raw) To: John Harrison, Melissa Wen, Borah, Chaitanya Kumar, Jani Nikula, Alex Hung, airlied, maarten.lankhorst, mripard, simona, tzimmermann Cc: Simon Ser, Uma Shankar, Xaver Hugl, Pekka Paalanen, Louis Chauvet, Matthew Schwartz, Rodrigo Siqueira, amd-gfx, kernel-dev, Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten, linux-arm-msm, freedreno, intel-xe, intel-gfx, dri-devel On 2026-06-09 13:23, John Harrison wrote: > On 6/3/26 04:27, Melissa Wen wrote: >> On 01/06/2026 11:24, Borah, Chaitanya Kumar wrote: >>> On 5/29/2026 7:16 PM, Jani Nikula wrote: >>>> On Tue, 26 May 2026, Alex Hung <alex.hung@amd.com> wrote: >>>>> On 5/26/26 08:17, Melissa Wen wrote: >>>>>> Only consider affected colorop states those that are part of an active >>>>>> color pipeline or a pipeline that is about to be activated or >>>>>> deactivated in the same atomic commit, i.e., colorop is in the chain of >>>>>> old/new plane color pipeline property. To cover color_pipeline >>>>>> deactivation, remove the condition for plane_state->color_pipeline. >>>>>> >>>>>> Signed-off-by: Melissa Wen <mwen@igalia.com> >>>>>> --- >>>>>> drivers/gpu/drm/drm_atomic.c | 67 +++++++++++++++++++++++++++++++----- >>>>>> 1 file changed, 58 insertions(+), 9 deletions(-) >>>>>> >>>>>> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c >>>>>> index 170de30c28ae..4fb3a23e862a 100644 >>>>>> --- a/drivers/gpu/drm/drm_atomic.c >>>>>> +++ b/drivers/gpu/drm/drm_atomic.c >>>>>> @@ -812,6 +812,59 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, >>>>>> return 0; >>>>>> } >>>>>> +/* >>>>>> + * This function walks old and new plane state color pipelines and adds all >>>>>> + * colorops in use by @plane to the atomic configuration @state. This is useful >>>>>> + * when an atomic commit needs to check all currently enabled or about to be >>>>>> + * enabled colorop on @plane, e.g. when changing the mode. This also avoids >>>>>> + * including colorop states that are not part of the atomic state. >>>>>> + * >>>>>> + * Returns: >>>>>> + * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK >>>>>> + * then the w/w mutex code has detected a deadlock and the entire atomic >>>>>> + * sequence must be restarted. All other errors are fatal. >>>>>> + */ >>>>>> +static int >>>>>> +drm_atomic_add_pipeline_colorops(struct drm_atomic_commit *state, >>>>>> + struct drm_plane *plane) >>>>>> +{ >>>>>> + struct drm_colorop *colorop; >>>>>> + struct drm_colorop_state *colorop_state; >>>>>> + struct drm_plane_state *new_plane_state, *old_plane_state; >>>>>> + >>>>>> + new_plane_state = drm_atomic_get_new_plane_state(state, plane); >>>>>> + old_plane_state = drm_atomic_get_old_plane_state(state, plane); >>>>>> + >>>>>> + if (WARN_ON(!new_plane_state || !old_plane_state)) >>>>>> + return -EINVAL; >>>>>> + >>>>>> + drm_dbg_atomic(plane->dev, >>>>>> + "Adding old+new pipeline colorops for [PLANE:%d:%s]\n", >>>>>> + plane->base.id, plane->name); >>>>>> + >>>>>> + for (colorop = new_plane_state->color_pipeline; >>>>>> + colorop; >>>>>> + colorop = colorop->next) { >>>>> >>>>> This for-loop is used 5 times in this patchset. How about a macro in >>>>> drm_colorop.h? >>>>> >>>>> #define drm_for_each_colorop_in_pipeline(colorop, pipeline) \ >>>>> for ((colorop) = (pipeline); (colorop); (colorop) = (colorop)->next) >>>> >>>> Is there a reason struct drm_colorop reinvents lists and doesn't have >>>> struct list_head node? >>>> >>> >>> I believe that's because the "next" colorop is exposed as a property (of the current colorop) to userspace. Since the chain is already described by the property, a struct list_head would be redundant. >> >> Also, each color pipeline is an immutable chain of colorops where the sequence and position matter: once the chain is built, colorops are never added, removed, replaced or walked in reverse. It's a forward-only chain that ends when next == NULL, and it directly matches userspace mapping. Another point to take into account is that there is no struct drm_color_pipeline to hold a list_head yet, since each color pipeline is identified by the first colorop element in the chain. Maybe we will want a container to link a given pre-blend color pipeline to a specific post-blend color pipeline for example, but linking pre- to post-blend color pipelines is something we are still not clear about. >> >> Melissa >> > "there is no struct drm_color_pipeline to hold a list_head" <-- I think this is the real reason. It is possible to convert to use a proper list structure, but the result is slightly messy. I had a quick go at it to see how messy: > https://patchwork.freedesktop.org/series/168200/ > Yeah, Melissa and Chaitanya pretty much described why they work the way they do. I'm not sure it makes sense to replace the mechanism with lists and any attempt to do so should make sure not to break userspace ABI. I'm not opposed to improvements either if anyone finds a solution that makes everyone's lives easier. Harry > John. > >>> >>> Harry, others can chime in. >>> >>> == >>> Chaitanya >>> >>>> BR, >>>> Jani. >>>> >>>>> >>>>>> + colorop_state = drm_atomic_get_colorop_state(state, colorop); >>>>>> + if (IS_ERR(colorop_state)) >>>>>> + return PTR_ERR(colorop_state); >>>>>> + } >>>>>> + >>>>>> + /* Same color pipeline as new; no point walking old. */ >>>>>> + if (new_plane_state->color_pipeline == old_plane_state->color_pipeline) >>>>>> + return 0; >>>>>> + >>>>>> + for (colorop = old_plane_state->color_pipeline; >>>>>> + colorop; >>>>>> + colorop = colorop->next) { >>>>>> + colorop_state = drm_atomic_get_colorop_state(state, colorop); >>>>>> + if (IS_ERR(colorop_state)) >>>>>> + return PTR_ERR(colorop_state); >>>>>> + } >>>>>> + >>>>>> + return 0; >>>>>> +} >>>>>> + >>>>>> static void drm_atomic_colorop_print_state(struct drm_printer *p, >>>>>> const struct drm_colorop_state *state) >>>>>> { >>>>>> @@ -1591,11 +1644,9 @@ drm_atomic_add_affected_planes(struct drm_atomic_commit *state, >>>>>> if (IS_ERR(plane_state)) >>>>>> return PTR_ERR(plane_state); >>>>>> - if (plane_state->color_pipeline) { >>>>>> - ret = drm_atomic_add_affected_colorops(state, plane); >>>>>> - if (ret) >>>>>> - return ret; >>>>>> - } >>>>>> + ret = drm_atomic_add_pipeline_colorops(state, plane); >>>>>> + if (ret) >>>>>> + return ret; >>>>>> } >>>>>> return 0; >>>>>> } >>>>>> @@ -1607,10 +1658,8 @@ EXPORT_SYMBOL(drm_atomic_add_affected_planes); >>>>>> * @plane: DRM plane >>>>>> * >>>>>> * This function walks the current configuration and adds all colorops >>>>>> - * currently used by @plane to the atomic configuration @state. This is useful >>>>>> - * when an atomic commit also needs to check all currently enabled colorop on >>>>>> - * @plane, e.g. when changing the mode. It's also useful when re-enabling a plane >>>>>> - * to avoid special code to force-enable all colorops. >>>>>> + * currently used by @plane to the atomic configuration @state. It's useful >>>>>> + * when re-enabling a plane to avoid special code to force-enable all colorops. >>>>>> * >>>>>> * Since acquiring a colorop state will always also acquire the w/w mutex of the >>>>>> * current plane for that colorop (if there is any) adding all the colorop states for >>>>> >>>> >>> >> > ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] drm/atomic: only add states of active or transient active colorops 2026-06-24 19:01 ` Harry Wentland @ 2026-06-24 20:06 ` John Harrison 0 siblings, 0 replies; 12+ messages in thread From: John Harrison @ 2026-06-24 20:06 UTC (permalink / raw) To: Harry Wentland, Melissa Wen, Borah, Chaitanya Kumar, Jani Nikula, Alex Hung, airlied, maarten.lankhorst, mripard, simona, tzimmermann Cc: Simon Ser, Uma Shankar, Xaver Hugl, Pekka Paalanen, Louis Chauvet, Matthew Schwartz, Rodrigo Siqueira, amd-gfx, kernel-dev, Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten, linux-arm-msm, freedreno, intel-xe, intel-gfx, dri-devel On 6/24/26 21:01, Harry Wentland wrote: > On 2026-06-09 13:23, John Harrison wrote: >> On 6/3/26 04:27, Melissa Wen wrote: >>> On 01/06/2026 11:24, Borah, Chaitanya Kumar wrote: >>>> On 5/29/2026 7:16 PM, Jani Nikula wrote: >>>>> On Tue, 26 May 2026, Alex Hung <alex.hung@amd.com> wrote: >>>>>> On 5/26/26 08:17, Melissa Wen wrote: >>>>>>> Only consider affected colorop states those that are part of an active >>>>>>> color pipeline or a pipeline that is about to be activated or >>>>>>> deactivated in the same atomic commit, i.e., colorop is in the chain of >>>>>>> old/new plane color pipeline property. To cover color_pipeline >>>>>>> deactivation, remove the condition for plane_state->color_pipeline. >>>>>>> >>>>>>> Signed-off-by: Melissa Wen <mwen@igalia.com> >>>>>>> --- >>>>>>> drivers/gpu/drm/drm_atomic.c | 67 +++++++++++++++++++++++++++++++----- >>>>>>> 1 file changed, 58 insertions(+), 9 deletions(-) >>>>>>> >>>>>>> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c >>>>>>> index 170de30c28ae..4fb3a23e862a 100644 >>>>>>> --- a/drivers/gpu/drm/drm_atomic.c >>>>>>> +++ b/drivers/gpu/drm/drm_atomic.c >>>>>>> @@ -812,6 +812,59 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, >>>>>>> return 0; >>>>>>> } >>>>>>> +/* >>>>>>> + * This function walks old and new plane state color pipelines and adds all >>>>>>> + * colorops in use by @plane to the atomic configuration @state. This is useful >>>>>>> + * when an atomic commit needs to check all currently enabled or about to be >>>>>>> + * enabled colorop on @plane, e.g. when changing the mode. This also avoids >>>>>>> + * including colorop states that are not part of the atomic state. >>>>>>> + * >>>>>>> + * Returns: >>>>>>> + * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK >>>>>>> + * then the w/w mutex code has detected a deadlock and the entire atomic >>>>>>> + * sequence must be restarted. All other errors are fatal. >>>>>>> + */ >>>>>>> +static int >>>>>>> +drm_atomic_add_pipeline_colorops(struct drm_atomic_commit *state, >>>>>>> + struct drm_plane *plane) >>>>>>> +{ >>>>>>> + struct drm_colorop *colorop; >>>>>>> + struct drm_colorop_state *colorop_state; >>>>>>> + struct drm_plane_state *new_plane_state, *old_plane_state; >>>>>>> + >>>>>>> + new_plane_state = drm_atomic_get_new_plane_state(state, plane); >>>>>>> + old_plane_state = drm_atomic_get_old_plane_state(state, plane); >>>>>>> + >>>>>>> + if (WARN_ON(!new_plane_state || !old_plane_state)) >>>>>>> + return -EINVAL; >>>>>>> + >>>>>>> + drm_dbg_atomic(plane->dev, >>>>>>> + "Adding old+new pipeline colorops for [PLANE:%d:%s]\n", >>>>>>> + plane->base.id, plane->name); >>>>>>> + >>>>>>> + for (colorop = new_plane_state->color_pipeline; >>>>>>> + colorop; >>>>>>> + colorop = colorop->next) { >>>>>> This for-loop is used 5 times in this patchset. How about a macro in >>>>>> drm_colorop.h? >>>>>> >>>>>> #define drm_for_each_colorop_in_pipeline(colorop, pipeline) \ >>>>>> for ((colorop) = (pipeline); (colorop); (colorop) = (colorop)->next) >>>>> Is there a reason struct drm_colorop reinvents lists and doesn't have >>>>> struct list_head node? >>>>> >>>> I believe that's because the "next" colorop is exposed as a property (of the current colorop) to userspace. Since the chain is already described by the property, a struct list_head would be redundant. >>> Also, each color pipeline is an immutable chain of colorops where the sequence and position matter: once the chain is built, colorops are never added, removed, replaced or walked in reverse. It's a forward-only chain that ends when next == NULL, and it directly matches userspace mapping. Another point to take into account is that there is no struct drm_color_pipeline to hold a list_head yet, since each color pipeline is identified by the first colorop element in the chain. Maybe we will want a container to link a given pre-blend color pipeline to a specific post-blend color pipeline for example, but linking pre- to post-blend color pipelines is something we are still not clear about. >>> >>> Melissa >>> >> "there is no struct drm_color_pipeline to hold a list_head" <-- I think this is the real reason. It is possible to convert to use a proper list structure, but the result is slightly messy. I had a quick go at it to see how messy: >> https://patchwork.freedesktop.org/series/168200/ >> > Yeah, Melissa and Chaitanya pretty much described why they work the way they do. I'm not sure it makes sense to replace the mechanism with lists and any attempt to do so should make sure not to break userspace ABI. I'm not opposed to improvements either if anyone finds a solution that makes everyone's lives easier. > > Harry @Harry, the patch series I linked above does the conversion. It does not affect the user space ABI at all, only the internal kernel operation is changed. I think it is better in some ways but maybe not in others. If you would like to take a look, any feedback would be appreciated. Thanks, John. > >> John. >> >>>> Harry, others can chime in. >>>> >>>> == >>>> Chaitanya >>>> >>>>> BR, >>>>> Jani. >>>>> >>>>>>> + colorop_state = drm_atomic_get_colorop_state(state, colorop); >>>>>>> + if (IS_ERR(colorop_state)) >>>>>>> + return PTR_ERR(colorop_state); >>>>>>> + } >>>>>>> + >>>>>>> + /* Same color pipeline as new; no point walking old. */ >>>>>>> + if (new_plane_state->color_pipeline == old_plane_state->color_pipeline) >>>>>>> + return 0; >>>>>>> + >>>>>>> + for (colorop = old_plane_state->color_pipeline; >>>>>>> + colorop; >>>>>>> + colorop = colorop->next) { >>>>>>> + colorop_state = drm_atomic_get_colorop_state(state, colorop); >>>>>>> + if (IS_ERR(colorop_state)) >>>>>>> + return PTR_ERR(colorop_state); >>>>>>> + } >>>>>>> + >>>>>>> + return 0; >>>>>>> +} >>>>>>> + >>>>>>> static void drm_atomic_colorop_print_state(struct drm_printer *p, >>>>>>> const struct drm_colorop_state *state) >>>>>>> { >>>>>>> @@ -1591,11 +1644,9 @@ drm_atomic_add_affected_planes(struct drm_atomic_commit *state, >>>>>>> if (IS_ERR(plane_state)) >>>>>>> return PTR_ERR(plane_state); >>>>>>> - if (plane_state->color_pipeline) { >>>>>>> - ret = drm_atomic_add_affected_colorops(state, plane); >>>>>>> - if (ret) >>>>>>> - return ret; >>>>>>> - } >>>>>>> + ret = drm_atomic_add_pipeline_colorops(state, plane); >>>>>>> + if (ret) >>>>>>> + return ret; >>>>>>> } >>>>>>> return 0; >>>>>>> } >>>>>>> @@ -1607,10 +1658,8 @@ EXPORT_SYMBOL(drm_atomic_add_affected_planes); >>>>>>> * @plane: DRM plane >>>>>>> * >>>>>>> * This function walks the current configuration and adds all colorops >>>>>>> - * currently used by @plane to the atomic configuration @state. This is useful >>>>>>> - * when an atomic commit also needs to check all currently enabled colorop on >>>>>>> - * @plane, e.g. when changing the mode. It's also useful when re-enabling a plane >>>>>>> - * to avoid special code to force-enable all colorops. >>>>>>> + * currently used by @plane to the atomic configuration @state. It's useful >>>>>>> + * when re-enabling a plane to avoid special code to force-enable all colorops. >>>>>>> * >>>>>>> * Since acquiring a colorop state will always also acquire the w/w mutex of the >>>>>>> * current plane for that colorop (if there is any) adding all the colorop states for ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 2/3] drm/atomic: duplicate state of all colorops 2026-05-26 14:17 [PATCH 0/3] don't allow changes to inactive colorops Melissa Wen 2026-05-26 14:17 ` [PATCH 1/3] drm/atomic: only add states of active or transient active colorops Melissa Wen @ 2026-05-26 14:17 ` Melissa Wen 2026-05-26 14:17 ` [PATCH 3/3] drm/atomic: reject colorop update from inactive color pipeline Melissa Wen 2 siblings, 0 replies; 12+ messages in thread From: Melissa Wen @ 2026-05-26 14:17 UTC (permalink / raw) To: airlied, maarten.lankhorst, mripard, simona, tzimmermann Cc: Alex Hung, Simon Ser, Uma Shankar, Chaitanya Kumar Borah, Xaver Hugl, Pekka Paalanen, Louis Chauvet, Matthew Schwartz, John Harrison, Rodrigo Siqueira, amd-gfx, kernel-dev, Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten, linux-arm-msm, freedreno, intel-xe, intel-gfx, dri-devel Userspace expects that colorop settings of an inactive color pipeline persist, so that, when the color pipeline is activated again, colorops previously set preserves their values when it was deactivated. Colorop setup is expected to persist even during a suspend/resume. To snapshot colorop settings correctly, duplicate state of all colorops in a given plane, independent if color pipeline is active or not. Signed-off-by: Melissa Wen <mwen@igalia.com> --- drivers/gpu/drm/drm_atomic_helper.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 51f39edc31ed..ea15e58518fd 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -3752,12 +3752,9 @@ drm_atomic_helper_duplicate_state(struct drm_device *dev, goto free; } - if (plane_state->color_pipeline) { - err = drm_atomic_add_affected_colorops(state, plane); - if (err) - goto free; - } - + err = drm_atomic_add_affected_colorops(state, plane); + if (err) + goto free; } drm_connector_list_iter_begin(dev, &conn_iter); -- 2.53.0 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/3] drm/atomic: reject colorop update from inactive color pipeline 2026-05-26 14:17 [PATCH 0/3] don't allow changes to inactive colorops Melissa Wen 2026-05-26 14:17 ` [PATCH 1/3] drm/atomic: only add states of active or transient active colorops Melissa Wen 2026-05-26 14:17 ` [PATCH 2/3] drm/atomic: duplicate state of all colorops Melissa Wen @ 2026-05-26 14:17 ` Melissa Wen 2026-05-26 23:04 ` Alex Hung 2 siblings, 1 reply; 12+ messages in thread From: Melissa Wen @ 2026-05-26 14:17 UTC (permalink / raw) To: airlied, maarten.lankhorst, mripard, simona, tzimmermann Cc: Alex Hung, Simon Ser, Uma Shankar, Chaitanya Kumar Borah, Xaver Hugl, Pekka Paalanen, Louis Chauvet, Matthew Schwartz, John Harrison, Rodrigo Siqueira, amd-gfx, kernel-dev, Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten, linux-arm-msm, freedreno, intel-xe, intel-gfx, dri-devel Only allow updates on colorops that are part of an active pipeline, i.e. check if a colorop belongs to the color pipeline of a plane in its current, new or old state. If not, reject the state change of this inactive colorop. Performing this check later in drm_atomic_check_only() to remove the ordering dependency that would exist if done at the time of colorop property setting. Userspace is allowed to change colorops of an active color pipeline, or when activating or deactivating its pipeline in the same commit. However, changes in inactive color pipeline is not allowed. Suggested-by: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com> Signed-off-by: Melissa Wen <mwen@igalia.com> --- drivers/gpu/drm/drm_atomic.c | 59 ++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 4fb3a23e862a..a0549435954b 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -865,6 +865,54 @@ drm_atomic_add_pipeline_colorops(struct drm_atomic_commit *state, return 0; } +/** + * drm_atomic_colorop_check - check new colorop state + * @new_colorop_state: new colorop state to check + * + * Ensure that the colorop in @new_colorop_state belongs to an active color + * pipeline, i.e. it's in the chain of colorops set to the color_pipeline + * property of current, old or new plane state. + * + * Returns: 0 on success, -EINVAL otherwise. + */ +static int drm_atomic_colorop_check(const struct drm_colorop_state *new_colorop_state) +{ + struct drm_atomic_commit *state = new_colorop_state->state; + struct drm_plane *plane = new_colorop_state->colorop->plane; + struct drm_plane_state *new_plane_state, *old_plane_state; + struct drm_colorop *colorop; + + new_plane_state = drm_atomic_get_new_plane_state(state, plane); + old_plane_state = drm_atomic_get_old_plane_state(state, plane); + + /* No changes in the plane state. Check current-committed plane state */ + if (!new_plane_state) { + for (colorop = plane->state->color_pipeline; colorop; colorop = colorop->next) + if (colorop == new_colorop_state->colorop) + return 0; + return -EINVAL; + } + + if (WARN_ON(!old_plane_state)) return -EINVAL; + + /* Check if the colorop is active in the new plane state */ + for (colorop = new_plane_state->color_pipeline; colorop; colorop = colorop->next) + if (colorop == new_colorop_state->colorop) + return 0; + + /* Same color pipeline as new; no point walking old. Colorop isn't active */ + if (new_plane_state->color_pipeline == old_plane_state->color_pipeline) + return -EINVAL; + + /* Check if the colorop was active in the old plane state */ + for (colorop = old_plane_state->color_pipeline; colorop; colorop = colorop->next) + if (colorop == new_colorop_state->colorop) + return 0; + + /* Colorop is not part of an active color pipeline. */ + return -EINVAL; +} + static void drm_atomic_colorop_print_state(struct drm_printer *p, const struct drm_colorop_state *state) { @@ -1714,6 +1762,8 @@ int drm_atomic_check_only(struct drm_atomic_commit *state) struct drm_plane *plane; struct drm_plane_state *old_plane_state; struct drm_plane_state *new_plane_state; + struct drm_colorop *colorop; + struct drm_colorop_state *new_colorop_state; struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; struct drm_crtc_state *new_crtc_state; @@ -1730,6 +1780,15 @@ int drm_atomic_check_only(struct drm_atomic_commit *state) requested_crtc |= drm_crtc_mask(crtc); } + for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) { + ret = drm_atomic_colorop_check(new_colorop_state); + if (ret) { + drm_dbg_atomic(dev, "[COLOROP:%d:%d] is not part of an active color pipeline.\n", + colorop->base.id, colorop->type); + return ret; + } + } + for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { ret = drm_atomic_plane_check(old_plane_state, new_plane_state); if (ret) { -- 2.53.0 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 3/3] drm/atomic: reject colorop update from inactive color pipeline 2026-05-26 14:17 ` [PATCH 3/3] drm/atomic: reject colorop update from inactive color pipeline Melissa Wen @ 2026-05-26 23:04 ` Alex Hung 0 siblings, 0 replies; 12+ messages in thread From: Alex Hung @ 2026-05-26 23:04 UTC (permalink / raw) To: Melissa Wen, airlied, maarten.lankhorst, mripard, simona, tzimmermann Cc: Simon Ser, Uma Shankar, Chaitanya Kumar Borah, Xaver Hugl, Pekka Paalanen, Louis Chauvet, Matthew Schwartz, John Harrison, Rodrigo Siqueira, amd-gfx, kernel-dev, Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten, linux-arm-msm, freedreno, intel-xe, intel-gfx, dri-devel On 5/26/26 08:17, Melissa Wen wrote: > Only allow updates on colorops that are part of an active pipeline, i.e. > check if a colorop belongs to the color pipeline of a plane in its > current, new or old state. If not, reject the state change of this > inactive colorop. Performing this check later in drm_atomic_check_only() > to remove the ordering dependency that would exist if done at the time > of colorop property setting. Userspace is allowed to change colorops of > an active color pipeline, or when activating or deactivating its > pipeline in the same commit. However, changes in inactive color pipeline > is not allowed. > > Suggested-by: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com> > Signed-off-by: Melissa Wen <mwen@igalia.com> > --- > drivers/gpu/drm/drm_atomic.c | 59 ++++++++++++++++++++++++++++++++++++ > 1 file changed, 59 insertions(+) > > diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c > index 4fb3a23e862a..a0549435954b 100644 > --- a/drivers/gpu/drm/drm_atomic.c > +++ b/drivers/gpu/drm/drm_atomic.c > @@ -865,6 +865,54 @@ drm_atomic_add_pipeline_colorops(struct drm_atomic_commit *state, > return 0; > } > > +/** > + * drm_atomic_colorop_check - check new colorop state > + * @new_colorop_state: new colorop state to check > + * > + * Ensure that the colorop in @new_colorop_state belongs to an active color > + * pipeline, i.e. it's in the chain of colorops set to the color_pipeline > + * property of current, old or new plane state. > + * > + * Returns: 0 on success, -EINVAL otherwise. > + */ > +static int drm_atomic_colorop_check(const struct drm_colorop_state *new_colorop_state) > +{ > + struct drm_atomic_commit *state = new_colorop_state->state; > + struct drm_plane *plane = new_colorop_state->colorop->plane; > + struct drm_plane_state *new_plane_state, *old_plane_state; > + struct drm_colorop *colorop; > + > + new_plane_state = drm_atomic_get_new_plane_state(state, plane); > + old_plane_state = drm_atomic_get_old_plane_state(state, plane); > + > + /* No changes in the plane state. Check current-committed plane state */ > + if (!new_plane_state) { > + for (colorop = plane->state->color_pipeline; colorop; colorop = colorop->next) > + if (colorop == new_colorop_state->colorop) > + return 0; > + return -EINVAL; > + } > + > + if (WARN_ON(!old_plane_state)) return -EINVAL; return should be in a new line. > + > + /* Check if the colorop is active in the new plane state */ > + for (colorop = new_plane_state->color_pipeline; colorop; colorop = colorop->next) > + if (colorop == new_colorop_state->colorop) > + return 0; > + > + /* Same color pipeline as new; no point walking old. Colorop isn't active */ > + if (new_plane_state->color_pipeline == old_plane_state->color_pipeline) > + return -EINVAL; > + > + /* Check if the colorop was active in the old plane state */ > + for (colorop = old_plane_state->color_pipeline; colorop; colorop = colorop->next) > + if (colorop == new_colorop_state->colorop) > + return 0; > + > + /* Colorop is not part of an active color pipeline. */ > + return -EINVAL; > +} > + > static void drm_atomic_colorop_print_state(struct drm_printer *p, > const struct drm_colorop_state *state) > { > @@ -1714,6 +1762,8 @@ int drm_atomic_check_only(struct drm_atomic_commit *state) > struct drm_plane *plane; > struct drm_plane_state *old_plane_state; > struct drm_plane_state *new_plane_state; > + struct drm_colorop *colorop; > + struct drm_colorop_state *new_colorop_state; > struct drm_crtc *crtc; > struct drm_crtc_state *old_crtc_state; > struct drm_crtc_state *new_crtc_state; > @@ -1730,6 +1780,15 @@ int drm_atomic_check_only(struct drm_atomic_commit *state) > requested_crtc |= drm_crtc_mask(crtc); > } > > + for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) { > + ret = drm_atomic_colorop_check(new_colorop_state); > + if (ret) { > + drm_dbg_atomic(dev, "[COLOROP:%d:%d] is not part of an active color pipeline.\n", > + colorop->base.id, colorop->type); > + return ret; > + } > + } > + > for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { > ret = drm_atomic_plane_check(old_plane_state, new_plane_state); > if (ret) { ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-06-24 20:07 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-26 14:17 [PATCH 0/3] don't allow changes to inactive colorops Melissa Wen 2026-05-26 14:17 ` [PATCH 1/3] drm/atomic: only add states of active or transient active colorops Melissa Wen 2026-05-26 23:02 ` Alex Hung 2026-05-29 13:46 ` Jani Nikula 2026-06-01 9:24 ` Borah, Chaitanya Kumar 2026-06-03 11:27 ` Melissa Wen 2026-06-09 17:23 ` John Harrison 2026-06-24 19:01 ` Harry Wentland 2026-06-24 20:06 ` John Harrison 2026-05-26 14:17 ` [PATCH 2/3] drm/atomic: duplicate state of all colorops Melissa Wen 2026-05-26 14:17 ` [PATCH 3/3] drm/atomic: reject colorop update from inactive color pipeline Melissa Wen 2026-05-26 23:04 ` Alex Hung
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).