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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>

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@xxxxxxxx>

> ---
>  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@xxxxxxxxxxxxxxxxxxxxx
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux