public inbox for intel-gfx@lists.freedesktop.org
 help / color / mirror / Atom feed
From: Dave Gordon <david.s.gordon@intel.com>
To: Chris Wilson <chris@chris-wilson.co.uk>, intel-gfx@lists.freedesktop.org
Subject: Re: [PATCH] drm/i915: Bug fixes to ring 'head' updating
Date: Tue, 04 Nov 2014 14:17:07 +0000	[thread overview]
Message-ID: <5458DFE3.8030003@intel.com> (raw)
In-Reply-To: <20141103205950.GI13658@nuc-i3427.alporthouse.com>

On 03/11/14 20:59, Chris Wilson wrote:
> On Mon, Nov 03, 2014 at 01:29:04PM +0000, Dave Gordon wrote:
>> Fixes to both the LRC and the legacy ringbuffer code to correctly
>> calculate and update the available space in a ring.
>>
>> The logical ring code was updating the software ring 'head' value
>> by reading the hardware 'HEAD' register. In LRC mode, this is not
>> valid as the hardware is not necessarily executing the same context
>> that is being processed by the software. Thus reading the h/w HEAD
>> could put an unrelated (undefined, effectively random) value into
>> the s/w 'head' -- A Bad Thing for the free space calculations.
>>
>> In addition, the old code could update a ringbuffer's 'head' value
>> from the 'last_retired_head' even when the latter hadn't been recently
>> updated and therefore had a value of -1; this would also confuse the
>> freespace calculations. Now, we consume 'last_retired_head' in just
>> one place, ensuring that this confusion does not arise.
> 
> What? Not unless someone had broken it...
> 
> This is the code I expect to see here based on requests:
> 
> static int ring_wait(struct intel_ringbuffer *ring, int n)
> {
>         int ret;
> 
>         trace_intel_ringbuffer_wait(ring, n);
> 
>         do {
>                 struct i915_gem_request *rq;
> 
>                 i915_gem_retire_requests__engine(ring->engine);
>                 if (ring->retired_head != -1) {
>                         ring->head = ring->retired_head;
>                         ring->retired_head = -1;
> 
>                         ring->space = intel_ring_space(ring);
>                         if (ring->space >= n)
>                                 return 0;
>                 }
> 
>                 list_for_each_entry(rq, &ring->breadcrumbs, breadcrumb_link)
>                         if (__intel_ring_space(rq->tail, ring->tail,
>                                                ring->size, I915_RING_RSVD) >= n)
>                                 break;
> 
>                 if (WARN_ON(&rq->breadcrumb_link == &ring->breadcrumbs))
>                         return -EDEADLK;
> 
>                 ret = i915_request_wait(rq);
>         } while (ret == 0);
> 
>         return ret;
> }

I like this sample code better than the version currently in the driver,
because it, like my patch, has only one place where the value is
transferred from 'retired_head' to 'head', and it's clearly guarded by a
test that 'retired_head' is not -1. But this isn't actually the code we
have, which has four places where this copying is done (two for LRC and
two for legacy), and one in each path is not so guarded. So *that's*
what I'm fixing.

It looks like this code also assumes one request queue per ringbuffer,
rather than one per engine, which may be nicer but isn't what we
currently have.

> and that works for both execlists and regular...
> -Chris

My calculate-freespace and update-freespace functions are likewise
LRC-agnostic, although the wait_for_request/wait_for_space functions
that they're called from have (regrettably) been duplicated. Not my
call, though.

Finally, my new code is more resilient against misuse than the current
version. At present, if a sequence of emit()s overruns the allocated
length (possibly due to display code injecting extra instruction without
setting up its own ring_begin/add_request pair, or simply a bug), then
the ring space calculation can in some cases claim that there's suddenly
a LOT of space (due to the way the modulo arithmetic is done) and
confusion will follow. My version will return "no space" rather than "a
lot of space" in this situation.

BTW, I have some local patches which enforce strict checking of
ring_begin/add_request pairing and generates warnings if there's a
mismatch or an overrun or any other misuse. We've been using these to
help identify and eliminate code that just stuffs instructions into the
ring without notifying the scheduler. Interested?

.Dave.
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

  reply	other threads:[~2014-11-04 14:18 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-03 13:29 [PATCH] drm/i915: Bug fixes to ring 'head' updating Dave Gordon
2014-11-03 20:59 ` Chris Wilson
2014-11-04 14:17   ` Dave Gordon [this message]
2014-11-17 16:31     ` Daniel Vetter
2014-11-18  4:43 ` akash goel
2014-11-18  8:02 ` Daniel Vetter
2014-11-24  9:35   ` Daniel Vetter
2014-11-18 15:00 ` Deepak S
2014-11-18 19:53   ` Dave Gordon
2014-11-18 20:07 ` [PATCH v2 0/3] " Dave Gordon
2014-11-18 20:07   ` [PATCH v2 1/3] drm/i915: Check for matching ringbuffer in logical_ring_wait_request() Dave Gordon
2014-11-25  4:14     ` Deepak S
2014-11-18 20:07   ` [PATCH v2 2/3] drm/i915: Don't read 'HEAD' MMIO register in LRC mode Dave Gordon
2014-11-25  7:57     ` Deepak S
2014-11-18 20:07   ` [PATCH v2 3/3] drm/i915: Consolidate ring freespace calculations Dave Gordon
2014-11-24 10:04     ` Daniel Vetter
2014-11-24 14:32       ` Dave Gordon
2014-11-25 11:41         ` Daniel Vetter
2014-11-25 11:47           ` Chris Wilson
2014-11-25  7:59     ` Deepak S
2014-11-27 11:22 ` [PATCH v3 0/2] Updates to " Dave Gordon
2014-11-27 11:22   ` [PATCH v3 1/2] drm/i915: Make ring freespace calculation more robust Dave Gordon
2014-11-27 11:22   ` [PATCH v3 2/2] drm/i915: Consolidate ring freespace calculations Dave Gordon
2014-11-27 19:20     ` [PATCH v3 2/2] drm/i915: Consolidate ring freespace shuang.he
2014-11-28 17:51     ` [PATCH v3 2/2] drm/i915: Consolidate ring freespace calculations Daniel Vetter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5458DFE3.8030003@intel.com \
    --to=david.s.gordon@intel.com \
    --cc=chris@chris-wilson.co.uk \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox