mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 22:40:54 -04:00
msm: kgsl: Halt GBIF before moving to NAP state
It has been observed that without gmu_clk, any active transactions will cause that transaction to be stuck in QSMMU. As of now we don't halt GBIF when moving to NAP state. So there is a possibility of transactions inflight when gmu_clk is gated. This will cause transactions to be stuck in QSMMU forever. This can eventually lead to GPU hang or TLB sync timeout. So halt GBIF before moving to NAP. Change-Id: I13bbe3b21b327d0d5c962bb2133c6d5d0f3a43c3 Signed-off-by: Puranam V G Tejaswi <pvgtejas@codeaurora.org>
This commit is contained in:
parent
8e0b5e5aaa
commit
f021cc3c5d
5 changed files with 30 additions and 12 deletions
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue