Commit 2def4ad9 authored by Chris Wilson's avatar Chris Wilson Committed by Daniel Vetter

drm/i915: Optimistically spin for the request completion

This provides a nice boost to mesa in swap bound scenarios (as mesa
throttles itself to the previous frame and given the scenario that will
complete shortly). It will also provide a good boost to systems running
with semaphores disabled and so frequently waiting on the GPU as it
switches rings. In the most favourable of microbenchmarks, this can
increase performance by around 15% - though in practice improvements
will be marginal and rarely noticeable.

v2: Account for user timeouts
v3: Limit the spinning to a single jiffie (~1us) at most. On an
otherwise idle system, there is no scheduler contention and so without a
limit we would spin until the GPU is ready.
v4: Drop forcewake - the lazy coherent access doesn't require it, and we
have no reason to believe that the forcewake itself improves seqno
coherency - it only adds delay.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Cc: Eero Tamminen <eero.t.tamminen@intel.com>
Cc: "Rantala, Valtteri" <valtteri.rantala@intel.com>
Reviewed-by: default avatarTvrtko Ursulin <tvrtko.ursulin@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent a1b2278e
...@@ -1181,6 +1181,29 @@ static bool missed_irq(struct drm_i915_private *dev_priv, ...@@ -1181,6 +1181,29 @@ static bool missed_irq(struct drm_i915_private *dev_priv,
return test_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings); return test_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings);
} }
static int __i915_spin_request(struct drm_i915_gem_request *rq)
{
unsigned long timeout;
if (i915_gem_request_get_ring(rq)->irq_refcount)
return -EBUSY;
timeout = jiffies + 1;
while (!need_resched()) {
if (i915_gem_request_completed(rq, true))
return 0;
if (time_after_eq(jiffies, timeout))
break;
cpu_relax_lowlatency();
}
if (i915_gem_request_completed(rq, false))
return 0;
return -EAGAIN;
}
/** /**
* __i915_wait_request - wait until execution of request has finished * __i915_wait_request - wait until execution of request has finished
* @req: duh! * @req: duh!
...@@ -1225,12 +1248,20 @@ int __i915_wait_request(struct drm_i915_gem_request *req, ...@@ -1225,12 +1248,20 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
if (INTEL_INFO(dev)->gen >= 6) if (INTEL_INFO(dev)->gen >= 6)
gen6_rps_boost(dev_priv, file_priv); gen6_rps_boost(dev_priv, file_priv);
if (!irq_test_in_progress && WARN_ON(!ring->irq_get(ring)))
return -ENODEV;
/* Record current time in case interrupted by signal, or wedged */ /* Record current time in case interrupted by signal, or wedged */
trace_i915_gem_request_wait_begin(req); trace_i915_gem_request_wait_begin(req);
before = ktime_get_raw_ns(); before = ktime_get_raw_ns();
/* Optimistic spin for the next jiffie before touching IRQs */
ret = __i915_spin_request(req);
if (ret == 0)
goto out;
if (!irq_test_in_progress && WARN_ON(!ring->irq_get(ring))) {
ret = -ENODEV;
goto out;
}
for (;;) { for (;;) {
struct timer_list timer; struct timer_list timer;
...@@ -1279,14 +1310,15 @@ int __i915_wait_request(struct drm_i915_gem_request *req, ...@@ -1279,14 +1310,15 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
destroy_timer_on_stack(&timer); destroy_timer_on_stack(&timer);
} }
} }
now = ktime_get_raw_ns();
trace_i915_gem_request_wait_end(req);
if (!irq_test_in_progress) if (!irq_test_in_progress)
ring->irq_put(ring); ring->irq_put(ring);
finish_wait(&ring->irq_queue, &wait); finish_wait(&ring->irq_queue, &wait);
out:
now = ktime_get_raw_ns();
trace_i915_gem_request_wait_end(req);
if (timeout) { if (timeout) {
s64 tres = *timeout - (now - before); s64 tres = *timeout - (now - before);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment