All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Ville Syrjälä" <ville.syrjala@linux.intel.com>
To: Jani Nikula <jani.nikula@linux.intel.com>
Cc: intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org
Subject: Re: [PATCH] drm/i915: Walk crtcs in pipe order
Date: Thu, 20 Nov 2025 20:42:16 +0200	[thread overview]
Message-ID: <aR9hCIHDIJKtt_Su@intel.com> (raw)
In-Reply-To: <add11487eaa3a418d199d8f9b851e4dfbad0cf25@intel.com>

On Thu, Nov 20, 2025 at 07:47:54PM +0200, Jani Nikula wrote:
> On Thu, 20 Nov 2025, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Currently our crtcs are registered in pipe order, and thus
> > all the for_intel_crtc*() iterators walk the crtcs in pipe
> > order. There are a bunch of places that more or less depend
> > on that. Eg. during plane updates and such we want joined
> > pipes to be processed back-to-back to give a better chance
> > of an atomic update across the whole set.
> >
> > When we start to register crtcs in a different order we don't
> > want to change the order in which the pipes get handled.
> > Decouple the for_each_intel_crtc*() iterators from the crtc
> > registration order by using a separate list which will be
> > sorted by the pipe rather than the crtc index.
> >
> > We could priobably use a simple array or something, but that
> > would require some kind of extra iterator variable for the
> > macros, and thus would require a lot more changes. Using
> > a linked list keeps the fallout minimal. We can look at
> > using a more optimal data structure later.
> 
> I think the list works fine.

I supose. Though we do walk these a lot, and we might be
hitting a few more cachelines now, but hopefully they
remain clean so there's no ping-pong between CPUs...

> 
> > I also added this extra junk to the atomic state iterators:
> > "(__i) = drm_crtc_index(&(crtc)->base), (void)(__i)"
> > even though the macro itself no longer needs the "__i" iterator.
> > This in case the "__i" is used by the caller, and to
> > avoid compiler warnings if it's completely unused now.
> 
> At a glance, I can't find any. Perhaps you could cook up some cocci to
> remove the parameter as follow-up?

IIRC I already took some kind of stab at hiding the __i inside
the macros (using the UNIQUE_ID stuff) but never posted it.
But I guess we can avoid that now. Might have to think about
doing the same to the drm core macros as well.

