diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_vblank.c')
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_vblank.c | 51 | 
1 files changed, 41 insertions, 10 deletions
| diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c index 2cec2abf9746..fe256bf7b485 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.c +++ b/drivers/gpu/drm/i915/display/intel_vblank.c @@ -265,6 +265,32 @@ int intel_crtc_scanline_to_hw(struct intel_crtc *crtc, int scanline)  	return (scanline + vtotal - crtc->scanline_offset) % vtotal;  } +/* + * The uncore version of the spin lock functions is used to decide + * whether we need to lock the uncore lock or not.  This is only + * needed in i915, not in Xe. + * + * This lock in i915 is needed because some old platforms (at least + * IVB and possibly HSW as well), which are not supported in Xe, need + * all register accesses to the same cacheline to be serialized, + * otherwise they may hang. + */ +static void intel_vblank_section_enter(struct drm_i915_private *i915) +	__acquires(i915->uncore.lock) +{ +#ifdef I915 +	spin_lock(&i915->uncore.lock); +#endif +} + +static void intel_vblank_section_exit(struct drm_i915_private *i915) +	__releases(i915->uncore.lock) +{ +#ifdef I915 +	spin_unlock(&i915->uncore.lock); +#endif +} +  static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc,  				     bool in_vblank_irq,  				     int *vpos, int *hpos, @@ -302,11 +328,12 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc,  	}  	/* -	 * Lock uncore.lock, as we will do multiple timing critical raw -	 * register reads, potentially with preemption disabled, so the -	 * following code must not block on uncore.lock. +	 * Enter vblank critical section, as we will do multiple +	 * timing critical raw register reads, potentially with +	 * preemption disabled, so the following code must not block.  	 */ -	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); +	local_irq_save(irqflags); +	intel_vblank_section_enter(dev_priv);  	/* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ @@ -374,7 +401,8 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc,  	/* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ -	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); +	intel_vblank_section_exit(dev_priv); +	local_irq_restore(irqflags);  	/*  	 * While in vblank, position will be negative @@ -412,9 +440,13 @@ int intel_get_crtc_scanline(struct intel_crtc *crtc)  	unsigned long irqflags;  	int position; -	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); +	local_irq_save(irqflags); +	intel_vblank_section_enter(dev_priv); +  	position = __intel_get_crtc_scanline(crtc); -	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); + +	intel_vblank_section_exit(dev_priv); +	local_irq_restore(irqflags);  	return position;  } @@ -537,7 +569,7 @@ void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state,  	 * Need to audit everything to make sure it's safe.  	 */  	spin_lock_irqsave(&i915->drm.vblank_time_lock, irqflags); -	spin_lock(&i915->uncore.lock); +	intel_vblank_section_enter(i915);  	drm_calc_timestamping_constants(&crtc->base, &adjusted_mode); @@ -546,7 +578,6 @@ void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state,  	crtc->mode_flags = mode_flags;  	crtc->scanline_offset = intel_crtc_scanline_offset(crtc_state); - -	spin_unlock(&i915->uncore.lock); +	intel_vblank_section_exit(i915);  	spin_unlock_irqrestore(&i915->drm.vblank_time_lock, irqflags);  } | 
