* [PATCH 1/3] drm/i915: Record the tail at each request and use it to estimate the head
@ 2012-02-15 11:25 Chris Wilson
2012-02-15 11:25 ` [PATCH 2/3] drm/i915: Record the in-flight requests at the time of a hang Chris Wilson
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Chris Wilson @ 2012-02-15 11:25 UTC (permalink / raw)
To: intel-gfx
By recording the location of every request in the ringbuffer, we know
that in order to retire the request the GPU must have finished reading
it and so the GPU head is now beyond the tail of the request. We can
therefore provide a conservative estimate of where the GPU is reading
from in order to avoid having to read back the ring buffer registers
when polling for space upon starting a new write into the ringbuffer.
A secondary effect is that this allows us to convert
intel_ring_buffer_wait() to use i915_wait_request() and so consolidate
upon the single function to handle the complicated task of waiting upon
the GPU. A necessary precaution is that we need to make that wait
uninterruptible to match the existing conditions as all the callers of
intel_ring_begin() have not been audited to handle ERESTARTSYS
correctly.
By using a conservative estimate for the head, and always processing all
outstanding requests first, we prevent a race condition between using
the estimate and direct reads of I915_RING_HEAD which could result in
the value of the head going backwards, and the tail overflowing once
again. We are also careful to mark any request that we skip over in
order to free space in ring as consumed which provides a
self-consistency check.
Given sufficient abuse, such as a set of unthrottled GPU bound
cairo-traces, avoiding the use of I915_RING_HEAD gives a 10-20% boost on
Sandy Bridge (i5-2520m):
firefox-paintball 18927ms -> 15646ms: 1.21x speedup
firefox-fishtank 12563ms -> 11278ms: 1.11x speedup
which is a mild consolation for the performance those traces achieved from
exploiting the buggy autoreported head.
v2: Add a few more comments and make request->tail a conservative
estimate as suggested by Daniel Vetter.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_drv.h | 5 ++
drivers/gpu/drm/i915/i915_gem.c | 17 ++++++-
drivers/gpu/drm/i915/intel_ringbuffer.c | 83 +++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/intel_ringbuffer.h | 15 ++++++
4 files changed, 119 insertions(+), 1 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 4ee0793..e8e1b85 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -945,6 +945,9 @@ struct drm_i915_gem_request {
/** GEM sequence number associated with this request. */
uint32_t seqno;
+ /** Postion in the ringbuffer of the end of the request */
+ u32 tail;
+
/** Time at which this request was emitted, in jiffies. */
unsigned long emitted_jiffies;
@@ -1234,6 +1237,8 @@ i915_gem_object_unpin_fence(struct drm_i915_gem_object *obj)
}
void i915_gem_retire_requests(struct drm_device *dev);
+void i915_gem_retire_requests_ring(struct intel_ring_buffer *ring);
+
void i915_gem_reset(struct drm_device *dev);
void i915_gem_clflush_object(struct drm_i915_gem_object *obj);
int __must_check i915_gem_object_set_domain(struct drm_i915_gem_object *obj,
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 51390b0..dbf30bc 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1784,12 +1784,20 @@ i915_add_request(struct intel_ring_buffer *ring,
{
drm_i915_private_t *dev_priv = ring->dev->dev_private;
uint32_t seqno;
+ u32 request_ring_position;
int was_empty;
int ret;
BUG_ON(request == NULL);
seqno = i915_gem_next_request_seqno(ring);
+ /* Record the position of the start of the request so that
+ * should we detect the updated seqno part-way through the
+ * GPU processing the request, we never over-estimate the
+ * position of the head.
+ */
+ request_ring_position = intel_ring_get_tail(ring);
+
ret = ring->add_request(ring, &seqno);
if (ret)
return ret;
@@ -1798,6 +1806,7 @@ i915_add_request(struct intel_ring_buffer *ring,
request->seqno = seqno;
request->ring = ring;
+ request->tail = request_ring_position;
request->emitted_jiffies = jiffies;
was_empty = list_empty(&ring->request_list);
list_add_tail(&request->list, &ring->request_list);
@@ -1934,7 +1943,7 @@ void i915_gem_reset(struct drm_device *dev)
/**
* This function clears the request list as sequence numbers are passed.
*/
-static void
+void
i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
{
uint32_t seqno;
@@ -1962,6 +1971,12 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
break;
trace_i915_gem_request_retire(ring, request->seqno);
+ /* We know the GPU must have read the request to have
+ * sent us the seqno + interrupt, so use the position
+ * of tail of the request to update the last known position
+ * of the GPU head.
+ */
+ ring->last_retired_head = request->tail;
list_del(&request->list);
i915_gem_request_remove_from_client(request);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 620b2ed..ae78da9 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -533,6 +533,7 @@ pc_render_add_request(struct intel_ring_buffer *ring,
PIPE_CONTROL_FLUSH(ring, scratch_addr);
scratch_addr += 128;
PIPE_CONTROL_FLUSH(ring, scratch_addr);
+
intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
PIPE_CONTROL_WRITE_FLUSH |
PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
@@ -1054,11 +1055,93 @@ static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring)
return 0;
}
+static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno)
+{
+ struct drm_i915_private *dev_priv = ring->dev->dev_private;
+ bool was_interruptible;
+ int ret;
+
+ /* XXX As we have not yet audited all the paths to check that
+ * they are ready for ERESTARTSYS from intel_ring_begin, do not
+ * allow us to be interruptible by a signal.
+ */
+ was_interruptible = dev_priv->mm.interruptible;
+ dev_priv->mm.interruptible = false;
+
+ ret = i915_wait_request(ring, seqno);
+
+ dev_priv->mm.interruptible = was_interruptible;
+
+ return ret;
+}
+
+static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
+{
+ struct drm_i915_gem_request *request;
+ u32 seqno = 0;
+ int ret;
+
+ i915_gem_retire_requests_ring(ring);
+
+ if (ring->last_retired_head != -1) {
+ ring->head = ring->last_retired_head;
+ ring->last_retired_head = -1;
+ ring->space = ring_space(ring);
+ if (ring->space >= n)
+ return 0;
+ }
+
+ list_for_each_entry(request, &ring->request_list, list) {
+ int space;
+
+ if (request->tail == -1)
+ continue;
+
+ space = request->tail - (ring->tail + 8);
+ if (space < 0)
+ space += ring->size;
+ if (space >= n) {
+ seqno = request->seqno;
+ break;
+ }
+
+ /* Consume this request in case we need more space than
+ * is available and so need to prevent a race between
+ * updating last_retired_head and direct reads of
+ * I915_RING_HEAD. It also provides a nice sanity check.
+ */
+ request->tail = -1;
+ }
+
+ if (seqno == 0)
+ return -ENOSPC;
+
+ ret = intel_ring_wait_seqno(ring, seqno);
+ if (ret)
+ return ret;
+
+ if (WARN_ON(ring->last_retired_head == -1))
+ return -ENOSPC;
+
+ ring->head = ring->last_retired_head;
+ ring->last_retired_head = -1;
+ ring->space = ring_space(ring);
+ if (WARN_ON(ring->space < n))
+ return -ENOSPC;
+
+ return 0;
+}
+
int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n)
{
struct drm_device *dev = ring->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long end;
+ int ret;
+
+ ret = intel_ring_wait_request(ring, n);
+ if (ret != -ENOSPC)
+ return ret;
trace_i915_ring_wait_begin(ring);
if (drm_core_check_feature(dev, DRIVER_GEM))
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 4c5338c..855233b 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -46,6 +46,16 @@ struct intel_ring_buffer {
int effective_size;
struct intel_hw_status_page status_page;
+ /** We track the position of the requests in the ring buffer, and
+ * when each is retired we increment last_retired_head as the GPU
+ * must have finished processing the request and so we know we
+ * can advance the ringbuffer up to that position.
+ *
+ * last_retired_head is set to -1 after the value is consumed so
+ * we can detect new retirements.
+ */
+ u32 last_retired_head;
+
spinlock_t irq_lock;
u32 irq_refcount;
u32 irq_mask;
@@ -191,6 +201,11 @@ int intel_init_blt_ring_buffer(struct drm_device *dev);
u32 intel_ring_get_active_head(struct intel_ring_buffer *ring);
void intel_ring_setup_status_page(struct intel_ring_buffer *ring);
+static inline u32 intel_ring_get_tail(struct intel_ring_buffer *ring)
+{
+ return ring->tail;
+}
+
static inline void i915_trace_irq_get(struct intel_ring_buffer *ring, u32 seqno)
{
if (ring->trace_irq_seqno == 0 && ring->irq_get(ring))
--
1.7.9
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 2/3] drm/i915: Record the in-flight requests at the time of a hang 2012-02-15 11:25 [PATCH 1/3] drm/i915: Record the tail at each request and use it to estimate the head Chris Wilson @ 2012-02-15 11:25 ` Chris Wilson 2012-02-15 11:25 ` [PATCH 3/3] drm/i915: Record the position of the request upon error Chris Wilson 2012-02-15 13:33 ` [PATCH 1/3] drm/i915: Record the tail at each request and use it to estimate the head Daniel Vetter 2 siblings, 0 replies; 4+ messages in thread From: Chris Wilson @ 2012-02-15 11:25 UTC (permalink / raw) To: intel-gfx Being able to tally the list of outstanding requests with the sequence of commands in the ringbuffer is often useful evidence with respect to driver corruption. Note that since this is the umpteenth per-ring data structure to be added to the error state, I've coallesced the nearby loops (the ringbuffer and batchbuffer) into a single structure along with the list of requests. A later task would be to refactor the ring register state into the same structure. v2: Fix pretty printing of requests so that they are parsed correctly by intel_error_decode and use the 0x%08x format for seqno for consistency Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> --- drivers/gpu/drm/i915/i915_debugfs.c | 24 ++++++++---- drivers/gpu/drm/i915/i915_drv.h | 17 ++++++-- drivers/gpu/drm/i915/i915_irq.c | 73 ++++++++++++++++++++++++---------- 3 files changed, 79 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 88bda69..1c89585 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -745,7 +745,7 @@ static int i915_error_state(struct seq_file *m, void *unused) drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_error_state *error; unsigned long flags; - int i, page, offset, elt; + int i, j, page, offset, elt; spin_lock_irqsave(&dev_priv->error_lock, flags); error = dev_priv->first_error; @@ -789,10 +789,10 @@ static int i915_error_state(struct seq_file *m, void *unused) error->pinned_bo, error->pinned_bo_count); - for (i = 0; i < ARRAY_SIZE(error->batchbuffer); i++) { - if (error->batchbuffer[i]) { - struct drm_i915_error_object *obj = error->batchbuffer[i]; + for (i = 0; i < ARRAY_SIZE(error->ring); i++) { + struct drm_i915_error_object *obj; + if ((obj = error->ring[i].batchbuffer)) { seq_printf(m, "%s --- gtt_offset = 0x%08x\n", dev_priv->ring[i].name, obj->gtt_offset); @@ -804,11 +804,19 @@ static int i915_error_state(struct seq_file *m, void *unused) } } } - } - for (i = 0; i < ARRAY_SIZE(error->ringbuffer); i++) { - if (error->ringbuffer[i]) { - struct drm_i915_error_object *obj = error->ringbuffer[i]; + if (error->ring[i].num_requests) { + seq_printf(m, "%s --- %d requests\n", + dev_priv->ring[i].name, + error->ring[i].num_requests); + for (j = 0; j < error->ring[i].num_requests; j++) { + seq_printf(m, " seqno 0x%08x, emitted %ld\n", + error->ring[i].requests[j].seqno, + error->ring[i].requests[j].jiffies); + } + } + + if ((obj = error->ring[i].ringbuffer)) { seq_printf(m, "%s --- ringbuffer = 0x%08x\n", dev_priv->ring[i].name, obj->gtt_offset); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e8e1b85..8f6ae11 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -172,11 +172,18 @@ struct drm_i915_error_state { u32 faddr[I915_NUM_RINGS]; u64 fence[I915_MAX_NUM_FENCES]; struct timeval time; - struct drm_i915_error_object { - int page_count; - u32 gtt_offset; - u32 *pages[0]; - } *ringbuffer[I915_NUM_RINGS], *batchbuffer[I915_NUM_RINGS]; + struct drm_i915_error_ring { + struct drm_i915_error_object { + int page_count; + u32 gtt_offset; + u32 *pages[0]; + } *ringbuffer, *batchbuffer; + struct drm_i915_error_request { + long jiffies; + u32 seqno; + } *requests; + int num_requests; + } ring[I915_NUM_RINGS]; struct drm_i915_error_buffer { u32 size; u32 name; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 6266f57..3fc9756 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -790,11 +790,11 @@ i915_error_state_free(struct kref *error_ref) typeof(*error), ref); int i; - for (i = 0; i < ARRAY_SIZE(error->batchbuffer); i++) - i915_error_object_free(error->batchbuffer[i]); - - for (i = 0; i < ARRAY_SIZE(error->ringbuffer); i++) - i915_error_object_free(error->ringbuffer[i]); + for (i = 0; i < ARRAY_SIZE(error->ring); i++) { + i915_error_object_free(error->ring[i].batchbuffer); + i915_error_object_free(error->ring[i].ringbuffer); + kfree(error->ring[i].requests); + } kfree(error->active_bo); kfree(error->overlay); @@ -929,6 +929,51 @@ static void i915_record_ring_state(struct drm_device *dev, error->tail[ring->id] = I915_READ_TAIL(ring); } +static void i915_gem_record_rings(struct drm_device *dev, + struct drm_i915_error_state *error) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_request *request; + int i, count; + + for (i = 0; i < I915_NUM_RINGS; i++) { + struct intel_ring_buffer *ring = &dev_priv->ring[i]; + + if (ring->obj == NULL) + continue; + + i915_record_ring_state(dev, error, ring); + + error->ring[i].batchbuffer = + i915_error_first_batchbuffer(dev_priv, ring); + + error->ring[i].ringbuffer = + i915_error_object_create(dev_priv, ring->obj); + + count = 0; + list_for_each_entry(request, &ring->request_list, list) + count++; + + error->ring[i].num_requests = count; + error->ring[i].requests = + kmalloc(count*sizeof(struct drm_i915_error_request), + GFP_ATOMIC); + if (error->ring[i].requests == NULL) { + error->ring[i].num_requests = 0; + continue; + } + + count = 0; + list_for_each_entry(request, &ring->request_list, list) { + struct drm_i915_error_request *erq; + + erq = &error->ring[i].requests[count++]; + erq->seqno = request->seqno; + erq->jiffies = request->emitted_jiffies; + } + } +} + /** * i915_capture_error_state - capture an error record for later analysis * @dev: drm device @@ -973,24 +1018,8 @@ static void i915_capture_error_state(struct drm_device *dev) error->done_reg = I915_READ(DONE_REG); } - i915_record_ring_state(dev, error, &dev_priv->ring[RCS]); - if (HAS_BLT(dev)) - i915_record_ring_state(dev, error, &dev_priv->ring[BCS]); - if (HAS_BSD(dev)) - i915_record_ring_state(dev, error, &dev_priv->ring[VCS]); - i915_gem_record_fences(dev, error); - - /* Record the active batch and ring buffers */ - for (i = 0; i < I915_NUM_RINGS; i++) { - error->batchbuffer[i] = - i915_error_first_batchbuffer(dev_priv, - &dev_priv->ring[i]); - - error->ringbuffer[i] = - i915_error_object_create(dev_priv, - dev_priv->ring[i].obj); - } + i915_gem_record_rings(dev, error); /* Record buffers on the active and pinned lists. */ error->active_bo = NULL; -- 1.7.9 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 3/3] drm/i915: Record the position of the request upon error 2012-02-15 11:25 [PATCH 1/3] drm/i915: Record the tail at each request and use it to estimate the head Chris Wilson 2012-02-15 11:25 ` [PATCH 2/3] drm/i915: Record the in-flight requests at the time of a hang Chris Wilson @ 2012-02-15 11:25 ` Chris Wilson 2012-02-15 13:33 ` [PATCH 1/3] drm/i915: Record the tail at each request and use it to estimate the head Daniel Vetter 2 siblings, 0 replies; 4+ messages in thread From: Chris Wilson @ 2012-02-15 11:25 UTC (permalink / raw) To: intel-gfx So that we can tally the request against the command sequence in the ringbuffer, or merely jump to the interesting locations. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> --- drivers/gpu/drm/i915/i915_debugfs.c | 5 +++-- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_irq.c | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 1c89585..6b35452 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -810,9 +810,10 @@ static int i915_error_state(struct seq_file *m, void *unused) dev_priv->ring[i].name, error->ring[i].num_requests); for (j = 0; j < error->ring[i].num_requests; j++) { - seq_printf(m, " seqno 0x%08x, emitted %ld\n", + seq_printf(m, " seqno 0x%08x, emitted %ld, tail 0x%08x\n", error->ring[i].requests[j].seqno, - error->ring[i].requests[j].jiffies); + error->ring[i].requests[j].jiffies, + error->ring[i].requests[j].tail); } } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8f6ae11..3ab593b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -181,6 +181,7 @@ struct drm_i915_error_state { struct drm_i915_error_request { long jiffies; u32 seqno; + u32 tail; } *requests; int num_requests; } ring[I915_NUM_RINGS]; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 3fc9756..e61f8c1 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -970,6 +970,7 @@ static void i915_gem_record_rings(struct drm_device *dev, erq = &error->ring[i].requests[count++]; erq->seqno = request->seqno; erq->jiffies = request->emitted_jiffies; + erq->tail = request->tail; } } } -- 1.7.9 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 1/3] drm/i915: Record the tail at each request and use it to estimate the head 2012-02-15 11:25 [PATCH 1/3] drm/i915: Record the tail at each request and use it to estimate the head Chris Wilson 2012-02-15 11:25 ` [PATCH 2/3] drm/i915: Record the in-flight requests at the time of a hang Chris Wilson 2012-02-15 11:25 ` [PATCH 3/3] drm/i915: Record the position of the request upon error Chris Wilson @ 2012-02-15 13:33 ` Daniel Vetter 2 siblings, 0 replies; 4+ messages in thread From: Daniel Vetter @ 2012-02-15 13:33 UTC (permalink / raw) To: Chris Wilson; +Cc: intel-gfx On Wed, Feb 15, 2012 at 11:25:36AM +0000, Chris Wilson wrote: > By recording the location of every request in the ringbuffer, we know > that in order to retire the request the GPU must have finished reading > it and so the GPU head is now beyond the tail of the request. We can > therefore provide a conservative estimate of where the GPU is reading > from in order to avoid having to read back the ring buffer registers > when polling for space upon starting a new write into the ringbuffer. > > A secondary effect is that this allows us to convert > intel_ring_buffer_wait() to use i915_wait_request() and so consolidate > upon the single function to handle the complicated task of waiting upon > the GPU. A necessary precaution is that we need to make that wait > uninterruptible to match the existing conditions as all the callers of > intel_ring_begin() have not been audited to handle ERESTARTSYS > correctly. > > By using a conservative estimate for the head, and always processing all > outstanding requests first, we prevent a race condition between using > the estimate and direct reads of I915_RING_HEAD which could result in > the value of the head going backwards, and the tail overflowing once > again. We are also careful to mark any request that we skip over in > order to free space in ring as consumed which provides a > self-consistency check. > > Given sufficient abuse, such as a set of unthrottled GPU bound > cairo-traces, avoiding the use of I915_RING_HEAD gives a 10-20% boost on > Sandy Bridge (i5-2520m): > firefox-paintball 18927ms -> 15646ms: 1.21x speedup > firefox-fishtank 12563ms -> 11278ms: 1.11x speedup > which is a mild consolation for the performance those traces achieved from > exploiting the buggy autoreported head. > > v2: Add a few more comments and make request->tail a conservative > estimate as suggested by Daniel Vetter. > > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Thanks for these 3 patches, queued for next. I've had to resolve a little conflict in this one because - you've based these on a three without Ben's defer retirement patches - and I don't want to double-merge the autoreport_head removal patch to both -fixes and -next For next plans I think this is all for the current round, I plan to push out a new -next for testing in 1-2 days. -Daniel -- Daniel Vetter Mail: daniel@ffwll.ch Mobile: +41 (0)79 365 57 48 ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2012-02-15 13:33 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-02-15 11:25 [PATCH 1/3] drm/i915: Record the tail at each request and use it to estimate the head Chris Wilson 2012-02-15 11:25 ` [PATCH 2/3] drm/i915: Record the in-flight requests at the time of a hang Chris Wilson 2012-02-15 11:25 ` [PATCH 3/3] drm/i915: Record the position of the request upon error Chris Wilson 2012-02-15 13:33 ` [PATCH 1/3] drm/i915: Record the tail at each request and use it to estimate the head Daniel Vetter
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox