Skip to content

Commit

Permalink
drm/msm: hangcheck harder
Browse files Browse the repository at this point in the history
If gpu locks up with the rptr shortly beyond the wrap-around point in
the ringbuffer, because the rptr was not reset (but wptr is, by virtue
of resetting rb->cur), we could end up in a scenario where we think
there is not enough space in the ringbuffer for the next cmds.  And
since the CP won't reset rptr until after processing an IB, this leaves
things in a sort of deadlock.

So reset rptr too.  And a bit more spiffing up of hangcheck to make
things easier to debug.

Signed-off-by: Rob Clark <robdclark@gmail.com>
  • Loading branch information
Rob Clark committed Sep 10, 2013
1 parent bf6811f commit 26791c4
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 2 deletions.
10 changes: 9 additions & 1 deletion drivers/gpu/drm/msm/adreno/adreno_gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ void adreno_recover(struct msm_gpu *gpu)

/* reset completed fence seqno, just discard anything pending: */
adreno_gpu->memptrs->fence = gpu->submitted_fence;
adreno_gpu->memptrs->rptr = 0;
adreno_gpu->memptrs->wptr = 0;

gpu->funcs->pm_resume(gpu);
ret = gpu->funcs->hw_init(gpu);
Expand Down Expand Up @@ -229,7 +231,7 @@ void adreno_idle(struct msm_gpu *gpu)
return;
} while(time_before(jiffies, t));

DRM_ERROR("timeout waiting for %s to drain ringbuffer!\n", gpu->name);
DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name);

/* TODO maybe we need to reset GPU here to recover from hang? */
}
Expand All @@ -256,11 +258,17 @@ void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
uint32_t freedwords;
unsigned long t = jiffies + ADRENO_IDLE_TIMEOUT;
do {
uint32_t size = gpu->rb->size / 4;
uint32_t wptr = get_wptr(gpu->rb);
uint32_t rptr = adreno_gpu->memptrs->rptr;
freedwords = (rptr + (size - 1) - wptr) % size;

if (time_after(jiffies, t)) {
DRM_ERROR("%s: timeout waiting for ringbuffer space\n", gpu->name);
break;
}
} while(freedwords < ndwords);
}

Expand Down
9 changes: 8 additions & 1 deletion drivers/gpu/drm/msm/msm_gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,15 @@ static void hangcheck_handler(unsigned long data)
gpu->hangcheck_fence = fence;
} else if (fence < gpu->submitted_fence) {
/* no progress and not done.. hung! */
struct msm_drm_private *priv = gpu->dev->dev_private;
struct drm_device *dev = gpu->dev;
struct msm_drm_private *priv = dev->dev_private;
gpu->hangcheck_fence = fence;
dev_err(dev->dev, "%s: hangcheck detected gpu lockup!\n",
gpu->name);
dev_err(dev->dev, "%s: completed fence: %u\n",
gpu->name, fence);
dev_err(dev->dev, "%s: submitted fence: %u\n",
gpu->name, gpu->submitted_fence);
queue_work(priv->wq, &gpu->recover_work);
}

Expand Down

0 comments on commit 26791c4

Please sign in to comment.