diff options
author | Akhil P Oommen <quic_akhilpo@quicinc.com> | 2022-06-16 19:43:48 +0530 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2023-02-26 22:31:35 -0800 |
commit | cace9002d5801252dcd456257f4a1395efb83c7b (patch) | |
tree | a364d305869bcc41fa5057129b5e2c6e2a3ab61c | |
parent | 23fb0f089b60ff8564f7aff5cf5285e4c265769d (diff) | |
download | graphics-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.c | 97 | ||||
-rw-r--r-- | kgsl_bus.c | 11 | ||||
-rw-r--r-- | kgsl_pwrctrl.c | 1 | ||||
-rw-r--r-- | kgsl_pwrctrl.h | 1 | ||||
-rw-r--r-- | kgsl_pwrscale.c | 24 | ||||
-rw-r--r-- | msm_adreno_devfreq.h | 7 |
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) { @@ -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; }; |