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

Commit 6f44033f authored by Harshdeep Dhatt's avatar Harshdeep Dhatt
Browse files

msm: kgsl: Remove the extra recovery hop



Currently, when we try to boot the gmu and it fails,
we force off the gmu gdsc followed by an inline
attempt to boot the gmu again. To do this, we go an
extra mile to do complex snapshot and power state
magic.

The same goal can be achieved by a simpler and
easier to maintain code path:

Set the state to KGSL_STATE_RESET upon gmu boot failure
so that the error path performs a RESET -> SLUMBER
transition. Here, we can reset the GMU so that next
SLUMBER exit can start afresh.

Change-Id: I4d3e75f40062e9fe5d71fe1e6010dfff75e09321
Signed-off-by: default avatarHarshdeep Dhatt <hdhatt@codeaurora.org>
parent be60d9a0
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1522,6 +1522,9 @@ static int gmu_suspend(struct kgsl_device *device)
		regulator_set_mode(gmu->cx_gdsc, REGULATOR_MODE_NORMAL);

	dev_err(&gmu->pdev->dev, "Suspended GMU\n");

	clear_bit(GMU_FAULT, &device->gmu_core.flags);

	return 0;
}

+17 −53
Original line number Diff line number Diff line
@@ -1804,7 +1804,6 @@ static int
_aware(struct kgsl_device *device)
{
	int status = 0;
	unsigned int state = device->state;

	switch (device->state) {
	case KGSL_STATE_RESET:
@@ -1832,65 +1831,23 @@ _aware(struct kgsl_device *device)
		kgsl_pwrscale_midframe_timer_cancel(device);
		break;
	case KGSL_STATE_SLUMBER:
		/* if GMU already in FAULT */
		if (gmu_core_isenabled(device) &&
			test_bit(GMU_FAULT, &device->gmu_core.flags)) {
			status = -EINVAL;
			break;
		}

		status = kgsl_pwrctrl_enable(device);
		break;
	default:
		status = -EINVAL;
	}

	if (status) {
		if (gmu_core_isenabled(device)) {
			/* GMU hang recovery */
			kgsl_pwrctrl_set_state(device, KGSL_STATE_RESET);
			set_bit(GMU_FAULT, &device->gmu_core.flags);
			status = kgsl_pwrctrl_enable(device);
			/* Cannot recover GMU failure GPU will not power on */

			if (WARN_ONCE(status, "Failed to recover GMU\n")) {
				if (device->snapshot)
					device->snapshot->recovered = false;
		if (status && gmu_core_isenabled(device))
			/*
				 * On recovery failure, we are clearing
				 * GMU_FAULT bit and also not keeping
				 * the state as RESET to make sure any
				 * attempt to wake GMU/GPU after this
				 * is treated as a fresh start. But on
				 * recovery failure, GMU HS, clocks and
				 * IRQs are still ON/enabled because of
				 * which next GMU/GPU wakeup results in
				 * multiple warnings from GMU start as HS,
				 * clocks and IRQ were ON while doing a
				 * fresh start i.e. wake from SLUMBER.
				 *
				 * Suspend the GMU on recovery failure
				 * to make sure next attempt to wake up
				 * GMU/GPU is indeed a fresh start.
			 * SLUMBER -> AWARE failed which means GMU boot failed.
			 * Make sure we reset the GMU while transitioning back
			 * to SLUMBER.
			 */
				kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
				gmu_core_suspend(device);
				kgsl_pwrctrl_set_state(device, state);
			} else {
				if (device->snapshot)
					device->snapshot->recovered = true;
				kgsl_pwrctrl_set_state(device,
					KGSL_STATE_AWARE);
			}
			kgsl_pwrctrl_set_state(device, KGSL_STATE_RESET);

			clear_bit(GMU_FAULT, &device->gmu_core.flags);
			return status;
		break;
	default:
		status = -EINVAL;
	}

		kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
	} else {
	if (!status)
		kgsl_pwrctrl_set_state(device, KGSL_STATE_AWARE);
	}

	return status;
}

@@ -1967,6 +1924,13 @@ _slumber(struct kgsl_device *device)
		kgsl_pwrctrl_disable(device);
		kgsl_pwrctrl_set_state(device, KGSL_STATE_SLUMBER);
		break;
	case KGSL_STATE_RESET:
		if (gmu_core_isenabled(device)) {
			 /* Reset the GMU if we failed to boot the GMU */
			gmu_core_suspend(device);
			kgsl_pwrctrl_set_state(device, KGSL_STATE_SLUMBER);
		}
		break;
	default:
		kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
		break;