From 0d44684cabc075a671060b70b28a4f29da4f973c Mon Sep 17 00:00:00 2001 From: Harshdeep Dhatt Date: Thu, 8 Aug 2019 21:01:28 -0600 Subject: [PATCH] msm: kgsl: Take GMU snapshot on GMU failures GMU can fail to turn on GX or it can fail the START HFI. So take snapshot and put GMU in NMI. When this happens, kgsl will call gmu_stop() and as GMU is already in fault aka NMI, reset the GMU and GPU. If oob during adreno_stop fails, take gmu snapshot and only do things that don't need gx to be on. Change-Id: Iafc9b34063a7ff2415d3462dd289b52e425fbf3b Signed-off-by: Harshdeep Dhatt --- drivers/gpu/msm/adreno.c | 44 ++++++++++++++++---------------------- drivers/gpu/msm/kgsl_gmu.c | 11 ++++++++++ 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 203521d9ce7c..d02abf18ad78 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -2057,12 +2057,16 @@ static int _adreno_start(struct adreno_device *adreno_dev) /* Send OOB request to turn on the GX */ status = gmu_core_dev_oob_set(device, oob_gpu); - if (status) - goto error_boot_oob_clear; + if (status) { + gmu_core_snapshot(device); + goto error_oob_clear; + } status = gmu_core_dev_hfi_start_msg(device); - if (status) + if (status) { + gmu_core_snapshot(device); goto error_oob_clear; + } if (device->pwrctrl.bus_control) { /* VBIF waiting for RAM */ @@ -2274,29 +2278,15 @@ static int adreno_stop(struct kgsl_device *device) error = gmu_core_dev_oob_set(device, oob_gpu); if (error) { gmu_core_dev_oob_clear(device, oob_gpu); - - if (gmu_core_regulator_isenabled(device)) { - /* GPU is on. Try recovery */ - set_bit(GMU_FAULT, &device->gmu_core.flags); gmu_core_snapshot(device); error = -EINVAL; - } + goto no_gx_power; } - adreno_dispatcher_stop(adreno_dev); - - adreno_ringbuffer_stop(adreno_dev); - kgsl_pwrscale_update_stats(device); adreno_irqctrl(adreno_dev, 0); - if (!IS_ERR_OR_NULL(adreno_dev->gpu_llc_slice)) - llcc_slice_deactivate(adreno_dev->gpu_llc_slice); - - if (!IS_ERR_OR_NULL(adreno_dev->gpuhtw_llc_slice)) - llcc_slice_deactivate(adreno_dev->gpuhtw_llc_slice); - /* Save active coresight registers if applicable */ adreno_coresight_stop(adreno_dev); @@ -2314,19 +2304,23 @@ static int adreno_stop(struct kgsl_device *device) */ if (!error && gmu_core_dev_wait_for_lowest_idle(device)) { - set_bit(GMU_FAULT, &device->gmu_core.flags); gmu_core_snapshot(device); - /* - * Assume GMU hang after 10ms without responding. - * It shall be relative safe to clear vbif and stop - * MMU later. Early return in adreno_stop function - * will result in kernel panic in adreno_start - */ error = -EINVAL; } adreno_clear_pending_transactions(device); +no_gx_power: + adreno_dispatcher_stop(adreno_dev); + + adreno_ringbuffer_stop(adreno_dev); + + if (!IS_ERR_OR_NULL(adreno_dev->gpu_llc_slice)) + llcc_slice_deactivate(adreno_dev->gpu_llc_slice); + + if (!IS_ERR_OR_NULL(adreno_dev->gpuhtw_llc_slice)) + llcc_slice_deactivate(adreno_dev->gpuhtw_llc_slice); + /* * The halt is not cleared in the above function if we have GBIF. * Clear it here if GMU is enabled as GMU stop needs access to diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c index c9386b59da9f..0e8e06b369d3 100644 --- a/drivers/gpu/msm/kgsl_gmu.c +++ b/drivers/gpu/msm/kgsl_gmu.c @@ -1674,6 +1674,12 @@ static void gmu_stop(struct kgsl_device *device) if (!test_bit(GMU_CLK_ON, &device->gmu_core.flags)) return; + /* Force suspend if gmu is already in fault */ + if (test_bit(GMU_FAULT, &device->gmu_core.flags)) { + gmu_core_suspend(device); + return; + } + /* Wait for the lowest idle level we requested */ if (gmu_core_dev_wait_for_lowest_idle(device)) goto error; @@ -1701,6 +1707,11 @@ static void gmu_stop(struct kgsl_device *device) error: dev_err(&gmu->pdev->dev, "Failed to stop GMU\n"); gmu_core_snapshot(device); + /* + * We failed to stop the gmu successfully. Force a suspend + * to set things up for a fresh start. + */ + gmu_core_suspend(device); } static void gmu_remove(struct kgsl_device *device)