From 6f44033fb9683bbf8ce6dfadd52e29593cffdb1d Mon Sep 17 00:00:00 2001 From: Harshdeep Dhatt Date: Thu, 8 Aug 2019 20:50:37 -0600 Subject: [PATCH] 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 --- drivers/gpu/msm/kgsl_gmu.c | 3 ++ drivers/gpu/msm/kgsl_pwrctrl.c | 70 +++++++++------------------------- 2 files changed, 20 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c index 7d1c93a5e7bc..13432796a4a3 100644 --- a/drivers/gpu/msm/kgsl_gmu.c +++ b/drivers/gpu/msm/kgsl_gmu.c @@ -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; } diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index 608397b50b9b..fe2788e41c43 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -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;