diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 6aa084f9b1da..2497907a7fd8 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -2573,6 +2573,27 @@ int adreno_set_constraint(struct kgsl_device *device, return status; } +static void adreno_force_on(struct adreno_device *adreno_dev) +{ + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); + + if (gmu_core_isenabled(device)) { + + set_bit(GMU_DISABLE_SLUMBER, &device->gmu_core.flags); + + if (!adreno_active_count_get(adreno_dev)) + adreno_active_count_put(adreno_dev); + + return; + } + + kgsl_pwrctrl_change_state(device, KGSL_STATE_ACTIVE); + + device->pwrctrl.ctrl_flags = KGSL_PWR_ON; + + adreno_fault_detect_stop(adreno_dev); +} + static int adreno_setproperty(struct kgsl_device_private *dev_priv, unsigned int type, void __user *value, @@ -2597,7 +2618,11 @@ static int adreno_setproperty(struct kgsl_device_private *dev_priv, mutex_lock(&device->mutex); if (enable) { - device->pwrctrl.ctrl_flags = 0; + if (gmu_core_isenabled(device)) + clear_bit(GMU_DISABLE_SLUMBER, + &device->gmu_core.flags); + else + device->pwrctrl.ctrl_flags = 0; if (!adreno_active_count_get(adreno_dev)) { adreno_fault_detect_start(adreno_dev); @@ -2606,10 +2631,7 @@ static int adreno_setproperty(struct kgsl_device_private *dev_priv, kgsl_pwrscale_enable(device); } else { - kgsl_pwrctrl_change_state(device, - KGSL_STATE_ACTIVE); - device->pwrctrl.ctrl_flags = KGSL_PWR_ON; - adreno_fault_detect_stop(adreno_dev); + adreno_force_on(adreno_dev); kgsl_pwrscale_disable(device, true); } diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index e7b2f5124748..92bda0fbac27 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -2821,25 +2821,21 @@ error: void a6xx_enable_gpu_irq(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); - struct kgsl_pwrctrl *pwr = &device->pwrctrl; + + kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON); adreno_irqctrl(adreno_dev, 1); - enable_irq(pwr->interrupt_num); - - trace_kgsl_irq(device, 1); } void a6xx_disable_gpu_irq(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); - struct kgsl_pwrctrl *pwr = &device->pwrctrl; - disable_irq(pwr->interrupt_num); + kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF); if (a6xx_gmu_gx_is_on(device)) adreno_irqctrl(adreno_dev, 0); - trace_kgsl_irq(device, 0); } static int a6xx_gpu_boot(struct adreno_device *adreno_dev) @@ -3112,14 +3108,19 @@ static void gmu_idle_check(struct work_struct *work) mutex_lock(&device->mutex); + if (test_bit(GMU_DISABLE_SLUMBER, &device->gmu_core.flags)) + goto done; + if (!atomic_read(&device->active_cnt)) { if (test_bit(GMU_PRIV_GPU_STARTED, &gmu->flags)) a6xx_power_off(adreno_dev); } else { + kgsl_pwrscale_update(device); mod_timer(&device->idle_timer, jiffies + device->pwrctrl.interval_timeout); } +done: mutex_unlock(&device->mutex); } diff --git a/drivers/gpu/msm/adreno_a6xx_rgmu.c b/drivers/gpu/msm/adreno_a6xx_rgmu.c index 2e086d3bd3d0..55f1ac8d9c3e 100644 --- a/drivers/gpu/msm/adreno_a6xx_rgmu.c +++ b/drivers/gpu/msm/adreno_a6xx_rgmu.c @@ -849,12 +849,18 @@ static void rgmu_idle_check(struct work_struct *work) mutex_lock(&device->mutex); - if (!atomic_read(&device->active_cnt)) + if (test_bit(GMU_DISABLE_SLUMBER, &device->gmu_core.flags)) + goto done; + + if (!atomic_read(&device->active_cnt)) { a6xx_power_off(adreno_dev); - else + } else { + kgsl_pwrscale_update(device); mod_timer(&device->idle_timer, jiffies + device->pwrctrl.interval_timeout); + } +done: mutex_unlock(&device->mutex); } diff --git a/drivers/gpu/msm/kgsl_gmu_core.h b/drivers/gpu/msm/kgsl_gmu_core.h index dd2685c6f1a5..e955d475cc90 100644 --- a/drivers/gpu/msm/kgsl_gmu_core.h +++ b/drivers/gpu/msm/kgsl_gmu_core.h @@ -39,6 +39,7 @@ enum gmu_core_flags { GMU_DCVS_REPLAY, GMU_ENABLED, GMU_RSCC_SLEEP_SEQ_DONE, + GMU_DISABLE_SLUMBER, }; /* diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index aa12bafebc0a..71619ddcfd6b 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -649,7 +649,12 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, * The device mutex must be held to change power state */ mutex_lock(&device->mutex); - kgsl_pwrctrl_change_state(device, KGSL_STATE_AWARE); + + if (gmu_core_isenabled(device)) + kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF); + else + kgsl_pwrctrl_change_state(device, KGSL_STATE_AWARE); + mutex_unlock(&device->mutex); } diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index 504cde5aea09..e07c165a3fb1 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -1330,7 +1330,7 @@ static int kgsl_pwrctrl_pwrrail(struct kgsl_device *device, int state) return status; } -static void kgsl_pwrctrl_irq(struct kgsl_device *device, int state) +void kgsl_pwrctrl_irq(struct kgsl_device *device, int state) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h index 483ab3464576..eeae3cec3568 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.h +++ b/drivers/gpu/msm/kgsl_pwrctrl.h @@ -228,4 +228,12 @@ int kgsl_pwrctrl_axi(struct kgsl_device *device, int state); * off state if the active_cnt is 0 and the hardware is idle. */ void kgsl_idle_check(struct work_struct *work); + +/** + * kgsl_pwrctrl_irq - Enable or disable gpu interrupts + * @device: Handle to the kgsl device + * @state: Variable to decide whether interrupts need to be enabled or disabled + * + */ +void kgsl_pwrctrl_irq(struct kgsl_device *device, int state); #endif /* __KGSL_PWRCTRL_H */