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>
This commit is contained in:
Rob Clark 2014-01-11 16:11:59 -05:00
parent 5b6ef08e4b
commit 0963756fe5
3 changed files with 31 additions and 37 deletions

View file

@ -326,21 +326,13 @@ static void a3xx_destroy(struct msm_gpu *gpu)
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? */
}

View file

@ -225,19 +225,11 @@ void adreno_flush(struct msm_gpu *gpu)
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_dump(struct msm_gpu *gpu)
}
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[] = {

View file

@ -76,7 +76,20 @@ struct adreno_platform_config {
#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)
{