Loading arch/arm64/configs/vendor/lito-perf_defconfig +1 −0 Original line number Original line Diff line number Diff line Loading @@ -771,3 +771,4 @@ CONFIG_SLA_ALGO=y CONFIG_RATP=y CONFIG_RATP=y CONFIG_QCOM_QDSS_BRIDGE=y CONFIG_QCOM_QDSS_BRIDGE=y CONFIG_CPUFREQ_BOUNCING=y CONFIG_CPUFREQ_BOUNCING=y CONFIG_OPLUS_FEATURE_SUGOV_TL=y arch/arm64/configs/vendor/lito_defconfig +1 −0 Original line number Original line Diff line number Diff line Loading @@ -835,3 +835,4 @@ CONFIG_SLA=y CONFIG_SLA_ALGO=y CONFIG_SLA_ALGO=y CONFIG_RATP=y CONFIG_RATP=y CONFIG_CPUFREQ_BOUNCING=y CONFIG_CPUFREQ_BOUNCING=y CONFIG_OPLUS_FEATURE_SUGOV_TL=y include/trace/events/power.h +60 −0 Original line number Original line Diff line number Diff line Loading @@ -901,6 +901,66 @@ TRACE_EVENT(memlat_dev_update, __entry->vote) __entry->vote) ); ); #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL TRACE_EVENT(sugov_next_freq_tl, TP_PROTO(unsigned int cpu, unsigned long util, unsigned long max, unsigned int freq, unsigned int laf, unsigned int prev_freq), TP_ARGS(cpu, util, max, freq, laf, prev_freq), TP_STRUCT__entry( __field(unsigned int, cpu) __field(unsigned long, util) __field(unsigned long, max) __field(unsigned int, freq) __field(unsigned int, laf) __field(unsigned int, prev_freq) ), TP_fast_assign( __entry->cpu = cpu; __entry->util = util; __entry->max = max; __entry->freq = freq; __entry->laf = laf; __entry->prev_freq = prev_freq; ), TP_printk("cpu=%u util=%lu max=%lu freq=%u laf=%u, prev_freq=%u", __entry->cpu, __entry->util, __entry->max, __entry->freq, __entry->laf, __entry->prev_freq) ); TRACE_EVENT(choose_freq, TP_PROTO(unsigned int freq, unsigned int prevfreq, unsigned int freqmax, unsigned int freqmin, unsigned int tl, int index), TP_ARGS(freq, prevfreq, freqmax, freqmin, tl, index), TP_STRUCT__entry( __field(unsigned int, freq) __field(unsigned int, prevfreq) __field(unsigned int, freqmax) __field(unsigned int, freqmin) __field(unsigned int, tl) __field(int, index) ), TP_fast_assign( __entry->freq = freq; __entry->prevfreq = prevfreq; __entry->freqmax = freqmax; __entry->freqmin = freqmin; __entry->tl = tl; __entry->index = index; ), TP_printk("freq=%u prevfreq=%u freqmax=%u freqmin=%u tl=%u index=%d", __entry->freq, __entry->prevfreq, __entry->freqmax, __entry->freqmin, __entry->tl, __entry->index) ); #endif #endif /* _TRACE_POWER_H */ #endif /* _TRACE_POWER_H */ /* This part must be outside protection */ /* This part must be outside protection */ Loading kernel/sched/cpufreq_schedutil.c +233 −1 Original line number Original line Diff line number Diff line Loading @@ -26,6 +26,12 @@ #endif #endif #include <linux/oem/cpufreq_bouncing.h> #include <linux/oem/cpufreq_bouncing.h> #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL /* Target load. Lower values result in higher CPU speeds. */ #define DEFAULT_TARGET_LOAD 80 static unsigned int default_target_loads[] = {DEFAULT_TARGET_LOAD}; #endif struct sugov_tunables { struct sugov_tunables { struct gov_attr_set attr_set; struct gov_attr_set attr_set; unsigned int up_rate_limit_us; unsigned int up_rate_limit_us; Loading @@ -34,6 +40,11 @@ struct sugov_tunables { unsigned int hispeed_freq; unsigned int hispeed_freq; unsigned int rtg_boost_freq; unsigned int rtg_boost_freq; bool pl; bool pl; #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL spinlock_t target_loads_lock; unsigned int *target_loads; int ntarget_loads; #endif /* CONFIG_OPLUS_FEATURE_SUGOV_TL */ }; }; struct sugov_policy { struct sugov_policy { Loading Loading @@ -318,6 +329,111 @@ static void sugov_deferred_update(struct sugov_policy *sg_policy, u64 time, } } #define TARGET_LOAD 80 #define TARGET_LOAD 80 #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL static unsigned int freq_to_targetload( struct sugov_tunables *tunables, unsigned int freq) { int i; unsigned int ret; unsigned long flags; spin_lock_irqsave(&tunables->target_loads_lock, flags); for (i = 0; i < tunables->ntarget_loads - 1 && freq >= tunables->target_loads[i+1]; i += 2) ; ret = tunables->target_loads[i]; spin_unlock_irqrestore(&tunables->target_loads_lock, flags); return ret; } static unsigned int choose_freq(struct sugov_policy *sg_policy, unsigned int loadadjfreq) { struct cpufreq_policy *policy = sg_policy->policy; unsigned int freq = policy->cur; unsigned int prevfreq, freqmin, freqmax; unsigned int tl; int index; freqmin = 0; freqmax = UINT_MAX; do { prevfreq = freq; tl = freq_to_targetload(sg_policy->tunables, freq); /* * Find the lowest frequency where the computed load is less * than or equal to the target load. */ index = cpufreq_frequency_table_target(policy, loadadjfreq / tl, CPUFREQ_RELATION_L); freq = policy->freq_table[index].frequency; trace_choose_freq(freq, prevfreq, freqmax, freqmin, tl, index); if (freq > prevfreq) { /* The previous frequency is too low. */ freqmin = prevfreq; if (freq >= freqmax) { /* * Find the highest frequency that is less * than freqmax. */ index = cpufreq_frequency_table_target( policy, freqmax - 1, CPUFREQ_RELATION_H); freq = policy->freq_table[index].frequency; if (freq == freqmin) { /* * The first frequency below freqmax * has already been found to be too * low. freqmax is the lowest speed * we found that is fast enough. */ freq = freqmax; break; } } } else if (freq < prevfreq) { /* The previous frequency is high enough. */ freqmax = prevfreq; if (freq <= freqmin) { /* * Find the lowest frequency that is higher * than freqmin. */ index = cpufreq_frequency_table_target( policy, freqmin + 1, CPUFREQ_RELATION_L); freq = policy->freq_table[index].frequency; /* * If freqmax is the first frequency above * freqmin then we have already found that * this speed is fast enough. */ if (freq == freqmax) break; } } /* If same frequency chosen as previous then done. */ } while (freq != prevfreq); return freq; } #endif /* CONFIG_OPLUS_FEATURE_SUGOV_TL */ /** /** * get_next_freq - Compute a new frequency for a given cpufreq policy. * get_next_freq - Compute a new frequency for a given cpufreq policy. * @sg_policy: schedutil policy object to compute the new frequency for. * @sg_policy: schedutil policy object to compute the new frequency for. Loading Loading @@ -349,8 +465,15 @@ static unsigned int get_next_freq(struct sugov_policy *sg_policy, #ifdef CONFIG_CONTROL_CENTER #ifdef CONFIG_CONTROL_CENTER unsigned int req_freq; unsigned int req_freq; freq = map_util_freq(util, freq, max); #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL unsigned int prev_freq = freq; unsigned int prev_laf = prev_freq * util * 100 / max; freq = choose_freq(sg_policy, prev_laf); trace_sugov_next_freq_tl(policy->cpu, util, max, freq, prev_laf, prev_freq); #else freq = map_util_freq(util, freq, max); #endif if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update) { if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update) { req_freq = sg_policy->next_freq; req_freq = sg_policy->next_freq; goto out; goto out; Loading @@ -364,9 +487,17 @@ static unsigned int get_next_freq(struct sugov_policy *sg_policy, sg_policy->policy->req_freq = req_freq; sg_policy->policy->req_freq = req_freq; trace_sugov_next_freq(policy->cpu, util, max, freq, req_freq); trace_sugov_next_freq(policy->cpu, util, max, freq, req_freq); return req_freq; return req_freq; #else #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL unsigned int prev_freq = freq; unsigned int prev_laf = prev_freq * util * 100 / max; freq = choose_freq(sg_policy, prev_laf); trace_sugov_next_freq_tl(policy->cpu, util, max, freq, prev_laf, prev_freq); #else #else freq = map_util_freq(util, freq, max); freq = map_util_freq(util, freq, max); trace_sugov_next_freq(policy->cpu, util, max, freq); trace_sugov_next_freq(policy->cpu, util, max, freq); #endif if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update) if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update) return sg_policy->next_freq; return sg_policy->next_freq; Loading Loading @@ -1123,11 +1254,103 @@ static ssize_t pl_store(struct gov_attr_set *attr_set, const char *buf, return count; return count; } } #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL static ssize_t target_loads_show(struct gov_attr_set *attr_set, char *buf) { struct sugov_tunables *tunables = to_sugov_tunables(attr_set); int i; ssize_t ret = 0; unsigned long flags; spin_lock_irqsave(&tunables->target_loads_lock, flags); for (i = 0; i < tunables->ntarget_loads; i++) ret += snprintf(buf + ret, PAGE_SIZE - ret - 1, "%u%s", tunables->target_loads[i], i & 0x1 ? ":" : " "); snprintf(buf + ret - 1, PAGE_SIZE - ret - 1, "\n"); spin_unlock_irqrestore(&tunables->target_loads_lock, flags); return ret; } static unsigned int *get_tokenized_data(const char *buf, int *num_tokens) { const char *cp; int i; int ntokens = 1; unsigned int *tokenized_data; int err = -EINVAL; cp = buf; while ((cp = strpbrk(cp + 1, " :"))) ntokens++; if (!(ntokens & 0x1)) goto err; tokenized_data = kmalloc(ntokens * sizeof(unsigned int), GFP_KERNEL); if (!tokenized_data) { err = -ENOMEM; goto err; } cp = buf; i = 0; while (i < ntokens) { if (sscanf(cp, "%u", &tokenized_data[i++]) != 1) goto err_kfree; cp = strpbrk(cp, " :"); if (!cp) break; cp++; } if (i != ntokens) goto err_kfree; *num_tokens = ntokens; return tokenized_data; err_kfree: kfree(tokenized_data); err: return ERR_PTR(err); } static ssize_t target_loads_store(struct gov_attr_set *attr_set, const char *buf, size_t count) { int ntokens; unsigned int *new_target_loads = NULL; unsigned long flags; struct sugov_tunables *tunables = to_sugov_tunables(attr_set); new_target_loads = get_tokenized_data(buf, &ntokens); if (IS_ERR(new_target_loads)) return PTR_ERR(new_target_loads); spin_lock_irqsave(&tunables->target_loads_lock, flags); if (tunables->target_loads != default_target_loads) kfree(tunables->target_loads); tunables->target_loads = new_target_loads; tunables->ntarget_loads = ntokens; spin_unlock_irqrestore(&tunables->target_loads_lock, flags); return count; } #endif /* CONFIG_OPLUS_FEATURE_SUGOV_TL */ static struct governor_attr hispeed_load = __ATTR_RW(hispeed_load); static struct governor_attr hispeed_load = __ATTR_RW(hispeed_load); static struct governor_attr hispeed_freq = __ATTR_RW(hispeed_freq); static struct governor_attr hispeed_freq = __ATTR_RW(hispeed_freq); static struct governor_attr rtg_boost_freq = __ATTR_RW(rtg_boost_freq); static struct governor_attr rtg_boost_freq = __ATTR_RW(rtg_boost_freq); static struct governor_attr pl = __ATTR_RW(pl); static struct governor_attr pl = __ATTR_RW(pl); #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL static struct governor_attr target_loads = __ATTR(target_loads, 0664, target_loads_show, target_loads_store); #endif /* CONFIG_OPLUS_FEATURE_SUGOV_TL */ static struct attribute *sugov_attributes[] = { static struct attribute *sugov_attributes[] = { &up_rate_limit_us.attr, &up_rate_limit_us.attr, &down_rate_limit_us.attr, &down_rate_limit_us.attr, Loading @@ -1135,6 +1358,9 @@ static struct attribute *sugov_attributes[] = { &hispeed_freq.attr, &hispeed_freq.attr, &rtg_boost_freq.attr, &rtg_boost_freq.attr, &pl.attr, &pl.attr, #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL &target_loads.attr, #endif /* CONFIG_OPLUS_FEATURE_SUGOV_TL */ NULL NULL }; }; Loading Loading @@ -1326,6 +1552,12 @@ static int sugov_init(struct cpufreq_policy *policy) tunables->hispeed_load = DEFAULT_HISPEED_LOAD; tunables->hispeed_load = DEFAULT_HISPEED_LOAD; tunables->hispeed_freq = 0; tunables->hispeed_freq = 0; #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL tunables->target_loads = default_target_loads; tunables->ntarget_loads = ARRAY_SIZE(default_target_loads); spin_lock_init(&tunables->target_loads_lock); #endif /* CONFIG_OPLUS_FEATURE_SUGOV_TL */ switch (policy->cpu) { switch (policy->cpu) { default: default: case 0: case 0: Loading Loading
arch/arm64/configs/vendor/lito-perf_defconfig +1 −0 Original line number Original line Diff line number Diff line Loading @@ -771,3 +771,4 @@ CONFIG_SLA_ALGO=y CONFIG_RATP=y CONFIG_RATP=y CONFIG_QCOM_QDSS_BRIDGE=y CONFIG_QCOM_QDSS_BRIDGE=y CONFIG_CPUFREQ_BOUNCING=y CONFIG_CPUFREQ_BOUNCING=y CONFIG_OPLUS_FEATURE_SUGOV_TL=y
arch/arm64/configs/vendor/lito_defconfig +1 −0 Original line number Original line Diff line number Diff line Loading @@ -835,3 +835,4 @@ CONFIG_SLA=y CONFIG_SLA_ALGO=y CONFIG_SLA_ALGO=y CONFIG_RATP=y CONFIG_RATP=y CONFIG_CPUFREQ_BOUNCING=y CONFIG_CPUFREQ_BOUNCING=y CONFIG_OPLUS_FEATURE_SUGOV_TL=y
include/trace/events/power.h +60 −0 Original line number Original line Diff line number Diff line Loading @@ -901,6 +901,66 @@ TRACE_EVENT(memlat_dev_update, __entry->vote) __entry->vote) ); ); #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL TRACE_EVENT(sugov_next_freq_tl, TP_PROTO(unsigned int cpu, unsigned long util, unsigned long max, unsigned int freq, unsigned int laf, unsigned int prev_freq), TP_ARGS(cpu, util, max, freq, laf, prev_freq), TP_STRUCT__entry( __field(unsigned int, cpu) __field(unsigned long, util) __field(unsigned long, max) __field(unsigned int, freq) __field(unsigned int, laf) __field(unsigned int, prev_freq) ), TP_fast_assign( __entry->cpu = cpu; __entry->util = util; __entry->max = max; __entry->freq = freq; __entry->laf = laf; __entry->prev_freq = prev_freq; ), TP_printk("cpu=%u util=%lu max=%lu freq=%u laf=%u, prev_freq=%u", __entry->cpu, __entry->util, __entry->max, __entry->freq, __entry->laf, __entry->prev_freq) ); TRACE_EVENT(choose_freq, TP_PROTO(unsigned int freq, unsigned int prevfreq, unsigned int freqmax, unsigned int freqmin, unsigned int tl, int index), TP_ARGS(freq, prevfreq, freqmax, freqmin, tl, index), TP_STRUCT__entry( __field(unsigned int, freq) __field(unsigned int, prevfreq) __field(unsigned int, freqmax) __field(unsigned int, freqmin) __field(unsigned int, tl) __field(int, index) ), TP_fast_assign( __entry->freq = freq; __entry->prevfreq = prevfreq; __entry->freqmax = freqmax; __entry->freqmin = freqmin; __entry->tl = tl; __entry->index = index; ), TP_printk("freq=%u prevfreq=%u freqmax=%u freqmin=%u tl=%u index=%d", __entry->freq, __entry->prevfreq, __entry->freqmax, __entry->freqmin, __entry->tl, __entry->index) ); #endif #endif /* _TRACE_POWER_H */ #endif /* _TRACE_POWER_H */ /* This part must be outside protection */ /* This part must be outside protection */ Loading
kernel/sched/cpufreq_schedutil.c +233 −1 Original line number Original line Diff line number Diff line Loading @@ -26,6 +26,12 @@ #endif #endif #include <linux/oem/cpufreq_bouncing.h> #include <linux/oem/cpufreq_bouncing.h> #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL /* Target load. Lower values result in higher CPU speeds. */ #define DEFAULT_TARGET_LOAD 80 static unsigned int default_target_loads[] = {DEFAULT_TARGET_LOAD}; #endif struct sugov_tunables { struct sugov_tunables { struct gov_attr_set attr_set; struct gov_attr_set attr_set; unsigned int up_rate_limit_us; unsigned int up_rate_limit_us; Loading @@ -34,6 +40,11 @@ struct sugov_tunables { unsigned int hispeed_freq; unsigned int hispeed_freq; unsigned int rtg_boost_freq; unsigned int rtg_boost_freq; bool pl; bool pl; #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL spinlock_t target_loads_lock; unsigned int *target_loads; int ntarget_loads; #endif /* CONFIG_OPLUS_FEATURE_SUGOV_TL */ }; }; struct sugov_policy { struct sugov_policy { Loading Loading @@ -318,6 +329,111 @@ static void sugov_deferred_update(struct sugov_policy *sg_policy, u64 time, } } #define TARGET_LOAD 80 #define TARGET_LOAD 80 #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL static unsigned int freq_to_targetload( struct sugov_tunables *tunables, unsigned int freq) { int i; unsigned int ret; unsigned long flags; spin_lock_irqsave(&tunables->target_loads_lock, flags); for (i = 0; i < tunables->ntarget_loads - 1 && freq >= tunables->target_loads[i+1]; i += 2) ; ret = tunables->target_loads[i]; spin_unlock_irqrestore(&tunables->target_loads_lock, flags); return ret; } static unsigned int choose_freq(struct sugov_policy *sg_policy, unsigned int loadadjfreq) { struct cpufreq_policy *policy = sg_policy->policy; unsigned int freq = policy->cur; unsigned int prevfreq, freqmin, freqmax; unsigned int tl; int index; freqmin = 0; freqmax = UINT_MAX; do { prevfreq = freq; tl = freq_to_targetload(sg_policy->tunables, freq); /* * Find the lowest frequency where the computed load is less * than or equal to the target load. */ index = cpufreq_frequency_table_target(policy, loadadjfreq / tl, CPUFREQ_RELATION_L); freq = policy->freq_table[index].frequency; trace_choose_freq(freq, prevfreq, freqmax, freqmin, tl, index); if (freq > prevfreq) { /* The previous frequency is too low. */ freqmin = prevfreq; if (freq >= freqmax) { /* * Find the highest frequency that is less * than freqmax. */ index = cpufreq_frequency_table_target( policy, freqmax - 1, CPUFREQ_RELATION_H); freq = policy->freq_table[index].frequency; if (freq == freqmin) { /* * The first frequency below freqmax * has already been found to be too * low. freqmax is the lowest speed * we found that is fast enough. */ freq = freqmax; break; } } } else if (freq < prevfreq) { /* The previous frequency is high enough. */ freqmax = prevfreq; if (freq <= freqmin) { /* * Find the lowest frequency that is higher * than freqmin. */ index = cpufreq_frequency_table_target( policy, freqmin + 1, CPUFREQ_RELATION_L); freq = policy->freq_table[index].frequency; /* * If freqmax is the first frequency above * freqmin then we have already found that * this speed is fast enough. */ if (freq == freqmax) break; } } /* If same frequency chosen as previous then done. */ } while (freq != prevfreq); return freq; } #endif /* CONFIG_OPLUS_FEATURE_SUGOV_TL */ /** /** * get_next_freq - Compute a new frequency for a given cpufreq policy. * get_next_freq - Compute a new frequency for a given cpufreq policy. * @sg_policy: schedutil policy object to compute the new frequency for. * @sg_policy: schedutil policy object to compute the new frequency for. Loading Loading @@ -349,8 +465,15 @@ static unsigned int get_next_freq(struct sugov_policy *sg_policy, #ifdef CONFIG_CONTROL_CENTER #ifdef CONFIG_CONTROL_CENTER unsigned int req_freq; unsigned int req_freq; freq = map_util_freq(util, freq, max); #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL unsigned int prev_freq = freq; unsigned int prev_laf = prev_freq * util * 100 / max; freq = choose_freq(sg_policy, prev_laf); trace_sugov_next_freq_tl(policy->cpu, util, max, freq, prev_laf, prev_freq); #else freq = map_util_freq(util, freq, max); #endif if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update) { if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update) { req_freq = sg_policy->next_freq; req_freq = sg_policy->next_freq; goto out; goto out; Loading @@ -364,9 +487,17 @@ static unsigned int get_next_freq(struct sugov_policy *sg_policy, sg_policy->policy->req_freq = req_freq; sg_policy->policy->req_freq = req_freq; trace_sugov_next_freq(policy->cpu, util, max, freq, req_freq); trace_sugov_next_freq(policy->cpu, util, max, freq, req_freq); return req_freq; return req_freq; #else #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL unsigned int prev_freq = freq; unsigned int prev_laf = prev_freq * util * 100 / max; freq = choose_freq(sg_policy, prev_laf); trace_sugov_next_freq_tl(policy->cpu, util, max, freq, prev_laf, prev_freq); #else #else freq = map_util_freq(util, freq, max); freq = map_util_freq(util, freq, max); trace_sugov_next_freq(policy->cpu, util, max, freq); trace_sugov_next_freq(policy->cpu, util, max, freq); #endif if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update) if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update) return sg_policy->next_freq; return sg_policy->next_freq; Loading Loading @@ -1123,11 +1254,103 @@ static ssize_t pl_store(struct gov_attr_set *attr_set, const char *buf, return count; return count; } } #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL static ssize_t target_loads_show(struct gov_attr_set *attr_set, char *buf) { struct sugov_tunables *tunables = to_sugov_tunables(attr_set); int i; ssize_t ret = 0; unsigned long flags; spin_lock_irqsave(&tunables->target_loads_lock, flags); for (i = 0; i < tunables->ntarget_loads; i++) ret += snprintf(buf + ret, PAGE_SIZE - ret - 1, "%u%s", tunables->target_loads[i], i & 0x1 ? ":" : " "); snprintf(buf + ret - 1, PAGE_SIZE - ret - 1, "\n"); spin_unlock_irqrestore(&tunables->target_loads_lock, flags); return ret; } static unsigned int *get_tokenized_data(const char *buf, int *num_tokens) { const char *cp; int i; int ntokens = 1; unsigned int *tokenized_data; int err = -EINVAL; cp = buf; while ((cp = strpbrk(cp + 1, " :"))) ntokens++; if (!(ntokens & 0x1)) goto err; tokenized_data = kmalloc(ntokens * sizeof(unsigned int), GFP_KERNEL); if (!tokenized_data) { err = -ENOMEM; goto err; } cp = buf; i = 0; while (i < ntokens) { if (sscanf(cp, "%u", &tokenized_data[i++]) != 1) goto err_kfree; cp = strpbrk(cp, " :"); if (!cp) break; cp++; } if (i != ntokens) goto err_kfree; *num_tokens = ntokens; return tokenized_data; err_kfree: kfree(tokenized_data); err: return ERR_PTR(err); } static ssize_t target_loads_store(struct gov_attr_set *attr_set, const char *buf, size_t count) { int ntokens; unsigned int *new_target_loads = NULL; unsigned long flags; struct sugov_tunables *tunables = to_sugov_tunables(attr_set); new_target_loads = get_tokenized_data(buf, &ntokens); if (IS_ERR(new_target_loads)) return PTR_ERR(new_target_loads); spin_lock_irqsave(&tunables->target_loads_lock, flags); if (tunables->target_loads != default_target_loads) kfree(tunables->target_loads); tunables->target_loads = new_target_loads; tunables->ntarget_loads = ntokens; spin_unlock_irqrestore(&tunables->target_loads_lock, flags); return count; } #endif /* CONFIG_OPLUS_FEATURE_SUGOV_TL */ static struct governor_attr hispeed_load = __ATTR_RW(hispeed_load); static struct governor_attr hispeed_load = __ATTR_RW(hispeed_load); static struct governor_attr hispeed_freq = __ATTR_RW(hispeed_freq); static struct governor_attr hispeed_freq = __ATTR_RW(hispeed_freq); static struct governor_attr rtg_boost_freq = __ATTR_RW(rtg_boost_freq); static struct governor_attr rtg_boost_freq = __ATTR_RW(rtg_boost_freq); static struct governor_attr pl = __ATTR_RW(pl); static struct governor_attr pl = __ATTR_RW(pl); #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL static struct governor_attr target_loads = __ATTR(target_loads, 0664, target_loads_show, target_loads_store); #endif /* CONFIG_OPLUS_FEATURE_SUGOV_TL */ static struct attribute *sugov_attributes[] = { static struct attribute *sugov_attributes[] = { &up_rate_limit_us.attr, &up_rate_limit_us.attr, &down_rate_limit_us.attr, &down_rate_limit_us.attr, Loading @@ -1135,6 +1358,9 @@ static struct attribute *sugov_attributes[] = { &hispeed_freq.attr, &hispeed_freq.attr, &rtg_boost_freq.attr, &rtg_boost_freq.attr, &pl.attr, &pl.attr, #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL &target_loads.attr, #endif /* CONFIG_OPLUS_FEATURE_SUGOV_TL */ NULL NULL }; }; Loading Loading @@ -1326,6 +1552,12 @@ static int sugov_init(struct cpufreq_policy *policy) tunables->hispeed_load = DEFAULT_HISPEED_LOAD; tunables->hispeed_load = DEFAULT_HISPEED_LOAD; tunables->hispeed_freq = 0; tunables->hispeed_freq = 0; #ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL tunables->target_loads = default_target_loads; tunables->ntarget_loads = ARRAY_SIZE(default_target_loads); spin_lock_init(&tunables->target_loads_lock); #endif /* CONFIG_OPLUS_FEATURE_SUGOV_TL */ switch (policy->cpu) { switch (policy->cpu) { default: default: case 0: case 0: Loading