Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0963756f authored by Rob Clark's avatar Rob Clark
Browse files

drm/msm: spin helper



Helper macro to simplify places where we need to poll with timeout
waiting for gpu.

Signed-off-by: default avatarRob Clark <robdclark@gmail.com>
parent 5b6ef08e
Loading
Loading
Loading
Loading
+3 −11
Original line number Diff line number Diff line
@@ -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? */
}
+15 −26
Original line number Diff line number Diff line
@@ -225,18 +225,10 @@ 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;

	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));
	uint32_t wptr = get_wptr(gpu->rb);

	/* 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;
	return (rptr + (size - 1) - wptr) % size;
}

		if (time_after(jiffies, t)) {
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);
			break;
		}
	} while(freedwords < ndwords);
}

static const char *iommu_ports[] = {
+14 −1
Original line number Diff line number Diff line
@@ -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)
{