> 
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_crtc.c     | 20 +++++
> >  drivers/gpu/drm/i915/display/intel_display.h  | 90 ++++++++-----------
> >  .../gpu/drm/i915/display/intel_display_core.h |  3 +
> >  .../drm/i915/display/intel_display_driver.c   |  1 +
> >  .../drm/i915/display/intel_display_types.h    |  1 +
> >  drivers/gpu/drm/xe/display/xe_display.c       |  1 +
> >  6 files changed, 64 insertions(+), 52 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
> > index 153ff4b4b52c..7ebbde716238 100644
> > --- a/drivers/gpu/drm/i915/display/intel_crtc.c
> > +++ b/drivers/gpu/drm/i915/display/intel_crtc.c
> > @@ -209,6 +209,8 @@ static struct intel_crtc *intel_crtc_alloc(void)
> >  	crtc->base.state = &crtc_state->uapi;
> >  	crtc->config = crtc_state;
> >  
> > +	INIT_LIST_HEAD(&crtc->pipe_head);
> > +
> >  	return crtc;
> >  }
> >  
> > @@ -222,6 +224,8 @@ static void intel_crtc_destroy(struct drm_crtc *_crtc)
> >  {
> >  	struct intel_crtc *crtc = to_intel_crtc(_crtc);
> >  
> > +	list_del(&crtc->pipe_head);
> > +
> >  	cpu_latency_qos_remove_request(&crtc->vblank_pm_qos);
> >  
> >  	drm_crtc_cleanup(&crtc->base);
> > @@ -308,6 +312,20 @@ static const struct drm_crtc_funcs i8xx_crtc_funcs = {
> >  	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> >  };
> >  
> > +static void add_crtc_to_pipe_list(struct intel_display *display, struct intel_crtc *crtc)
> > +{
> > +	struct intel_crtc *iter;
> > +
> > +	list_for_each_entry(iter, &display->pipe_list, pipe_head) {
> > +		if (iter->pipe > crtc->pipe) {
> 
> Nitpick, somehow I found it easier to think of this in reverse order,
> "crtc->pipe < iter->pipe", but could be just me. *shrug*.

Yeah, I suppose that might be better. Would at least match the order
of arguments to list_add_tail(), which does match the order they
end up on the list.

> 
> > +			list_add_tail(&crtc->pipe_head, &iter->pipe_head);
> > +			return;
> > +		}
> > +	}
> > +
> > +	list_add_tail(&crtc->pipe_head, &display->pipe_list);
> > +}
> > +
> >  int intel_crtc_init(struct intel_display *display, enum pipe pipe)
> >  {
> >  	struct intel_plane *primary, *cursor;
> > @@ -398,6 +416,8 @@ int intel_crtc_init(struct intel_display *display, enum pipe pipe)
> >  	if (HAS_CASF(display))
> >  		drm_crtc_create_sharpness_strength_property(&crtc->base);
> >  
> > +	add_crtc_to_pipe_list(display, crtc);
> > +
> >  	return 0;
> >  
> >  fail:
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> > index bcc6ccb69d2b..ac83d4f09bb9 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display.h
> > @@ -238,22 +238,23 @@ enum phy_fia {
> >  			    base.head)					\
> >  		for_each_if((intel_plane)->pipe == (intel_crtc)->pipe)
> >  
> > -#define for_each_intel_crtc(dev, intel_crtc)				\
> > -	list_for_each_entry(intel_crtc,					\
> > -			    &(dev)->mode_config.crtc_list,		\
> > -			    base.head)
> > +#define for_each_intel_crtc(dev, crtc) \
> > +	list_for_each_entry((crtc), \
> > +			    &to_intel_display(dev)->pipe_list, \
> > +			    pipe_head)
> >  
> > -#define for_each_intel_crtc_in_pipe_mask(dev, intel_crtc, pipe_mask)	\
> > -	list_for_each_entry(intel_crtc,					\
> > -			    &(dev)->mode_config.crtc_list,		\
> > -			    base.head)					\
> > -		for_each_if((pipe_mask) & BIT(intel_crtc->pipe))
> > +#define for_each_intel_crtc_reverse(dev, crtc) \
> > +	list_for_each_entry_reverse((crtc), \
> > +				    &to_intel_display(dev)->pipe_list, \
> > +				    pipe_head)
> >  
> > -#define for_each_intel_crtc_in_pipe_mask_reverse(dev, intel_crtc, pipe_mask)	\
> > -	list_for_each_entry_reverse((intel_crtc),				\
> > -				    &(dev)->mode_config.crtc_list,		\
> > -				    base.head)					\
> > -		for_each_if((pipe_mask) & BIT((intel_crtc)->pipe))
> > +#define for_each_intel_crtc_in_pipe_mask(dev, crtc, pipe_mask) \
> > +	for_each_intel_crtc((dev), (crtc)) \
> > +		for_each_if((pipe_mask) & BIT((crtc)->pipe))
> > +
> > +#define for_each_intel_crtc_in_pipe_mask_reverse(dev, crtc, pipe_mask) \
> > +	for_each_intel_crtc_reverse((dev), (crtc)) \
> > +		for_each_if((pipe_mask) & BIT((crtc)->pipe))
> >  
> >  #define for_each_intel_encoder(dev, intel_encoder)		\
> >  	list_for_each_entry(intel_encoder,			\
> > @@ -295,14 +296,6 @@ enum phy_fia {
> >  	     (__i)++) \
> >  		for_each_if(plane)
> >  
> > -#define for_each_old_intel_crtc_in_state(__state, crtc, old_crtc_state, __i) \
> > -	for ((__i) = 0; \
> > -	     (__i) < (__state)->base.dev->mode_config.num_crtc && \
> > -		     ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
> > -		      (old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), 1); \
> > -	     (__i)++) \
> > -		for_each_if(crtc)
> > -
> >  #define for_each_new_intel_plane_in_state(__state, plane, new_plane_state, __i) \
> >  	for ((__i) = 0; \
> >  	     (__i) < (__state)->base.dev->mode_config.num_total_plane && \
> > @@ -311,22 +304,6 @@ enum phy_fia {
> >  	     (__i)++) \
> >  		for_each_if(plane)
> >  
> > -#define for_each_new_intel_crtc_in_state(__state, crtc, new_crtc_state, __i) \
> > -	for ((__i) = 0; \
> > -	     (__i) < (__state)->base.dev->mode_config.num_crtc && \
> > -		     ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
> > -		      (new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \
> > -	     (__i)++) \
> > -		for_each_if(crtc)
> > -
> > -#define for_each_new_intel_crtc_in_state_reverse(__state, crtc, new_crtc_state, __i) \
> > -	for ((__i) = (__state)->base.dev->mode_config.num_crtc - 1; \
> > -	     (__i) >= 0  && \
> > -	     ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
> > -	      (new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \
> > -	     (__i)--) \
> > -		for_each_if(crtc)
> > -
> >  #define for_each_oldnew_intel_plane_in_state(__state, plane, old_plane_state, new_plane_state, __i) \
> >  	for ((__i) = 0; \
> >  	     (__i) < (__state)->base.dev->mode_config.num_total_plane && \
> > @@ -336,23 +313,32 @@ enum phy_fia {
> >  	     (__i)++) \
> >  		for_each_if(plane)
> >  
> > +#define for_each_old_intel_crtc_in_state(__state, crtc, old_crtc_state, __i) \
> > +	for_each_intel_crtc((__state)->base.dev, (crtc)) \
> > +		for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
> > +			     (old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc))))
> > +
> > +#define for_each_new_intel_crtc_in_state(__state, crtc, new_crtc_state, __i) \
> > +	for_each_intel_crtc((__state)->base.dev, (crtc)) \
> > +		for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
> > +			     (new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc))))
> > +
> > +#define for_each_new_intel_crtc_in_state_reverse(__state, crtc, new_crtc_state, __i) \
> > +	for_each_intel_crtc_reverse((__state)->base.dev, (crtc)) \
> > +		for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
> > +			     (new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc))))
> > +
> >  #define for_each_oldnew_intel_crtc_in_state(__state, crtc, old_crtc_state, new_crtc_state, __i) \
> > -	for ((__i) = 0; \
> > -	     (__i) < (__state)->base.dev->mode_config.num_crtc && \
> > -		     ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
> > -		      (old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), \
> > -		      (new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \
> > -	     (__i)++) \
> > -		for_each_if(crtc)
> > +	for_each_intel_crtc((__state)->base.dev, (crtc)) \
> > +		for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
> > +			     (old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc)), \
> > +			     (new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc))))
> >  
> >  #define for_each_oldnew_intel_crtc_in_state_reverse(__state, crtc, old_crtc_state, new_crtc_state, __i) \
> > -	for ((__i) = (__state)->base.dev->mode_config.num_crtc - 1; \
> > -	     (__i) >= 0  && \
> > -	     ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
> > -	      (old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), \
> > -	      (new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \
> > -	     (__i)--) \
> > -		for_each_if(crtc)
> > +	for_each_intel_crtc_reverse((__state)->base.dev, (crtc)) \
> > +		for_each_if(((__i) = drm_crtc_index(&(crtc)->base), (void)(__i), \
> > +			     (old_crtc_state) = intel_atomic_get_old_crtc_state((__state), (crtc)), \
> > +			     (new_crtc_state) = intel_atomic_get_new_crtc_state((__state), (crtc))))
> 
> These were a PITA to go through, but I think it's fine. Knocks wood.
> 
> Thanks for doing this.
> 
> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
> 
> >  
> >  #define intel_atomic_crtc_state_for_each_plane_state( \
> >  		  plane, plane_state, \
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
> > index 9b8414b77c15..4f4d5c314394 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_core.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display_core.h
> > @@ -294,6 +294,9 @@ struct intel_display {
> >  	/* Parent, or core, driver functions exposed to display */
> >  	const struct intel_display_parent_interface *parent;
> >  
> > +	/* list of all intel_crtcs sorted by pipe */
> > +	struct list_head pipe_list;
> > +
> >  	/* Display functions */
> >  	struct {
> >  		/* Top level crtc-ish functions */
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c
> > index 7e000ba3e08b..32726906e550 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_driver.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c
> > @@ -119,6 +119,7 @@ static void intel_mode_config_init(struct intel_display *display)
> >  
> >  	drm_mode_config_init(display->drm);
> >  	INIT_LIST_HEAD(&display->global.obj_list);
> > +	INIT_LIST_HEAD(&display->pipe_list);
> >  
> >  	mode_config->min_width = 0;
> >  	mode_config->min_height = 0;
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> > index 38702a9e0f50..1c2bd9445795 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> > @@ -1441,6 +1441,7 @@ struct intel_flipq {
> >  
> >  struct intel_crtc {
> >  	struct drm_crtc base;
> > +	struct list_head pipe_head;
> >  	enum pipe pipe;
> >  	/*
> >  	 * Whether the crtc and the connected output pipeline is active. Implies
> > diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c
> > index e3320d9e6314..cfcbc7dd8638 100644
> > --- a/drivers/gpu/drm/xe/display/xe_display.c
> > +++ b/drivers/gpu/drm/xe/display/xe_display.c
> > @@ -22,6 +22,7 @@
> >  #include "intel_audio.h"
> >  #include "intel_bw.h"
> >  #include "intel_display.h"
> > +#include "intel_display_core.h"
> >  #include "intel_display_device.h"
> >  #include "intel_display_driver.h"
> >  #include "intel_display_irq.h"
> 
> -- 
> Jani Nikula, Intel

-- 
Ville Syrjälä
Intel

  reply	other threads:[~2025-11-20 18:42 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-20 14:49 [PATCH] drm/i915: Walk crtcs in pipe order Ville Syrjala
2025-11-20 16:12 ` ✓ i915.CI.BAT: success for " Patchwork
2025-11-20 16:45 ` ✗ CI.checkpatch: warning " Patchwork
2025-11-20 16:46 ` ✓ CI.KUnit: success " Patchwork
2025-11-20 17:43 ` ✓ Xe.CI.BAT: " Patchwork
2025-11-20 17:47 ` [PATCH] " Jani Nikula
2025-11-20 18:42   ` Ville Syrjälä [this message]
2025-11-20 19:21 ` [PATCH v2] " Ville Syrjala
2026-04-08 12:02   ` Jani Nikula
2025-11-20 20:31 ` ✓ i915.CI.BAT: success for drm/i915: Walk crtcs in pipe order (rev2) Patchwork
2025-11-20 21:50 ` ✗ Xe.CI.Full: failure for drm/i915: Walk crtcs in pipe order Patchwork
2025-11-20 22:49 ` ✗ CI.checkpatch: warning for drm/i915: Walk crtcs in pipe order (rev2) Patchwork
2025-11-20 22:50 ` ✓ CI.KUnit: success " Patchwork
2025-11-20 23:29 ` ✓ Xe.CI.BAT: " Patchwork
2025-11-21  3:13 ` ✓ i915.CI.Full: success for drm/i915: Walk crtcs in pipe order Patchwork
2025-11-21  4:19 ` ✗ Xe.CI.Full: failure for drm/i915: Walk crtcs in pipe order (rev2) Patchwork
2025-11-21  4:48 ` ✗ i915.CI.Full: " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aR9hCIHDIJKtt_Su@intel.com \
    --to=ville.syrjala@linux.intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=jani.nikula@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.