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

Commit 5e1b78bd authored by Kyle Piefer's avatar Kyle Piefer
Browse files

msm: kgsl: Prevent repeated FENCE stuck errors



If the AHB fence is in DROP mode when we enter the RBBM
interrupt handler, it is usually harmless. The GMU will
see the pending interrupt and abort power collapse, causing
the fence to be set back to ALLOW. Until this happens though,
we cannot proceed to read the IRQ status and write the clear
register because they are inaccessible.

Poll the fence status until it is ALLOW and we can proceed.
If we poll for too long and the fence is still stuck,
the GMU is probably hung. In this case print an error
message and give up.

Change-Id: I6321d61778dde21f46d40eb3eba157907297dac6
Signed-off-by: default avatarKyle Piefer <kpiefer@codeaurora.org>
parent 1cc4edf0
Loading
Loading
Loading
Loading
+18 −7
Original line number Diff line number Diff line
@@ -610,7 +610,7 @@ static irqreturn_t adreno_irq_handler(struct kgsl_device *device)
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
	struct adreno_irq *irq_params = gpudev->irq;
	irqreturn_t ret = IRQ_NONE;
	unsigned int status = 0, fence = 0, tmp, int_bit;
	unsigned int status = 0, fence = 0, fence_retries = 0, tmp, int_bit;
	int i;

	atomic_inc(&adreno_dev->pending_irq_refcnt);
@@ -627,14 +627,25 @@ static irqreturn_t adreno_irq_handler(struct kgsl_device *device)

	/*
	 * If the AHB fence is not in ALLOW mode when we receive an RBBM
	 * interrupt, something went wrong. Set a fault and change the
	 * fence to ALLOW so we can clear the interrupt.
	 * interrupt, something went wrong. This means that we cannot proceed
	 * since the IRQ status and clear registers are not accessible.
	 * This is usually harmless because the GMU will abort power collapse
	 * and change the fence back to ALLOW. Poll so that this can happen.
	 */
	adreno_readreg(adreno_dev, ADRENO_REG_GMU_AO_AHB_FENCE_CTRL, &fence);
	if (fence != 0) {
		KGSL_DRV_CRIT_RATELIMIT(device, "AHB fence is stuck in ISR\n");
	if (kgsl_gmu_isenabled(device)) {
		do {
			adreno_readreg(adreno_dev,
					ADRENO_REG_GMU_AO_AHB_FENCE_CTRL,
					&fence);

			if (fence_retries == FENCE_RETRY_MAX) {
				KGSL_DRV_CRIT_RATELIMIT(device,
						"AHB fence stuck in ISR\n");
				return ret;
			}
			fence_retries++;
		} while (fence != 0);
	}

	adreno_readreg(adreno_dev, ADRENO_REG_RBBM_INT_0_STATUS, &status);

+3 −0
Original line number Diff line number Diff line
@@ -164,6 +164,9 @@
/* Number of times to try hard reset */
#define NUM_TIMES_RESET_RETRY 5

/* Number of times to poll the AHB fence in ISR */
#define FENCE_RETRY_MAX 100

/* One cannot wait forever for the core to idle, so set an upper limit to the
 * amount of time to wait for the core to go idle
 */