diff mbox

[RFC] drm/i915: fix potential dangling else problems in for_each_ macros

Message ID 1448386585-4144-1-git-send-email-jani.nikula@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jani Nikula Nov. 24, 2015, 5:36 p.m. UTC
We have serious dangling else bugs waiting to happen in our for_each_
style macros with ifs. Consider, for example,

 #define for_each_power_domain(domain, mask)                         \
         for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \
                 for_each_if ((1 << (domain)) & (mask))

If this is used in context:

	if (condition)
		for_each_power_domain(domain, mask);
	else
		foo();

foo() will be called for each domain *not* in mask, if condition holds,
and not at all if condition doesn't hold.

Fix this by reversing the conditions in the macros, and adding an else
branch for the "for each" block, so that other if/else blocks can't
interfere. Provide a "for_each_if" helper macro to make it easier to get
this right.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h         | 14 ++++++++------
 drivers/gpu/drm/i915/intel_display.c    |  2 +-
 drivers/gpu/drm/i915/intel_dsi.h        |  2 +-
 drivers/gpu/drm/i915/intel_runtime_pm.c |  4 ++--
 4 files changed, 12 insertions(+), 10 deletions(-)

Comments

Jani Nikula Nov. 24, 2015, 5:38 p.m. UTC | #1
On Tue, 24 Nov 2015, Jani Nikula <jani.nikula@intel.com> wrote:
> We have serious dangling else bugs waiting to happen in our for_each_
> style macros with ifs. Consider, for example,
>
>  #define for_each_power_domain(domain, mask)                         \
>          for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \
>                  for_each_if ((1 << (domain)) & (mask))

Blah, copy-paste from after the patch, should be s/for_each_if/if/

