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

Commit fe8301e8 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: Trigger preemption only if GMU is in ACTIVE state"

parents 4644fb20 7afc6882
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -232,6 +232,38 @@ static struct adreno_ringbuffer *a6xx_next_ringbuffer(
	return NULL;
}

#define GMU_ACTIVE_STATE_RETRY_MAX 100

static int adreno_gmu_wait_for_active(struct adreno_device *adreno_dev)
{
	unsigned int reg, num_retries = 0;
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);

	if (!kgsl_gmu_isenabled(device))
		return 0;

	kgsl_gmu_regread(device,
		A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE, &reg);

	while (reg != GPU_HW_ACTIVE) {
		/* Wait for small time before trying again */
		udelay(5);
		kgsl_gmu_regread(device,
			A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE, &reg);

		if (num_retries == GMU_ACTIVE_STATE_RETRY_MAX &&
			reg != GPU_HW_ACTIVE) {
			dev_err(adreno_dev->dev.dev,
				"GMU failed to move to ACTIVE state: 0x%x\n",
				reg);
			return -ETIMEDOUT;
		}
		num_retries++;
	}

	return 0;
}

void a6xx_preemption_trigger(struct adreno_device *adreno_dev)
{
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
@@ -361,6 +393,23 @@ void a6xx_preemption_trigger(struct adreno_device *adreno_dev)
		upper_32_bits(gpuaddr),
		FENCE_STATUS_WRITEDROPPED1_MASK);

	/*
	 * Above fence writes will make sure GMU comes out of
	 * IFPC state if its was in IFPC state but it doesn't
	 * guarantee that GMU FW actually moved to ACTIVE state
	 * i.e. wake-up from IFPC is complete.
	 * Wait for GMU to move to ACTIVE state before triggering
	 * preemption. This is require to make sure CP doesn't
	 * interrupt GMU during wake-up from IFPC.
	 */
	if (adreno_gmu_wait_for_active(adreno_dev)) {
		adreno_set_preempt_state(adreno_dev, ADRENO_PREEMPT_NONE);

		adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT);
		adreno_dispatcher_schedule(device);
		return;
	}

	adreno_dev->next_rb = next;

	/* Start the timer to detect a stuck preemption */