msm: kgsl: Process all idle checks
Rather than ignore some categories of idle events,
bin the events with small timelines and process all
events with the GPU DCVS algorithm.
CRs-Fixed: 427559
Signed-off-by: Lucille Sylvester <lsylvest@codeaurora.org>
Change-Id: I1a5e8d8af6020a08cf95a9daa934e825bc5f2854
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 8ebca50..8b43024 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -475,7 +475,7 @@
device->state == KGSL_STATE_ACTIVE &&
device->requested_state == KGSL_STATE_NONE) {
kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP);
- kgsl_pwrscale_idle(device, 1);
+ kgsl_pwrscale_idle(device);
if (kgsl_pwrctrl_sleep(device) != 0)
mod_timer(&device->idle_timer,
jiffies +
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 54eae2b..1eb12a0 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1008,7 +1008,7 @@
mutex_lock(&device->mutex);
if (device->state & (KGSL_STATE_ACTIVE | KGSL_STATE_NAP)) {
- kgsl_pwrscale_idle(device, 0);
+ kgsl_pwrscale_idle(device);
if (kgsl_pwrctrl_sleep(device) != 0) {
mod_timer(&device->idle_timer,
diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c
index aad1a8d..d46f552 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.c
+++ b/drivers/gpu/msm/kgsl_pwrscale.c
@@ -242,13 +242,13 @@
&device->pwrscale);
}
-void kgsl_pwrscale_idle(struct kgsl_device *device, unsigned int ignore_idle)
+void kgsl_pwrscale_idle(struct kgsl_device *device)
{
if (PWRSCALE_ACTIVE(device) && device->pwrscale.policy->idle)
if (device->requested_state != KGSL_STATE_SLUMBER &&
device->requested_state != KGSL_STATE_SLEEP)
device->pwrscale.policy->idle(device,
- &device->pwrscale, ignore_idle);
+ &device->pwrscale);
}
EXPORT_SYMBOL(kgsl_pwrscale_idle);
diff --git a/drivers/gpu/msm/kgsl_pwrscale.h b/drivers/gpu/msm/kgsl_pwrscale.h
index ba9b1af..85d5b82 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.h
+++ b/drivers/gpu/msm/kgsl_pwrscale.h
@@ -23,8 +23,7 @@
void (*close)(struct kgsl_device *device,
struct kgsl_pwrscale *pwrscale);
void (*idle)(struct kgsl_device *device,
- struct kgsl_pwrscale *pwrscale,
- unsigned int ignore_idle);
+ struct kgsl_pwrscale *pwrscale);
void (*busy)(struct kgsl_device *device,
struct kgsl_pwrscale *pwrscale);
void (*sleep)(struct kgsl_device *device,
@@ -64,8 +63,7 @@
struct kgsl_pwrscale_policy *policy);
void kgsl_pwrscale_detach_policy(struct kgsl_device *device);
-void kgsl_pwrscale_idle(struct kgsl_device *device,
- unsigned int ignore_idle);
+void kgsl_pwrscale_idle(struct kgsl_device *device);
void kgsl_pwrscale_busy(struct kgsl_device *device);
void kgsl_pwrscale_sleep(struct kgsl_device *device);
void kgsl_pwrscale_wake(struct kgsl_device *device);
diff --git a/drivers/gpu/msm/kgsl_pwrscale_idlestats.c b/drivers/gpu/msm/kgsl_pwrscale_idlestats.c
index fc58dd1..cd432c6 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_idlestats.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_idlestats.c
@@ -131,7 +131,7 @@
}
static void idlestats_idle(struct kgsl_device *device,
- struct kgsl_pwrscale *pwrscale, unsigned int ignore_idle)
+ struct kgsl_pwrscale *pwrscale)
{
int i, nr_cpu;
struct idlestats_priv *priv = pwrscale->priv;
diff --git a/drivers/gpu/msm/kgsl_pwrscale_msm.c b/drivers/gpu/msm/kgsl_pwrscale_msm.c
index c680d57..073e474 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_msm.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_msm.c
@@ -132,7 +132,7 @@
}
static void msm_idle(struct kgsl_device *device,
- struct kgsl_pwrscale *pwrscale, unsigned int ignore_idle)
+ struct kgsl_pwrscale *pwrscale)
{
struct msm_priv *priv = pwrscale->priv;
diff --git a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
index e01932b..3e81e56 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
@@ -30,9 +30,14 @@
int governor;
unsigned int no_switch_cnt;
unsigned int skip_cnt;
+ struct kgsl_power_stats bin;
};
spinlock_t tz_lock;
+/* FLOOR is 5msec to capture up to 3 re-draws
+ * per frame for 60fps content.
+ */
+#define FLOOR 5000
#define SWITCH_OFF 200
#define SWITCH_OFF_RESET_TH 40
#define SKIP_COUNTER 500
@@ -119,24 +124,27 @@
device->pwrctrl.default_pwrlevel);
}
-static void tz_idle(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale,
- unsigned int ignore_idle)
+static void tz_idle(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale)
{
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
struct tz_priv *priv = pwrscale->priv;
struct kgsl_power_stats stats;
int val, idle;
- if (ignore_idle)
- return;
-
/* In "performance" mode the clock speed always stays
the same */
if (priv->governor == TZ_GOVERNOR_PERFORMANCE)
return;
device->ftbl->power_stats(device, &stats);
- if (stats.total_time == 0)
+ priv->bin.total_time += stats.total_time;
+ priv->bin.busy_time += stats.busy_time;
+ /* Do not waste CPU cycles running this algorithm if
+ * the GPU just started, or if less than FLOOR time
+ * has passed since the last run.
+ */
+ if ((stats.total_time == 0) ||
+ (priv->bin.total_time < FLOOR))
return;
/* If the GPU has stayed in turbo mode for a while, *
@@ -155,7 +163,9 @@
priv->no_switch_cnt = 0;
}
- idle = stats.total_time - stats.busy_time;
+ idle = priv->bin.total_time - priv->bin.busy_time;
+ priv->bin.total_time = 0;
+ priv->bin.busy_time = 0;
idle = (idle > 0) ? idle : 0;
val = __secure_tz_entry(TZ_UPDATE_ID, idle, device->id);
if (val)
@@ -176,6 +186,8 @@
__secure_tz_entry(TZ_RESET_ID, 0, device->id);
priv->no_switch_cnt = 0;
+ priv->bin.total_time = 0;
+ priv->bin.busy_time = 0;
}
#ifdef CONFIG_MSM_SCM