Loading drivers/gpu/msm/kgsl_gmu.c +15 −3 Original line number Diff line number Diff line Loading @@ -1322,7 +1322,7 @@ static int gmu_disable_gdsc(struct gmu_device *gmu) return -ETIMEDOUT; } static int gmu_suspend(struct kgsl_device *device) int gmu_suspend(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); Loading Loading @@ -1408,6 +1408,7 @@ int gmu_start(struct kgsl_device *device) struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct gmu_device *gmu = &device->gmu; unsigned int boot_state = GMU_WARM_BOOT; switch (device->state) { case KGSL_STATE_INIT: Loading Loading @@ -1444,12 +1445,21 @@ int gmu_start(struct kgsl_device *device) gmu_enable_clks(gmu); gmu_irq_enable(device); /* * If unrecovered is set that means last * wakeup from SLUMBER state failed. Use GMU * and HFI boot state as COLD as this is a * boot after RESET. */ if (gmu->unrecovered) boot_state = GMU_COLD_BOOT; ret = gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_START, GMU_WARM_BOOT, 0); boot_state, 0); if (ret) goto error_gmu; ret = hfi_start(gmu, GMU_WARM_BOOT); ret = hfi_start(gmu, boot_state); if (ret) goto error_gmu; Loading Loading @@ -1495,6 +1505,8 @@ int gmu_start(struct kgsl_device *device) break; } /* Clear unrecovered as GMU start is successful */ gmu->unrecovered = false; return ret; error_gmu: Loading drivers/gpu/msm/kgsl_gmu.h +3 −0 Original line number Diff line number Diff line Loading @@ -212,6 +212,7 @@ enum gpu_idle_level { * @ccl: CNOC BW scaling client * @idle_level: Minimal GPU idle power level * @fault_count: GMU fault count * @unrecovered: Indicates whether GMU recovery failed or not */ struct gmu_device { unsigned int ver; Loading Loading @@ -246,6 +247,7 @@ struct gmu_device { unsigned int ccl; unsigned int idle_level; unsigned int fault_count; bool unrecovered; }; void gmu_snapshot(struct kgsl_device *device); Loading @@ -255,6 +257,7 @@ void gmu_remove(struct kgsl_device *device); int allocate_gmu_image(struct gmu_device *gmu, unsigned int size); int gmu_start(struct kgsl_device *device); void gmu_stop(struct kgsl_device *device); int gmu_suspend(struct kgsl_device *device); int gmu_dcvs_set(struct gmu_device *gmu, unsigned int gpu_pwrlevel, unsigned int bus_level); #endif /* __KGSL_GMU_H */ drivers/gpu/msm/kgsl_pwrctrl.c +19 −0 Original line number Diff line number Diff line Loading @@ -2798,6 +2798,25 @@ _aware(struct kgsl_device *device) WARN_ONCE(1, "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. */ gmu_suspend(device); gmu->unrecovered = true; kgsl_pwrctrl_set_state(device, state); } else { if (device->snapshot) Loading Loading
drivers/gpu/msm/kgsl_gmu.c +15 −3 Original line number Diff line number Diff line Loading @@ -1322,7 +1322,7 @@ static int gmu_disable_gdsc(struct gmu_device *gmu) return -ETIMEDOUT; } static int gmu_suspend(struct kgsl_device *device) int gmu_suspend(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); Loading Loading @@ -1408,6 +1408,7 @@ int gmu_start(struct kgsl_device *device) struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct gmu_device *gmu = &device->gmu; unsigned int boot_state = GMU_WARM_BOOT; switch (device->state) { case KGSL_STATE_INIT: Loading Loading @@ -1444,12 +1445,21 @@ int gmu_start(struct kgsl_device *device) gmu_enable_clks(gmu); gmu_irq_enable(device); /* * If unrecovered is set that means last * wakeup from SLUMBER state failed. Use GMU * and HFI boot state as COLD as this is a * boot after RESET. */ if (gmu->unrecovered) boot_state = GMU_COLD_BOOT; ret = gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_START, GMU_WARM_BOOT, 0); boot_state, 0); if (ret) goto error_gmu; ret = hfi_start(gmu, GMU_WARM_BOOT); ret = hfi_start(gmu, boot_state); if (ret) goto error_gmu; Loading Loading @@ -1495,6 +1505,8 @@ int gmu_start(struct kgsl_device *device) break; } /* Clear unrecovered as GMU start is successful */ gmu->unrecovered = false; return ret; error_gmu: Loading
drivers/gpu/msm/kgsl_gmu.h +3 −0 Original line number Diff line number Diff line Loading @@ -212,6 +212,7 @@ enum gpu_idle_level { * @ccl: CNOC BW scaling client * @idle_level: Minimal GPU idle power level * @fault_count: GMU fault count * @unrecovered: Indicates whether GMU recovery failed or not */ struct gmu_device { unsigned int ver; Loading Loading @@ -246,6 +247,7 @@ struct gmu_device { unsigned int ccl; unsigned int idle_level; unsigned int fault_count; bool unrecovered; }; void gmu_snapshot(struct kgsl_device *device); Loading @@ -255,6 +257,7 @@ void gmu_remove(struct kgsl_device *device); int allocate_gmu_image(struct gmu_device *gmu, unsigned int size); int gmu_start(struct kgsl_device *device); void gmu_stop(struct kgsl_device *device); int gmu_suspend(struct kgsl_device *device); int gmu_dcvs_set(struct gmu_device *gmu, unsigned int gpu_pwrlevel, unsigned int bus_level); #endif /* __KGSL_GMU_H */
drivers/gpu/msm/kgsl_pwrctrl.c +19 −0 Original line number Diff line number Diff line Loading @@ -2798,6 +2798,25 @@ _aware(struct kgsl_device *device) WARN_ONCE(1, "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. */ gmu_suspend(device); gmu->unrecovered = true; kgsl_pwrctrl_set_state(device, state); } else { if (device->snapshot) Loading