Loading drivers/gpu/msm/adreno_a6xx.c +8 −22 Original line number Diff line number Diff line Loading @@ -1128,8 +1128,7 @@ static int64_t a6xx_read_throttling_counters(struct adreno_device *adreno_dev) static int a6xx_reset(struct kgsl_device *device, int fault) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); int ret = -EINVAL; int i = 0; int ret; /* Use the regular reset sequence for No GMU */ if (!gmu_core_isenabled(device)) Loading @@ -1141,33 +1140,20 @@ static int a6xx_reset(struct kgsl_device *device, int fault) /* since device is officially off now clear start bit */ clear_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv); /* Keep trying to start the device until it works */ for (i = 0; i < NUM_TIMES_RESET_RETRY; i++) { ret = adreno_start(device, 0); if (!ret) break; msleep(20); } if (ret) return ret; if (i != 0) dev_warn(device->dev, "Device hard reset tried %d tries\n", i); kgsl_pwrctrl_change_state(device, KGSL_STATE_ACTIVE); /* * If active_cnt is non-zero then the system was active before * going into a reset - put it back in that state * If active_cnt is zero, there is no need to keep the GPU active. So, * we should transition to SLUMBER. */ if (!atomic_read(&device->active_cnt)) kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER); if (atomic_read(&device->active_cnt)) kgsl_pwrctrl_change_state(device, KGSL_STATE_ACTIVE); else kgsl_pwrctrl_change_state(device, KGSL_STATE_NAP); return ret; return 0; } static void a6xx_cp_hw_err_callback(struct adreno_device *adreno_dev, int bit) Loading drivers/gpu/msm/kgsl_gmu.c +3 −0 Original line number Diff line number Diff line Loading @@ -1542,6 +1542,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; } Loading drivers/gpu/msm/kgsl_pwrctrl.c +32 −61 Original line number Diff line number Diff line Loading @@ -2635,12 +2635,22 @@ static int _init(struct kgsl_device *device) int status = 0; switch (device->state) { case KGSL_STATE_RESET: if (gmu_core_isenabled(device)) { /* * If we fail a INIT -> AWARE transition, we will * transition back to INIT. However, we must hard reset * the GMU as we go back to INIT. This is done by * forcing a RESET -> INIT transition. */ gmu_core_suspend(device); kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT); } break; case KGSL_STATE_NAP: /* Force power on to do the stop */ status = kgsl_pwrctrl_enable(device); case KGSL_STATE_ACTIVE: /* fall through */ case KGSL_STATE_RESET: kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF); del_timer_sync(&device->idle_timer); kgsl_pwrscale_midframe_timer_cancel(device); Loading Loading @@ -2747,7 +2757,6 @@ static int _aware(struct kgsl_device *device) { int status = 0; unsigned int state = device->state; switch (device->state) { case KGSL_STATE_RESET: Loading @@ -2757,12 +2766,6 @@ _aware(struct kgsl_device *device) status = gmu_core_start(device); break; case KGSL_STATE_INIT: /* 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); break; /* The following 3 cases shouldn't occur, but don't panic. */ Loading @@ -2774,65 +2777,26 @@ _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); 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; if (status && gmu_core_isenabled(device)) /* * 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. * If a SLUMBER/INIT -> AWARE fails, we transition back to * SLUMBER/INIT state. We must hard reset the GMU while * transitioning back to SLUMBER/INIT. A RESET -> AWARE * transition is different. It happens when dispatcher is * attempting reset/recovery as part of fault handling. If it * fails, we should still transition back to RESET in case * we want to attempt another reset/recovery. */ 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 { kgsl_pwrctrl_set_state(device, KGSL_STATE_RESET); else kgsl_pwrctrl_set_state(device, KGSL_STATE_AWARE); } return status; } Loading Loading @@ -2921,6 +2885,13 @@ _slumber(struct kgsl_device *device) trace_gpu_frequency(0, 0); 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; Loading Loading
drivers/gpu/msm/adreno_a6xx.c +8 −22 Original line number Diff line number Diff line Loading @@ -1128,8 +1128,7 @@ static int64_t a6xx_read_throttling_counters(struct adreno_device *adreno_dev) static int a6xx_reset(struct kgsl_device *device, int fault) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); int ret = -EINVAL; int i = 0; int ret; /* Use the regular reset sequence for No GMU */ if (!gmu_core_isenabled(device)) Loading @@ -1141,33 +1140,20 @@ static int a6xx_reset(struct kgsl_device *device, int fault) /* since device is officially off now clear start bit */ clear_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv); /* Keep trying to start the device until it works */ for (i = 0; i < NUM_TIMES_RESET_RETRY; i++) { ret = adreno_start(device, 0); if (!ret) break; msleep(20); } if (ret) return ret; if (i != 0) dev_warn(device->dev, "Device hard reset tried %d tries\n", i); kgsl_pwrctrl_change_state(device, KGSL_STATE_ACTIVE); /* * If active_cnt is non-zero then the system was active before * going into a reset - put it back in that state * If active_cnt is zero, there is no need to keep the GPU active. So, * we should transition to SLUMBER. */ if (!atomic_read(&device->active_cnt)) kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER); if (atomic_read(&device->active_cnt)) kgsl_pwrctrl_change_state(device, KGSL_STATE_ACTIVE); else kgsl_pwrctrl_change_state(device, KGSL_STATE_NAP); return ret; return 0; } static void a6xx_cp_hw_err_callback(struct adreno_device *adreno_dev, int bit) Loading
drivers/gpu/msm/kgsl_gmu.c +3 −0 Original line number Diff line number Diff line Loading @@ -1542,6 +1542,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; } Loading
drivers/gpu/msm/kgsl_pwrctrl.c +32 −61 Original line number Diff line number Diff line Loading @@ -2635,12 +2635,22 @@ static int _init(struct kgsl_device *device) int status = 0; switch (device->state) { case KGSL_STATE_RESET: if (gmu_core_isenabled(device)) { /* * If we fail a INIT -> AWARE transition, we will * transition back to INIT. However, we must hard reset * the GMU as we go back to INIT. This is done by * forcing a RESET -> INIT transition. */ gmu_core_suspend(device); kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT); } break; case KGSL_STATE_NAP: /* Force power on to do the stop */ status = kgsl_pwrctrl_enable(device); case KGSL_STATE_ACTIVE: /* fall through */ case KGSL_STATE_RESET: kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF); del_timer_sync(&device->idle_timer); kgsl_pwrscale_midframe_timer_cancel(device); Loading Loading @@ -2747,7 +2757,6 @@ static int _aware(struct kgsl_device *device) { int status = 0; unsigned int state = device->state; switch (device->state) { case KGSL_STATE_RESET: Loading @@ -2757,12 +2766,6 @@ _aware(struct kgsl_device *device) status = gmu_core_start(device); break; case KGSL_STATE_INIT: /* 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); break; /* The following 3 cases shouldn't occur, but don't panic. */ Loading @@ -2774,65 +2777,26 @@ _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); 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; if (status && gmu_core_isenabled(device)) /* * 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. * If a SLUMBER/INIT -> AWARE fails, we transition back to * SLUMBER/INIT state. We must hard reset the GMU while * transitioning back to SLUMBER/INIT. A RESET -> AWARE * transition is different. It happens when dispatcher is * attempting reset/recovery as part of fault handling. If it * fails, we should still transition back to RESET in case * we want to attempt another reset/recovery. */ 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 { kgsl_pwrctrl_set_state(device, KGSL_STATE_RESET); else kgsl_pwrctrl_set_state(device, KGSL_STATE_AWARE); } return status; } Loading Loading @@ -2921,6 +2885,13 @@ _slumber(struct kgsl_device *device) trace_gpu_frequency(0, 0); 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; Loading