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)