>
> If this is used in context:
>
> 	if (condition)
> 		for_each_power_domain(domain, mask);
> 	else
> 		foo();
>
> foo() will be called for each domain *not* in mask, if condition holds,
> and not at all if condition doesn't hold.
>
> Fix this by reversing the conditions in the macros, and adding an else
> branch for the "for each" block, so that other if/else blocks can't
> interfere. Provide a "for_each_if" helper macro to make it easier to get
> this right.
>
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h         | 14 ++++++++------
>  drivers/gpu/drm/i915/intel_display.c    |  2 +-
>  drivers/gpu/drm/i915/intel_dsi.h        |  2 +-
>  drivers/gpu/drm/i915/intel_runtime_pm.c |  4 ++--
>  4 files changed, 12 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 3d8741eff7d3..f9c779fd84ad 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -263,6 +263,8 @@ struct i915_hotplug {
>  	 I915_GEM_DOMAIN_INSTRUCTION | \
>  	 I915_GEM_DOMAIN_VERTEX)
>  
> +#define for_each_if(condition) if (!(condition)); else
> +
>  #define for_each_pipe(__dev_priv, __p) \
>  	for ((__p) = 0; (__p) < INTEL_INFO(__dev_priv)->num_pipes; (__p)++)
>  #define for_each_plane(__dev_priv, __pipe, __p)				\
> @@ -286,7 +288,7 @@ struct i915_hotplug {
>  	list_for_each_entry(intel_plane,				\
>  			    &(dev)->mode_config.plane_list,		\
>  			    base.head)					\
> -		if ((intel_plane)->pipe == (intel_crtc)->pipe)
> +		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)
> @@ -303,15 +305,15 @@ struct i915_hotplug {
>  
>  #define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \
>  	list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
> -		if ((intel_encoder)->base.crtc == (__crtc))
> +		for_each_if ((intel_encoder)->base.crtc == (__crtc))
>  
>  #define for_each_connector_on_encoder(dev, __encoder, intel_connector) \
>  	list_for_each_entry((intel_connector), &(dev)->mode_config.connector_list, base.head) \
> -		if ((intel_connector)->base.encoder == (__encoder))
> +		for_each_if ((intel_connector)->base.encoder == (__encoder))
>  
>  #define for_each_power_domain(domain, mask)				\
>  	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
> -		if ((1 << (domain)) & (mask))
> +		for_each_if ((1 << (domain)) & (mask))
>  
>  struct drm_i915_private;
>  struct i915_mm_struct;
> @@ -730,7 +732,7 @@ struct intel_uncore {
>  	for ((i__) = 0, (domain__) = &(dev_priv__)->uncore.fw_domain[0]; \
>  	     (i__) < FW_DOMAIN_ID_COUNT; \
>  	     (i__)++, (domain__) = &(dev_priv__)->uncore.fw_domain[i__]) \
> -		if (((mask__) & (dev_priv__)->uncore.fw_domains) & (1 << (i__)))
> +		for_each_if (((mask__) & (dev_priv__)->uncore.fw_domains) & (1 << (i__)))
>  
>  #define for_each_fw_domain(domain__, dev_priv__, i__) \
>  	for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
> @@ -1969,7 +1971,7 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc)
>  /* Iterate over initialised rings */
>  #define for_each_ring(ring__, dev_priv__, i__) \
>  	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
> -		if (((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))
> +		for_each_if ((((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__))))
>  
>  enum hdmi_force_audio {
>  	HDMI_AUDIO_OFF_DVI = -2,	/* no aux data for HDMI-DVI converter */
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 75f03e5bee51..4b21d5e137dc 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -12417,7 +12417,7 @@ static bool intel_fuzzy_clock_check(int clock1, int clock2)
>  	list_for_each_entry((intel_crtc), \
>  			    &(dev)->mode_config.crtc_list, \
>  			    base.head) \
> -		if (mask & (1 <<(intel_crtc)->pipe))
> +		for_each_if (mask & (1 <<(intel_crtc)->pipe))
>  
>  static bool
>  intel_compare_m_n(unsigned int m, unsigned int n,
> diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h
> index e6cb25239941..02551ff228c2 100644
> --- a/drivers/gpu/drm/i915/intel_dsi.h
> +++ b/drivers/gpu/drm/i915/intel_dsi.h
> @@ -117,7 +117,7 @@ static inline struct intel_dsi_host *to_intel_dsi_host(struct mipi_dsi_host *h)
>  
>  #define for_each_dsi_port(__port, __ports_mask) \
>  	for ((__port) = PORT_A; (__port) < I915_MAX_PORTS; (__port)++)	\
> -		if ((__ports_mask) & (1 << (__port)))
> +		for_each_if ((__ports_mask) & (1 << (__port)))
>  
>  static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder)
>  {
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index 3fa43af94946..469927edf459 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -54,13 +54,13 @@
>  	     i < (power_domains)->power_well_count &&			\
>  		 ((power_well) = &(power_domains)->power_wells[i]);	\
>  	     i++)							\
> -		if ((power_well)->domains & (domain_mask))
> +		for_each_if ((power_well)->domains & (domain_mask))
>  
>  #define for_each_power_well_rev(i, power_well, domain_mask, power_domains) \
>  	for (i = (power_domains)->power_well_count - 1;			 \
>  	     i >= 0 && ((power_well) = &(power_domains)->power_wells[i]);\
>  	     i--)							 \
> -		if ((power_well)->domains & (domain_mask))
> +		for_each_if ((power_well)->domains & (domain_mask))
>  
>  bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
>  				    int power_well_id);
Daniel Vetter Nov. 24, 2015, 6:25 p.m. UTC | #2
On Tue, Nov 24, 2015 at 07:36:25PM +0200, Jani Nikula wrote:
> We have serious dangling else bugs waiting to happen in our for_each_
> style macros with ifs. Consider, for example,
> 
>  #define for_each_power_domain(domain, mask)                         \
>          for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \
>                  for_each_if ((1 << (domain)) & (mask))
> 
> If this is used in context:
> 
> 	if (condition)
> 		for_each_power_domain(domain, mask);
> 	else
> 		foo();
> 
> foo() will be called for each domain *not* in mask, if condition holds,
> and not at all if condition doesn't hold.
> 
> Fix this by reversing the conditions in the macros, and adding an else
> branch for the "for each" block, so that other if/else blocks can't
> interfere. Provide a "for_each_if" helper macro to make it easier to get
> this right.
> 
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>

There's a shocking amount of these in drm core too. Just looking through
drm_crtc.h finds plenty.

Care to respin with that included (and for_each_if move to drmP.h or
something like that)?

On the i915 parts meanwhile:

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/i915/i915_drv.h         | 14 ++++++++------
>  drivers/gpu/drm/i915/intel_display.c    |  2 +-
>  drivers/gpu/drm/i915/intel_dsi.h        |  2 +-
>  drivers/gpu/drm/i915/intel_runtime_pm.c |  4 ++--
>  4 files changed, 12 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 3d8741eff7d3..f9c779fd84ad 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -263,6 +263,8 @@ struct i915_hotplug {
>  	 I915_GEM_DOMAIN_INSTRUCTION | \
>  	 I915_GEM_DOMAIN_VERTEX)
>  
> +#define for_each_if(condition) if (!(condition)); else
> +
>  #define for_each_pipe(__dev_priv, __p) \
>  	for ((__p) = 0; (__p) < INTEL_INFO(__dev_priv)->num_pipes; (__p)++)
>  #define for_each_plane(__dev_priv, __pipe, __p)				\
> @@ -286,7 +288,7 @@ struct i915_hotplug {
>  	list_for_each_entry(intel_plane,				\
>  			    &(dev)->mode_config.plane_list,		\
>  			    base.head)					\
> -		if ((intel_plane)->pipe == (intel_crtc)->pipe)
> +		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)
> @@ -303,15 +305,15 @@ struct i915_hotplug {
>  
>  #define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \
>  	list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
> -		if ((intel_encoder)->base.crtc == (__crtc))
> +		for_each_if ((intel_encoder)->base.crtc == (__crtc))
>  
>  #define for_each_connector_on_encoder(dev, __encoder, intel_connector) \
>  	list_for_each_entry((intel_connector), &(dev)->mode_config.connector_list, base.head) \
> -		if ((intel_connector)->base.encoder == (__encoder))
> +		for_each_if ((intel_connector)->base.encoder == (__encoder))
>  
>  #define for_each_power_domain(domain, mask)				\
>  	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
> -		if ((1 << (domain)) & (mask))
> +		for_each_if ((1 << (domain)) & (mask))
>  
>  struct drm_i915_private;
>  struct i915_mm_struct;
> @@ -730,7 +732,7 @@ struct intel_uncore {
>  	for ((i__) = 0, (domain__) = &(dev_priv__)->uncore.fw_domain[0]; \
>  	     (i__) < FW_DOMAIN_ID_COUNT; \
>  	     (i__)++, (domain__) = &(dev_priv__)->uncore.fw_domain[i__]) \
> -		if (((mask__) & (dev_priv__)->uncore.fw_domains) & (1 << (i__)))
> +		for_each_if (((mask__) & (dev_priv__)->uncore.fw_domains) & (1 << (i__)))
>  
>  #define for_each_fw_domain(domain__, dev_priv__, i__) \
>  	for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
> @@ -1969,7 +1971,7 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc)
>  /* Iterate over initialised rings */
>  #define for_each_ring(ring__, dev_priv__, i__) \
>  	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
> -		if (((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))
> +		for_each_if ((((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__))))
>  
>  enum hdmi_force_audio {
>  	HDMI_AUDIO_OFF_DVI = -2,	/* no aux data for HDMI-DVI converter */
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 75f03e5bee51..4b21d5e137dc 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -12417,7 +12417,7 @@ static bool intel_fuzzy_clock_check(int clock1, int clock2)
>  	list_for_each_entry((intel_crtc), \
>  			    &(dev)->mode_config.crtc_list, \
>  			    base.head) \
> -		if (mask & (1 <<(intel_crtc)->pipe))
> +		for_each_if (mask & (1 <<(intel_crtc)->pipe))
>  
>  static bool
>  intel_compare_m_n(unsigned int m, unsigned int n,
> diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h
> index e6cb25239941..02551ff228c2 100644
> --- a/drivers/gpu/drm/i915/intel_dsi.h
> +++ b/drivers/gpu/drm/i915/intel_dsi.h
> @@ -117,7 +117,7 @@ static inline struct intel_dsi_host *to_intel_dsi_host(struct mipi_dsi_host *h)
>  
>  #define for_each_dsi_port(__port, __ports_mask) \
>  	for ((__port) = PORT_A; (__port) < I915_MAX_PORTS; (__port)++)	\
> -		if ((__ports_mask) & (1 << (__port)))
> +		for_each_if ((__ports_mask) & (1 << (__port)))
>  
>  static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder)
>  {
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index 3fa43af94946..469927edf459 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -54,13 +54,13 @@
>  	     i < (power_domains)->power_well_count &&			\
>  		 ((power_well) = &(power_domains)->power_wells[i]);	\
>  	     i++)							\
> -		if ((power_well)->domains & (domain_mask))
> +		for_each_if ((power_well)->domains & (domain_mask))
>  
>  #define for_each_power_well_rev(i, power_well, domain_mask, power_domains) \
>  	for (i = (power_domains)->power_well_count - 1;			 \
>  	     i >= 0 && ((power_well) = &(power_domains)->power_wells[i]);\
>  	     i--)							 \
> -		if ((power_well)->domains & (domain_mask))
> +		for_each_if ((power_well)->domains & (domain_mask))
>  
>  bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
>  				    int power_well_id);
> -- 
> 2.1.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Chris Wilson Nov. 24, 2015, 10:26 p.m. UTC | #3
On Tue, Nov 24, 2015 at 07:36:25PM +0200, Jani Nikula wrote:
>  /* Iterate over initialised rings */
>  #define for_each_ring(ring__, dev_priv__, i__) \
>  	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
> -		if (((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))
> +		for_each_if ((((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__))))

Idly wondering if we would be happy with

for_each_ring(ring__, dev_priv__)
	for ((ring__) = &(dev_priv__)->ring[0];
	     (ring__) <= &(dev_priv__)->ring[I915_NUM_RINGS];
	     (ring__)++)
	     for_each_if(intel_ring_initialized(ring__))

?

The downside is that we have used i__ in several places rather than
ring->id.
-Chris
Chris Wilson Nov. 24, 2015, 11:47 p.m. UTC | #4
On Tue, Nov 24, 2015 at 10:26:01PM +0000, Chris Wilson wrote:
> On Tue, Nov 24, 2015 at 07:36:25PM +0200, Jani Nikula wrote:
> >  /* Iterate over initialised rings */
> >  #define for_each_ring(ring__, dev_priv__, i__) \
> >  	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
> > -		if (((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))
> > +		for_each_if ((((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__))))
> 
> Idly wondering if we would be happy with
> 
> for_each_ring(ring__, dev_priv__)
> 	for ((ring__) = &(dev_priv__)->ring[0];
> 	     (ring__) <= &(dev_priv__)->ring[I915_NUM_RINGS];
> 	     (ring__)++)
> 	     for_each_if(intel_ring_initialized(ring__))
> 
> ?
> 
> The downside is that we have used i__ in several places rather than
> ring->id.

Fwiw, 13 files changed, 113 insertions(+), 140 deletions(-)

Seems a reasonable shrinkage.
-Chris
Jani Nikula Nov. 25, 2015, 9:10 a.m. UTC | #5
On Wed, 25 Nov 2015, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> On Tue, Nov 24, 2015 at 10:26:01PM +0000, Chris Wilson wrote:
>> On Tue, Nov 24, 2015 at 07:36:25PM +0200, Jani Nikula wrote:
>> >  /* Iterate over initialised rings */
>> >  #define for_each_ring(ring__, dev_priv__, i__) \
>> >  	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
>> > -		if (((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))
>> > +		for_each_if ((((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__))))
>> 
>> Idly wondering if we would be happy with
>> 
>> for_each_ring(ring__, dev_priv__)
>> 	for ((ring__) = &(dev_priv__)->ring[0];
>> 	     (ring__) <= &(dev_priv__)->ring[I915_NUM_RINGS];
>> 	     (ring__)++)
>> 	     for_each_if(intel_ring_initialized(ring__))
>> 
>> ?
>> 
>> The downside is that we have used i__ in several places rather than
>> ring->id.
>
> Fwiw, 13 files changed, 113 insertions(+), 140 deletions(-)

Seems good, looks like you have the patch so I won't bother. v2 of my
patch was merged to drm-misc now, so that complicates a bit. Perhaps the
i__ to ring->id change could be a prep step. *shrug*.

BR,
Jani.



>
> Seems a reasonable shrinkage.
> -Chris
Daniel Vetter Nov. 25, 2015, 9:23 a.m. UTC | #6
On Tue, Nov 24, 2015 at 11:47:26PM +0000, Chris Wilson wrote:
> On Tue, Nov 24, 2015 at 10:26:01PM +0000, Chris Wilson wrote:
> > On Tue, Nov 24, 2015 at 07:36:25PM +0200, Jani Nikula wrote:
> > >  /* Iterate over initialised rings */
> > >  #define for_each_ring(ring__, dev_priv__, i__) \
> > >  	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
> > > -		if (((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))
> > > +		for_each_if ((((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__))))
> > 
> > Idly wondering if we would be happy with
> > 
> > for_each_ring(ring__, dev_priv__)
> > 	for ((ring__) = &(dev_priv__)->ring[0];
> > 	     (ring__) <= &(dev_priv__)->ring[I915_NUM_RINGS];
> > 	     (ring__)++)
> > 	     for_each_if(intel_ring_initialized(ring__))
> > 
> > ?
> > 
> > The downside is that we have used i__ in several places rather than
> > ring->id.
> 
> Fwiw, 13 files changed, 113 insertions(+), 140 deletions(-)
> 
> Seems a reasonable shrinkage.

Maybe for_each_engine even, and phase out for_each_ring completely?
-Daniel
Dave Gordon Dec. 2, 2015, 1:29 p.m. UTC | #7
On 25/11/15 09:23, Daniel Vetter wrote:
> On Tue, Nov 24, 2015 at 11:47:26PM +0000, Chris Wilson wrote:
>> On Tue, Nov 24, 2015 at 10:26:01PM +0000, Chris Wilson wrote:
>>> On Tue, Nov 24, 2015 at 07:36:25PM +0200, Jani Nikula wrote:
>>>>   /* Iterate over initialised rings */
>>>>   #define for_each_ring(ring__, dev_priv__, i__) \
>>>>   	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
>>>> -		if (((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))
>>>> +		for_each_if ((((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__))))
>>>
>>> Idly wondering if we would be happy with
>>>
>>> for_each_ring(ring__, dev_priv__)
>>> 	for ((ring__) = &(dev_priv__)->ring[0];
>>> 	     (ring__) <= &(dev_priv__)->ring[I915_NUM_RINGS];
>>> 	     (ring__)++)
>>> 	     for_each_if(intel_ring_initialized(ring__))
>>>
>>> ?
>>>
>>> The downside is that we have used i__ in several places rather than
>>> ring->id.
>>
>> Fwiw, 13 files changed, 113 insertions(+), 140 deletions(-)
>>
>> Seems a reasonable shrinkage.
>
> Maybe for_each_engine even, and phase out for_each_ring completely?
> -Daniel
>

Wouldn't it be nicer (and safer) not to build macros that fold the loop 
structure into the macro (in contravention of kernel programming 
guidelines).

So how about NOT including the actual for() inside the macro, so that 
instead of writing

	for_each_engine(engine, dev_priv)
		do_stuff(engine)

we would write it as

	for (EACH_ENGINE(engine, dev_priv))
		initialise(engine)

	for (EACH_ACTIVE_ENGINE(engine, dev_priv)) {
		service(engine)
		restart(engine)
	}

etc. The for-loop is visible and the scope doesn't give you any surprises.

[The EACH_ENGINE() macros expands to a semicolon-separated triplet of 
expressions; still a violation of the "don't use macros to redefine C 
syntax" guideline, but much less egregious than macros that contain 
embedded 'for's and 'if's.

.Dave.
Chris Wilson Dec. 2, 2015, 1:46 p.m. UTC | #8
On Wed, Dec 02, 2015 at 01:29:21PM +0000, Dave Gordon wrote:
> On 25/11/15 09:23, Daniel Vetter wrote:
> >On Tue, Nov 24, 2015 at 11:47:26PM +0000, Chris Wilson wrote:
> >>On Tue, Nov 24, 2015 at 10:26:01PM +0000, Chris Wilson wrote:
> >>>On Tue, Nov 24, 2015 at 07:36:25PM +0200, Jani Nikula wrote:
> >>>>  /* Iterate over initialised rings */
> >>>>  #define for_each_ring(ring__, dev_priv__, i__) \
> >>>>  	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
> >>>>-		if (((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))
> >>>>+		for_each_if ((((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__))))
> >>>
> >>>Idly wondering if we would be happy with
> >>>
> >>>for_each_ring(ring__, dev_priv__)
> >>>	for ((ring__) = &(dev_priv__)->ring[0];
> >>>	     (ring__) <= &(dev_priv__)->ring[I915_NUM_RINGS];
> >>>	     (ring__)++)
> >>>	     for_each_if(intel_ring_initialized(ring__))
> >>>
> >>>?
> >>>
> >>>The downside is that we have used i__ in several places rather than
> >>>ring->id.
> >>
> >>Fwiw, 13 files changed, 113 insertions(+), 140 deletions(-)
> >>
> >>Seems a reasonable shrinkage.
> >
> >Maybe for_each_engine even, and phase out for_each_ring completely?
> >-Daniel
> >
> 
> Wouldn't it be nicer (and safer) not to build macros that fold the
> loop structure into the macro (in contravention of kernel
> programming guidelines).
> 
> So how about NOT including the actual for() inside the macro, so
> that instead of writing
> 
> 	for_each_engine(engine, dev_priv)
> 		do_stuff(engine)
> 
> we would write it as
> 
> 	for (EACH_ENGINE(engine, dev_priv))
> 		initialise(engine)
> 
> 	for (EACH_ACTIVE_ENGINE(engine, dev_priv)) {
> 		service(engine)
> 		restart(engine)
> 	}
> 
> etc. The for-loop is visible and the scope doesn't give you any surprises.
> 
> [The EACH_ENGINE() macros expands to a semicolon-separated triplet
> of expressions; still a violation of the "don't use macros to
> redefine C syntax" guideline, but much less egregious than macros
> that contain embedded 'for's and 'if's.

for_each() is common practice in the kernel, so hiding the for() inside
the macro isn't that egregious. The problem is defining EACH_ACTIVE_ENGINE()
simply, preferrably without the use of another loop inside the for(;;).
One is to pack the i915->engines[] and have i915->num_engines and
intel_lookup_engine (or an i915->engine_for_id[]) for the occasional
case where we look up e.g. &i915->engines[BCS].
-Chris
Dave Gordon Dec. 2, 2015, 2:51 p.m. UTC | #9
On 02/12/15 13:46, Chris Wilson wrote:
> On Wed, Dec 02, 2015 at 01:29:21PM +0000, Dave Gordon wrote:
>> On 25/11/15 09:23, Daniel Vetter wrote:
>>> On Tue, Nov 24, 2015 at 11:47:26PM +0000, Chris Wilson wrote:
>>>> On Tue, Nov 24, 2015 at 10:26:01PM +0000, Chris Wilson wrote:
>>>>> On Tue, Nov 24, 2015 at 07:36:25PM +0200, Jani Nikula wrote:
>>>>>>   /* Iterate over initialised rings */
>>>>>>   #define for_each_ring(ring__, dev_priv__, i__) \
>>>>>>   	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
>>>>>> -		if (((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))
>>>>>> +		for_each_if ((((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__))))
>>>>>
>>>>> Idly wondering if we would be happy with
>>>>>
>>>>> for_each_ring(ring__, dev_priv__)
>>>>> 	for ((ring__) = &(dev_priv__)->ring[0];
>>>>> 	     (ring__) <= &(dev_priv__)->ring[I915_NUM_RINGS];
>>>>> 	     (ring__)++)
>>>>> 	     for_each_if(intel_ring_initialized(ring__))
>>>>>
>>>>> ?
>>>>>
>>>>> The downside is that we have used i__ in several places rather than
>>>>> ring->id.
>>>>
>>>> Fwiw, 13 files changed, 113 insertions(+), 140 deletions(-)
>>>>
>>>> Seems a reasonable shrinkage.
>>>
>>> Maybe for_each_engine even, and phase out for_each_ring completely?
>>> -Daniel
>>>
>>
>> Wouldn't it be nicer (and safer) not to build macros that fold the
>> loop structure into the macro (in contravention of kernel
>> programming guidelines).
>>
>> So how about NOT including the actual for() inside the macro, so
>> that instead of writing
>>
>> 	for_each_engine(engine, dev_priv)
>> 		do_stuff(engine)
>>
>> we would write it as
>>
>> 	for (EACH_ENGINE(engine, dev_priv))
>> 		initialise(engine)
>>
>> 	for (EACH_ACTIVE_ENGINE(engine, dev_priv)) {
>> 		service(engine)
>> 		restart(engine)
>> 	}
>>
>> etc. The for-loop is visible and the scope doesn't give you any surprises.
>>
>> [The EACH_ENGINE() macros expands to a semicolon-separated triplet
>> of expressions; still a violation of the "don't use macros to
>> redefine C syntax" guideline, but much less egregious than macros
>> that contain embedded 'for's and 'if's.
>
> for_each() is common practice in the kernel, so hiding the for() inside
> the macro isn't that egregious. The problem is defining EACH_ACTIVE_ENGINE()
> simply, preferrably without the use of another loop inside the for(;;).

Nothing wrong with another loop :) Although, to keep it tidy, it can be 
inside an inline helper function that skips over the unwanted items in 
the iteration. I think it's better to have the if-ready condition test 
inside the iterator (and therefore clearly bounded) than let it dangle 
at the end of the macro.

> One is to pack the i915->engines[] and have i915->num_engines and
> intel_lookup_engine (or an i915->engine_for_id[]) for the occasional
> case where we look up e.g. &i915->engines[BCS].
> -Chris

Or, put the active ones on a linked list, or keep a bitmask of which 
ones have been initialised inside the dev_priv structure, so you don't 
have to even dereference the engine[] array to work out whether a 
particular engine is initialised. Apropos which, wouldn't it be much 
more efficient to do that, because intel_ring_initialized() is quite 
heavyweight and the results surely don't change often, if at all, during 
normal operation. So we should only evaluate it when something has 
changed, and cache the bool result for use in all those for_each() loops!

.Dave.
Chris Wilson Dec. 2, 2015, 2:58 p.m. UTC | #10
On Wed, Dec 02, 2015 at 02:51:17PM +0000, Dave Gordon wrote:
> Or, put the active ones on a linked list, or keep a bitmask of which
> ones have been initialised inside the dev_priv structure, so you
> don't have to even dereference the engine[] array to work out
> whether a particular engine is initialised. Apropos which, wouldn't
> it be much more efficient to do that, because
> intel_ring_initialized() is quite heavyweight and the results surely
> don't change often, if at all, during normal operation. So we should
> only evaluate it when something has changed, and cache the bool
> result for use in all those for_each() loops!

commit b53cd50c19f9d3c6f3308165b3e26c47b19dd041
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Tue Mar 31 00:25:20 2015 +0100

    drm/i915: intel_ring_initialized() must be simple and inline
    
    Fixes regression from
    commit 48d823878d64f93163f5a949623346748bbce1b4
    Author: Oscar Mateo <oscar.mateo@intel.com>
    Date:   Thu Jul 24 17:04:23 2014 +0100
    
        drm/i915/bdw: Generic logical ring init and cleanup
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

...

-bool intel_ring_initialized(struct intel_engine_cs *ring);
+static inline bool
+intel_ring_initialized(struct intel_engine_cs *ring)
+{
+       return ring->dev != NULL;
+}

Just waiting to clear a massive backlog.

If we can use an array rather than a list (and a static assignment
certainly qualifies), use an array.
-Chris
Dave Gordon Dec. 10, 2015, 12:32 p.m. UTC | #11
On 25/11/15 09:23, Daniel Vetter wrote:
> On Tue, Nov 24, 2015 at 11:47:26PM +0000, Chris Wilson wrote:
>> On Tue, Nov 24, 2015 at 10:26:01PM +0000, Chris Wilson wrote:
>>> On Tue, Nov 24, 2015 at 07:36:25PM +0200, Jani Nikula wrote:
>>>>   /* Iterate over initialised rings */
>>>>   #define for_each_ring(ring__, dev_priv__, i__) \
>>>>   	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
>>>> -		if (((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))
>>>> +		for_each_if ((((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__))))
>>>
>>> Idly wondering if we would be happy with
>>>
>>> for_each_ring(ring__, dev_priv__)
>>> 	for ((ring__) = &(dev_priv__)->ring[0];
>>> 	     (ring__) <= &(dev_priv__)->ring[I915_NUM_RINGS];
>>> 	     (ring__)++)
>>> 	     for_each_if(intel_ring_initialized(ring__))
>>>
>>> ?
>>>
>>> The downside is that we have used i__ in several places rather than
>>> ring->id.
>>
>> Fwiw, 13 files changed, 113 insertions(+), 140 deletions(-)
>>
>> Seems a reasonable shrinkage.
>
> Maybe for_each_engine even, and phase out for_each_ring completely?
> -Daniel

Hi,

I've done an implementation of for_each_engine(ring, dev_priv), and 
converted a few uses of for_each_ring(ring, dev_priv, unused) to get rid 
of the unused dummy variable. That works fine, so now I'm looking at 
for_each_ring() for the cases where the variable IS used.

The comments above imply to me that the loop variable shouldn't really 
be the index in dev_priv->ring[i], but rather the value of engine->id. 
Is this correct?

Presumably there is at present no difference, i.e.
	dev_priv->ring[i].id == i
(at least if the ring has been initialised?). So is the reason that 
converting from index to id might give more flexibility in how to 
organise the ring structures?

.Dave.
Chris Wilson Dec. 10, 2015, 12:42 p.m. UTC | #12
On Thu, Dec 10, 2015 at 12:32:03PM +0000, Dave Gordon wrote:
> On 25/11/15 09:23, Daniel Vetter wrote:
> >On Tue, Nov 24, 2015 at 11:47:26PM +0000, Chris Wilson wrote:
> >>On Tue, Nov 24, 2015 at 10:26:01PM +0000, Chris Wilson wrote:
> >>>On Tue, Nov 24, 2015 at 07:36:25PM +0200, Jani Nikula wrote:
> >>>>  /* Iterate over initialised rings */
> >>>>  #define for_each_ring(ring__, dev_priv__, i__) \
> >>>>  	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
> >>>>-		if (((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))
> >>>>+		for_each_if ((((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__))))
> >>>
> >>>Idly wondering if we would be happy with
> >>>
> >>>for_each_ring(ring__, dev_priv__)
> >>>	for ((ring__) = &(dev_priv__)->ring[0];
> >>>	     (ring__) <= &(dev_priv__)->ring[I915_NUM_RINGS];
> >>>	     (ring__)++)
> >>>	     for_each_if(intel_ring_initialized(ring__))
> >>>
> >>>?
> >>>
> >>>The downside is that we have used i__ in several places rather than
> >>>ring->id.
> >>
> >>Fwiw, 13 files changed, 113 insertions(+), 140 deletions(-)
> >>
> >>Seems a reasonable shrinkage.
> >
> >Maybe for_each_engine even, and phase out for_each_ring completely?
> >-Daniel
> 
> Hi,
> 
> I've done an implementation of for_each_engine(ring, dev_priv), and
> converted a few uses of for_each_ring(ring, dev_priv, unused) to get
> rid of the unused dummy variable. That works fine, so now I'm
> looking at for_each_ring() for the cases where the variable IS used.
> 
> The comments above imply to me that the loop variable shouldn't
> really be the index in dev_priv->ring[i], but rather the value of
> engine->id. Is this correct?

Yes, that is more common and I think looks better for the slight
abstraction.
 
> Presumably there is at present no difference, i.e.
> 	dev_priv->ring[i].id == i
> (at least if the ring has been initialised?). So is the reason that
> converting from index to id might give more flexibility in how to
> organise the ring structures?

It would. Primary motivation today is consistency.
-Chris
Dave Gordon March 23, 2016, 6:19 p.m. UTC | #13
Late last year, there were discussions on updating the for_each_ring()
macro -- now renamed for_each_engine() -- to eliminate the third
(index) parameter, which is mostly unused at the macro callsites.
In particular, Chris Wilson and Daniel Vetter mentioned that we would
like the flexibility to eventually move away from a linear indexed
array-of-engines to some more sophisticated structure.

So here's a patchset that does just that. First we locate all the places
where the third argument to the macro *is* used, and change the macro
to a new version "for_each_engine_id()", at the same time updating the
third argument from an (int) index (usually 'i') to an intel_engine_id.

This replacement makes no functional change in itself, because at present
(dev_priv->engine[i].id == i for all i in 0..I915_NUM_ENGINES-1), but it
opens the way to using something other than an embedded array in future.

Then, we can replace all remaining instances with a simpler two-parameter
version.  Along the way, all the engine-iterator macros are updated to
the form suggested by Chris Wilson, where the pointer into the array
(rather than the index variable) is used to compute loop termination,
and many redundant loop-counter variables are eliminated :)

Dave Gordon (2):
  drm/i915: introduce for_each_engine_id()
  drm/i915: replace for_each_engine()

 drivers/gpu/drm/i915/i915_debugfs.c        | 94 +++++++++++++++---------------
 drivers/gpu/drm/i915/i915_drv.h            | 28 ++++++---
 drivers/gpu/drm/i915/i915_gem.c            | 50 +++++++---------
 drivers/gpu/drm/i915/i915_gem_context.c    |  6 +-
 drivers/gpu/drm/i915/i915_gem_debug.c      |  3 +-
 drivers/gpu/drm/i915/i915_gem_gtt.c        |  9 +--
 drivers/gpu/drm/i915/i915_gpu_error.c      |  6 +-
 drivers/gpu/drm/i915/i915_guc_submission.c | 14 ++---
 drivers/gpu/drm/i915/i915_irq.c            | 24 ++++----
 drivers/gpu/drm/i915/intel_guc_loader.c    |  8 +--
 drivers/gpu/drm/i915/intel_lrc.c           |  3 +-
 drivers/gpu/drm/i915/intel_mocs.c          |  6 +-
 drivers/gpu/drm/i915/intel_pm.c            | 19 +++---
 drivers/gpu/drm/i915/intel_ringbuffer.c    | 21 ++++---
 14 files changed, 143 insertions(+), 148 deletions(-)
Dave Gordon March 24, 2016, 11:38 a.m. UTC | #14
On 24/03/16 09:06, Patchwork wrote:
> == Series Details ==
>
> Series: drm/i915: fix potential dangling else problems in for_each_ macros (rev3)
> URL   : https://patchwork.freedesktop.org/series/1142/
> State : failure
>
> == Summary ==
>
> Series 1142v3 drm/i915: fix potential dangling else problems in for_each_ macros
> http://patchwork.freedesktop.org/api/1.0/series/1142/revisions/3/mbox/
>
> Test kms_flip:
>          Subgroup basic-flip-vs-wf_vblank:
>                  pass       -> FAIL       (snb-x220t)

Already filed,
https://bugs.freedesktop.org/show_bug.cgi?id=94294

> Test kms_pipe_crc_basic:
>          Subgroup suspend-read-crc-pipe-c:
>                  dmesg-warn -> PASS       (bsw-nuc-2)
> Test pm_rpm:
>          Subgroup basic-pci-d3-state:
>                  dmesg-warn -> PASS       (bsw-nuc-2)
>                  pass       -> DMESG-WARN (byt-nuc)

Ditto,
https://bugs.freedesktop.org/show_bug.cgi?id=94164

>          Subgroup basic-rte:
>                  dmesg-warn -> PASS       (byt-nuc) UNSTABLE
>
> bdw-nuci7        total:192  pass:180  dwarn:0   dfail:0   fail:0   skip:12
> bdw-ultra        total:192  pass:171  dwarn:0   dfail:0   fail:0   skip:21
> bsw-nuc-2        total:192  pass:155  dwarn:0   dfail:0   fail:0   skip:37
> byt-nuc          total:192  pass:156  dwarn:1   dfail:0   fail:0   skip:35
> hsw-brixbox      total:192  pass:170  dwarn:0   dfail:0   fail:0   skip:22
> hsw-gt2          total:192  pass:175  dwarn:0   dfail:0   fail:0   skip:17
> ilk-hp8440p      total:192  pass:129  dwarn:0   dfail:0   fail:0   skip:63
> ivb-t430s        total:192  pass:167  dwarn:0   dfail:0   fail:0   skip:25
> skl-i7k-2        total:192  pass:169  dwarn:0   dfail:0   fail:0   skip:23
> skl-nuci5        total:192  pass:181  dwarn:0   dfail:0   fail:0   skip:11
> snb-dellxps      total:192  pass:158  dwarn:0   dfail:0   fail:0   skip:34
> snb-x220t        total:192  pass:157  dwarn:0   dfail:0   fail:2   skip:33
>
> Results at /archive/results/CI_IGT_test/Patchwork_1699/
>
> 8f2e9bbc15607f56261aefd7a1f8caf6909c6b9d drm-intel-nightly: 2016y-03m-23d-17h-03m-10s UTC integration manifest
> c4613575f37039f81f8969a4e805a80ff0a64ef9 drm/i915: replace for_each_engine()
> 31beb6168bc53ad8b3fe008dcaa2ae038743a252 drm/i915: introduce for_each_engine_id()
>
Tvrtko Ursulin March 24, 2016, 2:35 p.m. UTC | #15
On 24/03/16 12:03, Patchwork wrote:
> == Series Details ==
>
> Series: drm/i915: fix potential dangling else problems in for_each_ macros (rev4)
> URL   : https://patchwork.freedesktop.org/series/1142/
> State : success
>
> == Summary ==
>
> Series 1142v4 drm/i915: fix potential dangling else problems in for_each_ macros
> http://patchwork.freedesktop.org/api/1.0/series/1142/revisions/4/mbox/
>
> Test gem_exec_suspend:
>          Subgroup basic-s3:
>                  dmesg-warn -> PASS       (bsw-nuc-2)
> Test kms_pipe_crc_basic:
>          Subgroup suspend-read-crc-pipe-a:
>                  pass       -> SKIP       (byt-nuc)
>          Subgroup suspend-read-crc-pipe-c:
>                  incomplete -> PASS       (hsw-gt2)
> Test pm_rpm:
>          Subgroup basic-pci-d3-state:
>                  dmesg-warn -> PASS       (byt-nuc)
>
> bdw-nuci7        total:192  pass:180  dwarn:0   dfail:0   fail:0   skip:12
> bdw-ultra        total:192  pass:171  dwarn:0   dfail:0   fail:0   skip:21
> bsw-nuc-2        total:192  pass:155  dwarn:0   dfail:0   fail:0   skip:37
> byt-nuc          total:192  pass:156  dwarn:0   dfail:0   fail:0   skip:36
> hsw-brixbox      total:192  pass:170  dwarn:0   dfail:0   fail:0   skip:22
> hsw-gt2          total:192  pass:175  dwarn:0   dfail:0   fail:0   skip:17
> ivb-t430s        total:192  pass:167  dwarn:0   dfail:0   fail:0   skip:25
> skl-i7k-2        total:192  pass:169  dwarn:0   dfail:0   fail:0   skip:23
> skl-nuci5        total:192  pass:181  dwarn:0   dfail:0   fail:0   skip:11
> snb-dellxps      total:192  pass:158  dwarn:0   dfail:0   fail:0   skip:34
> snb-x220t        total:192  pass:158  dwarn:0   dfail:0   fail:1   skip:33
>
> Results at /archive/results/CI_IGT_test/Patchwork_1704/
>
> 79ee42317266a82b932a39e9567244ed91dd27d6 drm-intel-nightly: 2016y-03m-24d-10h-26m-54s UTC integration manifest
> 0126b0b851d5abdfc08ccd48cf2babf2fdd550c0 drm/i915: replace for_each_engine()
> 6fe2515ba81fbeaf484a388941b776350f910ba2 drm/i915: introduce for_each_engine_id()

Merged, thanks for patches and review!

Regards,

Tvrtko
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 3d8741eff7d3..f9c779fd84ad 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -263,6 +263,8 @@  struct i915_hotplug {
 	 I915_GEM_DOMAIN_INSTRUCTION | \
 	 I915_GEM_DOMAIN_VERTEX)
 
+#define for_each_if(condition) if (!(condition)); else
+
 #define for_each_pipe(__dev_priv, __p) \
 	for ((__p) = 0; (__p) < INTEL_INFO(__dev_priv)->num_pipes; (__p)++)
 #define for_each_plane(__dev_priv, __pipe, __p)				\
@@ -286,7 +288,7 @@  struct i915_hotplug {
 	list_for_each_entry(intel_plane,				\
 			    &(dev)->mode_config.plane_list,		\
 			    base.head)					\
-		if ((intel_plane)->pipe == (intel_crtc)->pipe)
+		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)
@@ -303,15 +305,15 @@  struct i915_hotplug {
 
 #define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \
 	list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
-		if ((intel_encoder)->base.crtc == (__crtc))
+		for_each_if ((intel_encoder)->base.crtc == (__crtc))
 
 #define for_each_connector_on_encoder(dev, __encoder, intel_connector) \
 	list_for_each_entry((intel_connector), &(dev)->mode_config.connector_list, base.head) \
-		if ((intel_connector)->base.encoder == (__encoder))
+		for_each_if ((intel_connector)->base.encoder == (__encoder))
 
 #define for_each_power_domain(domain, mask)				\
 	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
-		if ((1 << (domain)) & (mask))
+		for_each_if ((1 << (domain)) & (mask))
 
 struct drm_i915_private;
 struct i915_mm_struct;
@@ -730,7 +732,7 @@  struct intel_uncore {
 	for ((i__) = 0, (domain__) = &(dev_priv__)->uncore.fw_domain[0]; \
 	     (i__) < FW_DOMAIN_ID_COUNT; \
 	     (i__)++, (domain__) = &(dev_priv__)->uncore.fw_domain[i__]) \
-		if (((mask__) & (dev_priv__)->uncore.fw_domains) & (1 << (i__)))
+		for_each_if (((mask__) & (dev_priv__)->uncore.fw_domains) & (1 << (i__)))
 
 #define for_each_fw_domain(domain__, dev_priv__, i__) \
 	for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
@@ -1969,7 +1971,7 @@  static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc)
 /* Iterate over initialised rings */
 #define for_each_ring(ring__, dev_priv__, i__) \
 	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
-		if (((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))
+		for_each_if ((((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__))))
 
 enum hdmi_force_audio {
 	HDMI_AUDIO_OFF_DVI = -2,	/* no aux data for HDMI-DVI converter */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 75f03e5bee51..4b21d5e137dc 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12417,7 +12417,7 @@  static bool intel_fuzzy_clock_check(int clock1, int clock2)
 	list_for_each_entry((intel_crtc), \
 			    &(dev)->mode_config.crtc_list, \
 			    base.head) \
-		if (mask & (1 <<(intel_crtc)->pipe))
+		for_each_if (mask & (1 <<(intel_crtc)->pipe))
 
 static bool
 intel_compare_m_n(unsigned int m, unsigned int n,
diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h
index e6cb25239941..02551ff228c2 100644
--- a/drivers/gpu/drm/i915/intel_dsi.h
+++ b/drivers/gpu/drm/i915/intel_dsi.h
@@ -117,7 +117,7 @@  static inline struct intel_dsi_host *to_intel_dsi_host(struct mipi_dsi_host *h)
 
 #define for_each_dsi_port(__port, __ports_mask) \
 	for ((__port) = PORT_A; (__port) < I915_MAX_PORTS; (__port)++)	\
-		if ((__ports_mask) & (1 << (__port)))
+		for_each_if ((__ports_mask) & (1 << (__port)))
 
 static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder)
 {
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 3fa43af94946..469927edf459 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -54,13 +54,13 @@ 
 	     i < (power_domains)->power_well_count &&			\
 		 ((power_well) = &(power_domains)->power_wells[i]);	\
 	     i++)							\
-		if ((power_well)->domains & (domain_mask))
+		for_each_if ((power_well)->domains & (domain_mask))
 
 #define for_each_power_well_rev(i, power_well, domain_mask, power_domains) \
 	for (i = (power_domains)->power_well_count - 1;			 \
 	     i >= 0 && ((power_well) = &(power_domains)->power_wells[i]);\
 	     i--)							 \
-		if ((power_well)->domains & (domain_mask))
+		for_each_if ((power_well)->domains & (domain_mask))
 
 bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
 				    int power_well_id);