public inbox for intel-gfx@lists.freedesktop.org
 help / color / mirror / Atom feed
From: Dave Gordon <david.s.gordon@intel.com>
To: Daniel Vetter <daniel@ffwll.ch>
Cc: intel-gfx@lists.freedesktop.org
Subject: Re: [PATCH v2 3/3] drm/i915: Consolidate ring freespace calculations
Date: Mon, 24 Nov 2014 14:32:25 +0000	[thread overview]
Message-ID: <54734179.1080509@intel.com> (raw)
In-Reply-To: <20141124100434.GN25711@phenom.ffwll.local>

On 24/11/14 10:04, Daniel Vetter wrote:
> On Tue, Nov 18, 2014 at 08:07:22PM +0000, Dave Gordon wrote:
>> diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
>> index ae09258..a08ae65 100644
>> --- a/drivers/gpu/drm/i915/intel_ringbuffer.c
>> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
>> @@ -52,16 +52,27 @@ intel_ring_initialized(struct intel_engine_cs *ring)
>>  
>>  int __intel_ring_space(int head, int tail, int size)
>>  {
>> -	int space = head - (tail + I915_RING_FREE_SPACE);
>> -	if (space < 0)
>> +	int space = head - tail;
>> +	if (space <= 0)
>>  		space += size;
>> -	return space;
>> +	return space - I915_RING_FREE_SPACE;
> 
> Changing the free space computation doesn't seem required, but resulting
> in Chris&me just discussing it on irc to convince ourselves it's not
> broken accidentally now. Can you please respin you patch with this change
> dropped?
> 
> In generally it's good practice to review the diff after committing a
> patch and hunt for any unecessary changes. Imo even when the endresult
> looks a bit ulgy (e.g. crazy ordering of static functions which requires
> tons of predeclarations) it's better if the resulting diff looks cleaner.
> And if things get out of hand we can always do a pure cleanup patch.
> -Daniel

This isn't an accidental change; it's to improve resilience in the case
that head and/or tail end up with values they shouldn't have.

Here's a C program to model the two different calculations in a tiny ring:

#include <stdio.h>

#define FREE    4
#define SIZE    8

main()
{
        int h, t, s1, s2;

        printf("%s\t%s\t%s\t%s\n", "Head", "Tail", "OSpace", "NSpace");
        for (h = 0; h <= SIZE; ++h)
        {
                for (t = 0; t <= SIZE; ++t)
                {
                        s1 = h - (t + FREE);
                        if (s1 < 0)
                                s1 += SIZE;

                        s2 = h - t;
                        if (s2 <= 0)
                                s2 += SIZE;
                        s2 -= FREE;

                        printf("%2d\t%2d\t%2d\t%2d\n", h, t, s1, s2);
                }
                printf("\n");
        }
}

OSpace (s1) uses the old code, whereas NSpace (s2) is my new method.
They agree for all well-behaved cases, but look at this snippet:

Head	Tail	OSpace	NSpace
 6	 0	 2	 2
 6	 1	 1	 1
 6	 2	 0	 0
 6	 3	 7	-1
 6	 4	 6	-2
 6	 5	 5	-3
 6	 6	 4	 4
 6	 7	 3	 3
 6	 8	 2	 2

Both the old and new code give the right answers if HEAD and TAIL have
legitimate values. But if TAIL should somehow advance further than it
should, and run into the reserved area, the old code might tell you that
there's now LOTS of space available, whereas the new code returns "less
than zero" space available.

For example, the old calculation tells us that if head=6 and tail=4 then
there are 6 slots available -- which just can't be right, as by
definition the answer should never be more than (SIZE-RSVD). I'd much
rather get the answer "-2" for this case, as it's then obvious that this
really shouldn't happen.

In particular, this new code would mean that the commonly-used test
(available >= required) would immediately reject further writes into the
ring after an overrun, giving some chance that we can recover from or at
least diagnose the original problem; whereas allowing more writes would
likely both confuse the h/w and destroy the evidence.

It's also easier to understand, IMHO (if experienced programmers such as
you & Chris had to discuss the old code to be confident that it was
correct, that already suggests that it's not as clear as it could be).

The used space in a ring is given by the cyclic distance from the
consumer to the producer; conversely, the available space in a ring is
the cyclic distance from the producer to the consumer, MINUS the amount
reserved. The new code expresses that directly, without having to figure
out the meaning of ADDING the reserved amount to the tail before
subtracting it from head. In ASCII pix:

                  +++++++++++++++++++
                  +      free       +  0
                  +      free       +  1
                  +    reserved     +  2
                  +    reserved     +  3
(consumer) HEAD-> +      used       +  4
                  +      used       +  5
                  +      used       +  6
                  +      used       +  7
                  +      used       +  8
                  +      used       +  9
(producer) TAIL-> +      free       + 10
                  +      free       + 11
                  +++++++++++++++++++

The sketch above shows the situation with size=12, reserved=2, TAIL=10
and HEAD=4. Slots 4 to 9 are used (TAIL-HEAD = 10-4 = 6 slots). The
available space is (HEAD-TAIL (+SIZE) - RSVD = 4-10+12-2 = 4 slots).

                  +++++++++++++++++++
                  +      used       +  0
                  +      used       +  1
(producer) TAIL-> +      free       +  2
                  +      free       +  3
                  +    reserved     +  4
                  +    reserved     +  5
(consumer) HEAD-> +      used       +  6
                  +      used       +  7
                  +      used       +  8
                  +      used       +  9
                  +      used       + 10
                  +      used       + 11
                  +++++++++++++++++++

After TAIL has wrapped, we might have this situation with TAIL=2 and
HEAD=6. Used space is (TAIL-HEAD (+SIZE) = 2-6+12 = 8 slots), and
available space is (HEAD-TAIL - RSVD) = 6-2-2 = 2 slots. Straightforward
and easy to understand :)

So, I'd definitely prefer to keep this new code. We not only want to do
the calculation in only one place, but we want to do it in the best
possible way, with the minimum chance of propagating errors and
confusing both h/w and developers if someone does introduce a ring
overrun or off-by-one error in some ring-stuffing code elsewhere.
(BTW,

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

  reply	other threads:[~2014-11-24 14:32 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
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 [this message]
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=54734179.1080509@intel.com \
    --to=david.s.gordon@intel.com \
    --cc=daniel@ffwll.ch \
    --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