diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index c29293a5d840..510012f5c8aa 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -3505,7 +3505,7 @@ static int adreno_regulator_enable(struct kgsl_device *device) return ret; } -static bool adreno_is_hw_collapsible(struct kgsl_device *device) +static bool adreno_prepare_for_power_off(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); const struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); @@ -3519,8 +3519,16 @@ static bool adreno_is_hw_collapsible(struct kgsl_device *device) device->pwrctrl.ctrl_flags) return false; - return adreno_isidle(adreno_dev) && (gpudev->is_sptp_idle ? - gpudev->is_sptp_idle(adreno_dev) : true); + if (!adreno_isidle(adreno_dev) || !(gpudev->is_sptp_idle ? + gpudev->is_sptp_idle(adreno_dev) : true)) + return false; + + if (gpudev->clear_pending_transactions(adreno_dev)) + return false; + + adreno_dispatcher_stop_fault_timer(device); + + return true; } static void adreno_regulator_disable(struct kgsl_device *device) @@ -3727,6 +3735,15 @@ static int adreno_gpu_bus_set(struct kgsl_device *device, int level, u32 ab) return adreno_interconnect_bus_set(adreno_dev, level, ab); } +static void adreno_deassert_gbif_halt(struct kgsl_device *device) +{ + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + const struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); + + if (gpudev->deassert_gbif_halt) + gpudev->deassert_gbif_halt(adreno_dev); +} + static const struct kgsl_functable adreno_functable = { /* Mandatory functions */ .regread = adreno_regread, @@ -3761,17 +3778,17 @@ static const struct kgsl_functable adreno_functable = { .drawctxt_sched = adreno_drawctxt_sched, .resume = adreno_dispatcher_start, .regulator_enable = adreno_regulator_enable, - .is_hw_collapsible = adreno_is_hw_collapsible, + .prepare_for_power_off = adreno_prepare_for_power_off, .regulator_disable = adreno_regulator_disable, .pwrlevel_change_settings = adreno_pwrlevel_change_settings, .regulator_disable_poll = adreno_regulator_disable_poll, .clk_set_options = adreno_clk_set_options, .gpu_model = adreno_gpu_model, - .stop_fault_timer = adreno_dispatcher_stop_fault_timer, .query_property_list = adreno_query_property_list, .is_hwcg_on = adreno_is_hwcg_on, .gpu_clock_set = adreno_gpu_clock_set, .gpu_bus_set = adreno_gpu_bus_set, + .deassert_gbif_halt = adreno_deassert_gbif_halt, }; static const struct component_master_ops adreno_ops = { diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 22874c25f99c..fbf8a12ff56d 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -811,6 +811,7 @@ struct adreno_gpudev { */ const struct adreno_power_ops *power_ops; int (*clear_pending_transactions)(struct adreno_device *adreno_dev); + void (*deassert_gbif_halt)(struct adreno_device *adreno_dev); }; /** @@ -1735,8 +1736,6 @@ static inline u32 adreno_get_level(u32 priority) int adreno_gmu_fenced_write(struct adreno_device *adreno_dev, enum adreno_regs offset, unsigned int val, unsigned int fence_mask); -int adreno_clear_pending_transactions(struct kgsl_device *device); - /** * adreno_get_firwmare - Load firmware into a adreno_firmware struct diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index 4f950a8fd498..fb4497cfc82d 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -2509,6 +2509,7 @@ const struct adreno_gpudev adreno_a6xx_gpudev = { .read_alwayson = a6xx_read_alwayson, .power_ops = &adreno_power_operations, .clear_pending_transactions = a6xx_clear_pending_transactions, + .deassert_gbif_halt = a6xx_deassert_gbif_halt, }; const struct adreno_gpudev adreno_a6xx_hwsched_gpudev = { @@ -2622,6 +2623,7 @@ const struct adreno_gpudev adreno_a619_holi_gpudev = { .read_alwayson = a6xx_read_alwayson, .power_ops = &adreno_power_operations, .clear_pending_transactions = a6xx_clear_pending_transactions, + .deassert_gbif_halt = a6xx_deassert_gbif_halt, }; const struct adreno_gpudev adreno_a630_gpudev = { diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index c68d4cac981f..544cabeb3890 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -148,7 +148,7 @@ struct kgsl_functable { struct kgsl_context *context); void (*resume)(struct kgsl_device *device); int (*regulator_enable)(struct kgsl_device *device); - bool (*is_hw_collapsible)(struct kgsl_device *device); + bool (*prepare_for_power_off)(struct kgsl_device *device); void (*regulator_disable)(struct kgsl_device *device); void (*pwrlevel_change_settings)(struct kgsl_device *device, unsigned int prelevel, unsigned int postlevel, bool post); @@ -157,7 +157,6 @@ struct kgsl_functable { const char *name, struct clk *clk, bool on); void (*gpu_model)(struct kgsl_device *device, char *str, size_t bufsz); - void (*stop_fault_timer)(struct kgsl_device *device); /** * @query_property_list: query the list of properties * supported by the device. If 'list' is NULL just return the total @@ -171,6 +170,7 @@ struct kgsl_functable { int (*gpu_clock_set)(struct kgsl_device *device, u32 pwrlevel); /** @gpu_bus_set: Target specific function to set gpu bandwidth */ int (*gpu_bus_set)(struct kgsl_device *device, int bus_level, u32 ab); + void (*deassert_gbif_halt)(struct kgsl_device *device); }; struct kgsl_ioctl { diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index 88ac2285245e..28aba03c96af 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -1859,6 +1859,7 @@ static int _wake(struct kgsl_device *device) /* Turn on the core clocks */ kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON, KGSL_STATE_ACTIVE); + device->ftbl->deassert_gbif_halt(device); /* * No need to turn on/off irq here as it no longer affects * power collapse @@ -1943,12 +1944,11 @@ _nap(struct kgsl_device *device) { switch (device->state) { case KGSL_STATE_ACTIVE: - if (!device->ftbl->is_hw_collapsible(device)) { + if (!device->ftbl->prepare_for_power_off(device)) { kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE); return -EBUSY; } - device->ftbl->stop_fault_timer(device); kgsl_pwrscale_midframe_timer_cancel(device); /* @@ -2006,7 +2006,7 @@ _slumber(struct kgsl_device *device) switch (device->state) { case KGSL_STATE_ACTIVE: - if (!device->ftbl->is_hw_collapsible(device)) { + if (!device->ftbl->prepare_for_power_off(device)) { kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE); return -EBUSY; }