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

Commit 2c7fecd9 authored by Carter Cooper's avatar Carter Cooper
Browse files

msm: kgsl: Ensure the GMU updates the wptr register



There is a chance that the GMU is powered down when KGSL tries to
update the ringbuffer wptr. If that happens, the wptr update will
be dropped. So if using the GMU, verify the update wasn't dropped.
If it was dropped, then repost the register write until it succeeds.

Change-Id: I08f900bf8689532ff0c994d29b5e20f2a211dfa4
Signed-off-by: default avatarCarter Cooper <ccooper@codeaurora.org>
parent df7ba70a
Loading
Loading
Loading
Loading
+45 −1
Original line number Diff line number Diff line
@@ -86,7 +86,43 @@ static void adreno_get_submit_time(struct adreno_device *adreno_dev,
	local_irq_restore(flags);
}

void adreno_ringbuffer_wptr(struct adreno_device *adreno_dev,
/*
 * Wait time before trying to write the register again.
 * Hopefully the GMU has finished waking up during this delay.
 */
#define GMU_WAKEUP_DELAY 50
/* Max amount of tries to wake up the GMU. */
#define GMU_WAKEUP_RETRY_MAX 20

/*
 * Check the WRITEDROPPED0 bit in the
 * FENCE_STATUS regsiter to check if the write went
 * through. If it didn't then we retry the write.
 */
static inline void _gmu_wptr_update_if_dropped(struct adreno_device *adreno_dev,
		struct adreno_ringbuffer *rb)
{
	unsigned int val, i;

	for (i = 0; i < GMU_WAKEUP_RETRY_MAX; i++) {
		adreno_read_gmureg(adreno_dev, ADRENO_REG_GMU_AHB_FENCE_STATUS,
				&val);

		/* If !writedropped, then wptr update was successful */
		if (!(val & 0x1))
			return;

		/* Wait a small amount of time before trying again */
		udelay(GMU_WAKEUP_DELAY);

		/* Try to write WPTR again */
		adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_WPTR, rb->_wptr);
	}

	dev_err(adreno_dev->dev.dev, "GMU WPTR update timed out\n");
}

static void adreno_ringbuffer_wptr(struct adreno_device *adreno_dev,
		struct adreno_ringbuffer *rb)
{
	unsigned long flags;
@@ -102,6 +138,14 @@ void adreno_ringbuffer_wptr(struct adreno_device *adreno_dev,
			kgsl_pwrscale_busy(KGSL_DEVICE(adreno_dev));
			adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_WPTR,
				rb->_wptr);

			/*
			 * If GMU, ensure the write posted after a possible
			 * GMU wakeup (write could have dropped during wakeup)
			 */
			if (kgsl_gmu_isenabled(KGSL_DEVICE(adreno_dev)))
				_gmu_wptr_update_if_dropped(adreno_dev, rb);

		}
	}