summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkhil P Oommen <quic_akhilpo@quicinc.com>2022-06-16 19:43:48 +0530
committerGerrit - the friendly Code Review server <code-review@localhost>2023-02-26 22:31:35 -0800
commitcace9002d5801252dcd456257f4a1395efb83c7b (patch)
treea364d305869bcc41fa5057129b5e2c6e2a3ab61c
parent23fb0f089b60ff8564f7aff5cf5285e4c265769d (diff)
downloadgraphics-cace9002d5801252dcd456257f4a1395efb83c7b.tar.gz
msm: kgsl: Refactor bus hint/mod
Currently, we generate bus modifier hint (to update bus level) in gpubw governor to identify the bus modifier value. Also, we leak "wait_active_percent" stat from gpubw governor to kgsl_bus.c to again update the bus level, something which a bus hint could have done. To make it cleaner, we can keep the entire logic of bus hint generation logic within the gpubw governor and pass a new hint to increase the buslevel twice. And refactor the bus hint generation logic in gpubw governer to make it a little bit more readable. Change-Id: Id996c31f20efd6735b7f79da642bd3db1aa3184e Signed-off-by: Akhil P Oommen <quic_akhilpo@quicinc.com>
-rw-r--r--governor_gpubw_mon.c97
-rw-r--r--kgsl_bus.c11
-rw-r--r--kgsl_pwrctrl.c1
-rw-r--r--kgsl_pwrctrl.h1
-rw-r--r--kgsl_pwrscale.c24
-rw-r--r--msm_adreno_devfreq.h7
6 files changed, 71 insertions, 70 deletions
diff --git a/governor_gpubw_mon.c b/governor_gpubw_mon.c
index a512f97..87797d5 100644
--- a/governor_gpubw_mon.c
+++ b/governor_gpubw_mon.c
@@ -86,6 +86,57 @@ static const struct device_attribute *gpubw_attr_list[] = {
NULL
};
+static u32 generate_hint(struct devfreq_msm_adreno_tz_data *priv, int buslevel,
+ unsigned long freq, unsigned long minfreq)
+{
+ int act_level;
+ int norm_max_cycles;
+ int norm_cycles;
+ int wait_active_percent;
+ int gpu_percent;
+
+ norm_max_cycles = (unsigned int)(priv->bus.ram_time) /
+ (unsigned int) priv->bus.total_time;
+ norm_cycles = (unsigned int)(priv->bus.ram_time + priv->bus.ram_wait) /
+ (unsigned int) priv->bus.total_time;
+ wait_active_percent = (100 * (unsigned int)priv->bus.ram_wait) /
+ (unsigned int) priv->bus.ram_time;
+ gpu_percent = (100 * (unsigned int)priv->bus.gpu_time) /
+ (unsigned int) priv->bus.total_time;
+
+ /*
+ * If there's a new high watermark, update the cutoffs and send the
+ * FAST hint, provided that we are using a floating watermark.
+ * Otherwise check the current value against the current
+ * cutoffs.
+ */
+ if (norm_max_cycles > priv->bus.max && priv->bus.floating) {
+ _update_cutoff(priv, norm_max_cycles);
+ return BUSMON_FLAG_FAST_HINT;
+ }
+
+ if (minfreq == freq && wait_active_percent > 95)
+ return BUSMON_FLAG_SUPER_FAST_HINT;
+
+ if (minfreq == freq && wait_active_percent > 80)
+ return BUSMON_FLAG_FAST_HINT;
+
+ /* GPU votes for IB not AB so don't under vote the system */
+ norm_cycles = (100 * norm_cycles) / TARGET;
+ act_level = max_t(int, buslevel, 0);
+ act_level = min_t(int, act_level, priv->bus.num - 1);
+
+ if ((norm_cycles > priv->bus.up[act_level] ||
+ wait_active_percent > WAIT_THRESHOLD) &&
+ gpu_percent > CAP)
+ return BUSMON_FLAG_FAST_HINT;
+
+ if (norm_cycles < priv->bus.down[act_level] && buslevel)
+ return BUSMON_FLAG_SLOW_HINT;
+
+ return 0;
+}
+
static int devfreq_gpubw_get_target(struct devfreq *df,
unsigned long *freq)
{
@@ -98,18 +149,13 @@ static int devfreq_gpubw_get_target(struct devfreq *df,
struct devfreq_dev_status *stats = &df->last_status;
struct xstats b = {0};
int result;
- int act_level;
- int norm_max_cycles;
- int norm_cycles;
- int wait_active_percent;
- int gpu_percent;
+ int norm_ab;
+ unsigned long ab_mbytes = 0;
/*
* Normalized AB should at max usage be the gpu_bimc frequency in MHz.
* Start with a reasonable value and let the system push it up to max.
*/
static int norm_ab_max = 300;
- int norm_ab;
- unsigned long ab_mbytes = 0;
if (priv == NULL)
return 0;
@@ -131,41 +177,8 @@ static int devfreq_gpubw_get_target(struct devfreq *df,
if (priv->bus.total_time < bus_profile->sampling_ms)
return result;
- norm_max_cycles = (unsigned int)(priv->bus.ram_time) /
- (unsigned int) priv->bus.total_time;
- norm_cycles = (unsigned int)(priv->bus.ram_time + priv->bus.ram_wait) /
- (unsigned int) priv->bus.total_time;
- wait_active_percent = (100 * (unsigned int)priv->bus.ram_wait) /
- (unsigned int) priv->bus.ram_time;
- gpu_percent = (100 * (unsigned int)priv->bus.gpu_time) /
- (unsigned int) priv->bus.total_time;
-
- /*
- * If there's a new high watermark, update the cutoffs and send the
- * FAST hint, provided that we are using a floating watermark.
- * Otherwise check the current value against the current
- * cutoffs.
- */
- if (norm_max_cycles > priv->bus.max && priv->bus.floating) {
- _update_cutoff(priv, norm_max_cycles);
- bus_profile->flag = DEVFREQ_FLAG_FAST_HINT;
- } else {
- /* GPU votes for IB not AB so don't under vote the system */
- norm_cycles = (100 * norm_cycles) / TARGET;
- act_level = b.buslevel;
- act_level = (act_level < 0) ? 0 : act_level;
- act_level = (act_level >= priv->bus.num) ?
- (priv->bus.num - 1) : act_level;
- if (((norm_cycles > priv->bus.up[act_level] ||
- wait_active_percent > WAIT_THRESHOLD) &&
- gpu_percent > CAP) || (b.gpu_minfreq == *freq
- && wait_active_percent > 80))
- bus_profile->flag = DEVFREQ_FLAG_FAST_HINT;
- else if (norm_cycles < priv->bus.down[act_level] && b.buslevel)
- bus_profile->flag = DEVFREQ_FLAG_SLOW_HINT;
- }
-
- bus_profile->wait_active_percent = wait_active_percent;
+ bus_profile->flag = generate_hint(priv, b.buslevel, *freq,
+ b.gpu_minfreq);
/* Calculate the AB vote based on bus width if defined */
if (priv->bus.width) {
diff --git a/kgsl_bus.c b/kgsl_bus.c
index 6a149a5..0842c83 100644
--- a/kgsl_bus.c
+++ b/kgsl_bus.c
@@ -38,7 +38,6 @@ int kgsl_bus_update(struct kgsl_device *device,
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
/* FIXME: this might be wrong? */
int cur = pwr->pwrlevels[pwr->active_pwrlevel].bus_freq;
- int cur_max = pwr->pwrlevels[pwr->active_pwrlevel].bus_max;
int buslevel = 0;
u32 ab;
@@ -54,27 +53,17 @@ int kgsl_bus_update(struct kgsl_device *device,
buslevel = min_t(int, pwr->pwrlevels[0].bus_max,
cur + pwr->bus_mod);
buslevel = max_t(int, buslevel, 1);
-
- /*
- * larger % of stalls we consider increasing the bus vote by
- * more than 1 level.
- */
- if ((pwr->active_pwrlevel == pwr->min_pwrlevel) &&
- pwr->ddr_stall_percent >= 95)
- buslevel = min_t(int, buslevel + 1, cur_max);
} else if (vote_state == KGSL_BUS_VOTE_MINIMUM) {
/* Request bus level 1, minimum non-zero value */
buslevel = 1;
pwr->bus_mod = 0;
pwr->bus_percent_ab = 0;
pwr->bus_ab_mbytes = 0;
- pwr->ddr_stall_percent = 0;
} else if (vote_state == KGSL_BUS_VOTE_OFF) {
/* If the bus is being turned off, reset to default level */
pwr->bus_mod = 0;
pwr->bus_percent_ab = 0;
pwr->bus_ab_mbytes = 0;
- pwr->ddr_stall_percent = 0;
}
/* buslevel is the IB vote, update the AB */
diff --git a/kgsl_pwrctrl.c b/kgsl_pwrctrl.c
index f4e23d2..cf7504f 100644
--- a/kgsl_pwrctrl.c
+++ b/kgsl_pwrctrl.c
@@ -230,7 +230,6 @@ void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device,
if (pwr->bus_mod < 0 || new_level < old_level) {
pwr->bus_mod = 0;
pwr->bus_percent_ab = 0;
- pwr->ddr_stall_percent = 0;
}
/*
* Update the bus before the GPU clock to prevent underrun during
diff --git a/kgsl_pwrctrl.h b/kgsl_pwrctrl.h
index e5f1e90..2331de5 100644
--- a/kgsl_pwrctrl.h
+++ b/kgsl_pwrctrl.h
@@ -139,7 +139,6 @@ struct kgsl_pwrctrl {
unsigned int bus_percent_ab;
unsigned int bus_width;
unsigned long bus_ab_mbytes;
- u32 ddr_stall_percent;
/** @ddr_table: List of the DDR bandwidths in KBps for the target */
u32 *ddr_table;
/** @ddr_table_count: Number of objects in @ddr_table */
diff --git a/kgsl_pwrscale.c b/kgsl_pwrscale.c
index 7b0f0e5..97ef8d1 100644
--- a/kgsl_pwrscale.c
+++ b/kgsl_pwrscale.c
@@ -415,14 +415,18 @@ int kgsl_busmon_get_dev_status(struct device *dev,
return 0;
}
-static inline bool _check_fast_hint(u32 flags)
+static int _read_hint(u32 flags)
{
- return (flags & DEVFREQ_FLAG_FAST_HINT);
-}
-
-static inline bool _check_slow_hint(u32 flags)
-{
- return (flags & DEVFREQ_FLAG_SLOW_HINT);
+ switch (flags) {
+ case BUSMON_FLAG_FAST_HINT:
+ return 1;
+ case BUSMON_FLAG_SUPER_FAST_HINT:
+ return 2;
+ case BUSMON_FLAG_SLOW_HINT:
+ return -1;
+ default:
+ return 0;
+ }
}
/*
@@ -475,10 +479,7 @@ int kgsl_busmon_target(struct device *dev, unsigned long *freq, u32 flags)
}
b = pwr->bus_mod;
- if (_check_fast_hint(bus_flag))
- pwr->bus_mod++;
- else if (_check_slow_hint(bus_flag))
- pwr->bus_mod--;
+ pwr->bus_mod += _read_hint(bus_flag);
/* trim calculated change to fit range */
if (pwr_level->bus_freq + pwr->bus_mod < pwr_level->bus_min)
@@ -489,7 +490,6 @@ int kgsl_busmon_target(struct device *dev, unsigned long *freq, u32 flags)
/* Update bus vote if AB or IB is modified */
if ((pwr->bus_mod != b) || (pwr->bus_ab_mbytes != ab_mbytes)) {
pwr->bus_percent_ab = device->pwrscale.bus_profile.percent_ab;
- pwr->ddr_stall_percent = device->pwrscale.bus_profile.wait_active_percent;
/*
* When gpu is thermally throttled to its lowest power level,
* drop GPU's AB vote as a last resort to lower CX voltage and
diff --git a/msm_adreno_devfreq.h b/msm_adreno_devfreq.h
index c936435..b6c1316 100644
--- a/msm_adreno_devfreq.h
+++ b/msm_adreno_devfreq.h
@@ -10,8 +10,10 @@
#include <linux/devfreq.h>
#include <linux/notifier.h>
-#define DEVFREQ_FLAG_FAST_HINT 0x1
-#define DEVFREQ_FLAG_SLOW_HINT 0x2
+/* Flags used to send bus modifier hint from busmon governer to driver */
+#define BUSMON_FLAG_FAST_HINT BIT(0)
+#define BUSMON_FLAG_SUPER_FAST_HINT BIT(1)
+#define BUSMON_FLAG_SLOW_HINT BIT(2)
struct device;
@@ -66,7 +68,6 @@ struct msm_busmon_extended_profile {
u32 sampling_ms;
unsigned long percent_ab;
unsigned long ab_mbytes;
- u32 wait_active_percent;
struct devfreq_msm_adreno_tz_data *private_data;
struct devfreq_dev_profile profile;
};