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: Harshdeep Dhatt <hdhatt@codeaurora.org>
This commit is contained in:
Harshdeep Dhatt 2019-08-08 20:50:37 -06:00
commit 6f44033fb9
2 changed files with 20 additions and 53 deletions

View file

@ -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;
}

View file

@ -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);
if (status && gmu_core_isenabled(device))
/*
* SLUMBER -> AWARE failed which means GMU boot failed.
* Make sure we reset the GMU while transitioning back
* to SLUMBER.
*/
kgsl_pwrctrl_set_state(device, KGSL_STATE_RESET);
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;
/*
* 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.
*/
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);
}
clear_bit(GMU_FAULT, &device->gmu_core.flags);
return status;
}
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;