drm/msm: spin helper
Helper macro to simplify places where we need to poll with timeout
waiting for gpu.
Signed-off-by: Rob Clark <robdclark@gmail.com>
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
index 8b6fb84..59ed762 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
@@ -326,21 +326,13 @@
static void a3xx_idle(struct msm_gpu *gpu)
{
- unsigned long t;
-
/* wait for ringbuffer to drain: */
adreno_idle(gpu);
- t = jiffies + ADRENO_IDLE_TIMEOUT;
-
/* then wait for GPU to finish: */
- do {
- uint32_t rbbm_status = gpu_read(gpu, REG_A3XX_RBBM_STATUS);
- if (!(rbbm_status & A3XX_RBBM_STATUS_GPU_BUSY))
- return;
- } while(time_before(jiffies, t));
-
- DRM_ERROR("timeout waiting for %s to idle!\n", gpu->name);
+ if (spin_until(!(gpu_read(gpu, REG_A3XX_RBBM_STATUS) &
+ A3XX_RBBM_STATUS_GPU_BUSY)))
+ DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
/* TODO maybe we need to reset GPU here to recover from hang? */
}
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index cf6eb97..7a11563 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -225,19 +225,11 @@
void adreno_idle(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
- uint32_t rptr, wptr = get_wptr(gpu->rb);
- unsigned long t;
+ uint32_t wptr = get_wptr(gpu->rb);
- t = jiffies + ADRENO_IDLE_TIMEOUT;
-
- /* then wait for CP to drain ringbuffer: */
- do {
- rptr = adreno_gpu->memptrs->rptr;
- if (rptr == wptr)
- return;
- } while(time_before(jiffies, t));
-
- DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name);
+ /* wait for CP to drain ringbuffer: */
+ if (spin_until(adreno_gpu->memptrs->rptr == wptr))
+ DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name);
/* TODO maybe we need to reset GPU here to recover from hang? */
}
@@ -278,22 +270,19 @@
}
-void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords)
+static uint32_t ring_freewords(struct msm_gpu *gpu)
{
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;
+ uint32_t size = gpu->rb->size / 4;
+ uint32_t wptr = get_wptr(gpu->rb);
+ uint32_t rptr = adreno_gpu->memptrs->rptr;
+ return (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);
+void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords)
+{
+ if (spin_until(ring_freewords(gpu) >= ndwords))
+ DRM_ERROR("%s: timeout waiting for ringbuffer space\n", gpu->name);
}
static const char *iommu_ports[] = {
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index e16200d..63c36ce 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -76,7 +76,20 @@
#endif
};
-#define ADRENO_IDLE_TIMEOUT (20 * 1000)
+#define ADRENO_IDLE_TIMEOUT msecs_to_jiffies(1000)
+
+#define spin_until(X) ({ \
+ int __ret = -ETIMEDOUT; \
+ unsigned long __t = jiffies + ADRENO_IDLE_TIMEOUT; \
+ do { \
+ if (X) { \
+ __ret = 0; \
+ break; \
+ } \
+ } while (time_before(jiffies, __t)); \
+ __ret; \
+})
+
static inline bool adreno_is_a3xx(struct adreno_gpu *gpu)
{