summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Gordon <david.s.gordon@intel.com>2014-11-27 11:22:48 +0000
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-12-03 09:35:26 +0100
commit4f54741e07f9c4791f06a3d151b56ece08b27c20 (patch)
tree7b195797e93cc470520fc83cc751729a08f7f0f9
parent17af40a835f1805e8d0523dddf1fbabe06abf230 (diff)
downloadlwn-4f54741e07f9c4791f06a3d151b56ece08b27c20.tar.gz
lwn-4f54741e07f9c4791f06a3d151b56ece08b27c20.zip
drm/i915: Make ring freespace calculation more robust
The used space in a ring is given by the cyclic distance from the consumer (HEAD) to the producer (TAIL), i.e. ((tail-head) MOD size); conversely, the available space in a ring is the cyclic distance from the producer to the consumer, MINUS the amount reserved for a "gap" that is supposed to guarantee that the producer never catches up with or overruns the consumer. Note that some GEN h/w requires that TAIL never approach to within one cacheline of HEAD, so the gap is usually set to twice the cacheline size to ensure this. While the existing code gives the correct answer for correct inputs, if the producer HAS overrun into the reserved space, the result can be a value larger than the maximum valid value (size-reserved). We can improve this by reorganising the calculation, so that in the event of overrun the result will be negative rather than over-large. This means that the commonly-used test (available >= required) will then 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 of what went wrong. Signed-off-by: Dave Gordon <david.s.gordon@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 788e1b6648ac..2ac382ac6bbb 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -52,10 +52,10 @@ 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;
}
int intel_ring_space(struct intel_ringbuffer *ringbuf)