Re: [PATCH v2 1/6] drm/i915: Lock out execlist tasklet while peeking inside for busy-stats

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

 



Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> writes:

> In order to prevent a race condition where we may end up overaccounting
> the active state and leaving the busy-stats believing the GPU is 100%
> busy, lock out the tasklet while we reconstruct the busy state. There is
> no direct spinlock guard for the execlists->port[], so we need to
> utilise tasklet_disable() as a synchronous barrier to prevent the only
> writer to execlists->port[] from running at the same time as the enable.
>
> Fixes: 4900727d35bb ("drm/i915/pmu: Reconstruct active state on starting busy-stats")
> Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@xxxxxxxxx>

This series applied on drm-tip with j1900. Uptime 2h 35min until system
hang. Load was glxgears + video.

-Mika

> ---
>  drivers/gpu/drm/i915/intel_engine_cs.c | 20 ++++++++++++--------
>  1 file changed, 12 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
> index d790bdc227ff..b221610f2365 100644
> --- a/drivers/gpu/drm/i915/intel_engine_cs.c
> +++ b/drivers/gpu/drm/i915/intel_engine_cs.c
> @@ -1943,16 +1943,22 @@ intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance)
>   */
>  int intel_enable_engine_stats(struct intel_engine_cs *engine)
>  {
> +	struct intel_engine_execlists *execlists = &engine->execlists;
>  	unsigned long flags;
> +	int err = 0;
>  
>  	if (!intel_engine_supports_stats(engine))
>  		return -ENODEV;
>  
> +	tasklet_disable(&execlists->tasklet);
>  	spin_lock_irqsave(&engine->stats.lock, flags);
> -	if (engine->stats.enabled == ~0)
> -		goto busy;
> +
> +	if (unlikely(engine->stats.enabled == ~0)) {
> +		err = -EBUSY;
> +		goto unlock;
> +	}
> +
>  	if (engine->stats.enabled++ == 0) {
> -		struct intel_engine_execlists *execlists = &engine->execlists;
>  		const struct execlist_port *port = execlists->port;
>  		unsigned int num_ports = execlists_num_ports(execlists);
>  
> @@ -1967,14 +1973,12 @@ int intel_enable_engine_stats(struct intel_engine_cs *engine)
>  		if (engine->stats.active)
>  			engine->stats.start = engine->stats.enabled_at;
>  	}
> -	spin_unlock_irqrestore(&engine->stats.lock, flags);
>  
> -	return 0;
> -
> -busy:
> +unlock:
>  	spin_unlock_irqrestore(&engine->stats.lock, flags);
> +	tasklet_enable(&execlists->tasklet);
>  
> -	return -EBUSY;
> +	return err;
>  }
>  
>  static ktime_t __intel_engine_get_busy_time(struct intel_engine_cs *engine)
> -- 
> 2.15.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
https://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