msm: kgsl: Do not allocate space in ringbuffer for hung context
If a hang is detected when allocating space in ringbuffer and
if the context for which the space is being allocated is hung
then do not allocate space at all.
Change-Id: Ia5ade2341fe5016119d8c140413860420c5c3a3d
Signed-off-by: Shubhraprakash Das <sadas@codeaurora.org>
Signed-off-by: Rajeev Kulkarni <krajeev@codeaurora.org>
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 1a9da60..db913a5 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -44,9 +44,10 @@
adreno_regwrite(rb->device, REG_CP_RB_WPTR, rb->wptr);
}
-static void
-adreno_ringbuffer_waitspace(struct adreno_ringbuffer *rb, unsigned int numcmds,
- int wptr_ahead)
+static int
+adreno_ringbuffer_waitspace(struct adreno_ringbuffer *rb,
+ struct adreno_context *context,
+ unsigned int numcmds, int wptr_ahead)
{
int nopcount;
unsigned int freecmds;
@@ -120,19 +121,28 @@
continue;
err:
- if (!adreno_dump_and_recover(rb->device))
- wait_time = jiffies + wait_timeout;
- else
- /* GPU is hung and we cannot recover */
- BUG();
+ if (!adreno_dump_and_recover(rb->device)) {
+ if (context && context->flags & CTXT_FLAGS_GPU_HANG) {
+ KGSL_CTXT_WARN(rb->device,
+ "Context %p caused a gpu hang. Will not accept commands for context %d\n",
+ context, context->id);
+ return -EDEADLK;
+ }
+ wait_time = jiffies + wait_timeout;
+ } else {
+ /* GPU is hung and we cannot recover */
+ BUG();
+ }
}
+ return 0;
}
unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb,
- unsigned int numcmds)
+ struct adreno_context *context,
+ unsigned int numcmds)
{
- unsigned int *ptr = NULL;
-
+ unsigned int *ptr = NULL;
+ int ret = 0;
BUG_ON(numcmds >= rb->sizedwords);
GSL_RB_GET_READPTR(rb, &rb->rptr);
@@ -142,20 +152,25 @@
/* reserve dwords for nop packet */
if ((rb->wptr + numcmds) > (rb->sizedwords -
GSL_RB_NOP_SIZEDWORDS))
- adreno_ringbuffer_waitspace(rb, numcmds, 1);
+ ret = adreno_ringbuffer_waitspace(rb, context,
+ numcmds, 1);
} else {
/* wptr behind rptr */
if ((rb->wptr + numcmds) >= rb->rptr)
- adreno_ringbuffer_waitspace(rb, numcmds, 0);
+ ret = adreno_ringbuffer_waitspace(rb, context,
+ numcmds, 0);
/* check for remaining space */
/* reserve dwords for nop packet */
- if ((rb->wptr + numcmds) > (rb->sizedwords -
+ if (!ret && (rb->wptr + numcmds) > (rb->sizedwords -
GSL_RB_NOP_SIZEDWORDS))
- adreno_ringbuffer_waitspace(rb, numcmds, 1);
+ ret = adreno_ringbuffer_waitspace(rb, context,
+ numcmds, 1);
}
- ptr = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr;
- rb->wptr += numcmds;
+ if (!ret) {
+ ptr = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr;
+ rb->wptr += numcmds;
+ }
return ptr;
}
@@ -512,13 +527,12 @@
total_sizedwords += 4; /* global timestamp for recovery*/
}
- ringcmds = adreno_ringbuffer_allocspace(rb, total_sizedwords);
- /* GPU may hang during space allocation, if thats the case the current
- * context may have hung the GPU */
- if (context->flags & CTXT_FLAGS_GPU_HANG) {
- KGSL_CTXT_WARN(rb->device,
- "Context %p caused a gpu hang. Will not accept commands for context %d\n",
- context, context->id);
+ ringcmds = adreno_ringbuffer_allocspace(rb, context, total_sizedwords);
+ if (!ringcmds) {
+ /*
+ * We could not allocate space in ringbuffer, just return the
+ * last timestamp
+ */
return rb->timestamp[context_id];
}