Loading kernel/sched/cpufreq_schedutil.c +100 −22 Original line number Diff line number Diff line Loading @@ -23,7 +23,8 @@ struct sugov_tunables { struct gov_attr_set attr_set; unsigned int rate_limit_us; unsigned int up_rate_limit_us; unsigned int down_rate_limit_us; unsigned int hispeed_load; unsigned int hispeed_freq; bool pl; Loading @@ -37,7 +38,9 @@ struct sugov_policy { raw_spinlock_t update_lock; /* For shared policies */ u64 last_freq_update_time; s64 freq_update_delay_ns; s64 min_rate_limit_ns; s64 up_rate_delay_ns; s64 down_rate_delay_ns; u64 last_ws; u64 curr_cycles; u64 last_cyc_update_time; Loading Loading @@ -100,8 +103,32 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time) return true; } /* No need to recalculate next freq for min_rate_limit_us * at least. However we might still decide to further rate * limit once frequency change direction is decided, according * to the separate rate limits. */ delta_ns = time - sg_policy->last_freq_update_time; return delta_ns >= sg_policy->freq_update_delay_ns; return delta_ns >= sg_policy->min_rate_limit_ns; } static bool sugov_up_down_rate_limit(struct sugov_policy *sg_policy, u64 time, unsigned int next_freq) { s64 delta_ns; delta_ns = time - sg_policy->last_freq_update_time; if (next_freq > sg_policy->next_freq && delta_ns < sg_policy->up_rate_delay_ns) return true; if (next_freq < sg_policy->next_freq && delta_ns < sg_policy->down_rate_delay_ns) return true; return false; } static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time, Loading @@ -112,6 +139,9 @@ static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time, if (sg_policy->next_freq == next_freq) return; if (sugov_up_down_rate_limit(sg_policy, time, next_freq)) return; sg_policy->next_freq = next_freq; sg_policy->last_freq_update_time = time; Loading Loading @@ -361,6 +391,7 @@ static void sugov_update_single(struct update_util_data *hook, u64 time, if (busy && next_f < sg_policy->next_freq) next_f = sg_policy->next_freq; } sugov_update_commit(sg_policy, time, next_f); raw_spin_unlock(&sg_policy->update_lock); } Loading Loading @@ -506,15 +537,52 @@ static inline struct sugov_tunables *to_sugov_tunables(struct gov_attr_set *attr return container_of(attr_set, struct sugov_tunables, attr_set); } static ssize_t rate_limit_us_show(struct gov_attr_set *attr_set, char *buf) static DEFINE_MUTEX(min_rate_lock); static void update_min_rate_limit_ns(struct sugov_policy *sg_policy) { mutex_lock(&min_rate_lock); sg_policy->min_rate_limit_ns = min(sg_policy->up_rate_delay_ns, sg_policy->down_rate_delay_ns); mutex_unlock(&min_rate_lock); } static ssize_t up_rate_limit_us_show(struct gov_attr_set *attr_set, char *buf) { struct sugov_tunables *tunables = to_sugov_tunables(attr_set); return sprintf(buf, "%u\n", tunables->rate_limit_us); return sprintf(buf, "%u\n", tunables->up_rate_limit_us); } static ssize_t rate_limit_us_store(struct gov_attr_set *attr_set, const char *buf, size_t count) static ssize_t down_rate_limit_us_show(struct gov_attr_set *attr_set, char *buf) { struct sugov_tunables *tunables = to_sugov_tunables(attr_set); return sprintf(buf, "%u\n", tunables->down_rate_limit_us); } static ssize_t up_rate_limit_us_store(struct gov_attr_set *attr_set, const char *buf, size_t count) { struct sugov_tunables *tunables = to_sugov_tunables(attr_set); struct sugov_policy *sg_policy; unsigned int rate_limit_us; if (kstrtouint(buf, 10, &rate_limit_us)) return -EINVAL; tunables->up_rate_limit_us = rate_limit_us; list_for_each_entry(sg_policy, &attr_set->policy_list, tunables_hook) { sg_policy->up_rate_delay_ns = rate_limit_us * NSEC_PER_USEC; update_min_rate_limit_ns(sg_policy); } return count; } static ssize_t down_rate_limit_us_store(struct gov_attr_set *attr_set, const char *buf, size_t count) { struct sugov_tunables *tunables = to_sugov_tunables(attr_set); struct sugov_policy *sg_policy; Loading @@ -523,10 +591,12 @@ static ssize_t rate_limit_us_store(struct gov_attr_set *attr_set, const char *bu if (kstrtouint(buf, 10, &rate_limit_us)) return -EINVAL; tunables->rate_limit_us = rate_limit_us; tunables->down_rate_limit_us = rate_limit_us; list_for_each_entry(sg_policy, &attr_set->policy_list, tunables_hook) sg_policy->freq_update_delay_ns = rate_limit_us * NSEC_PER_USEC; list_for_each_entry(sg_policy, &attr_set->policy_list, tunables_hook) { sg_policy->down_rate_delay_ns = rate_limit_us * NSEC_PER_USEC; update_min_rate_limit_ns(sg_policy); } return count; } Loading Loading @@ -601,13 +671,15 @@ static ssize_t pl_store(struct gov_attr_set *attr_set, const char *buf, return count; } static struct governor_attr rate_limit_us = __ATTR_RW(rate_limit_us); static struct governor_attr up_rate_limit_us = __ATTR_RW(up_rate_limit_us); static struct governor_attr down_rate_limit_us = __ATTR_RW(down_rate_limit_us); static struct governor_attr hispeed_load = __ATTR_RW(hispeed_load); static struct governor_attr hispeed_freq = __ATTR_RW(hispeed_freq); static struct governor_attr pl = __ATTR_RW(pl); static struct attribute *sugov_attributes[] = { &rate_limit_us.attr, &up_rate_limit_us.attr, &down_rate_limit_us.attr, &hispeed_load.attr, &hispeed_freq.attr, &pl.attr, Loading Loading @@ -725,7 +797,8 @@ static void sugov_tunables_save(struct cpufreq_policy *policy, cached->pl = tunables->pl; cached->hispeed_load = tunables->hispeed_load; cached->hispeed_freq = tunables->hispeed_freq; cached->rate_limit_us = tunables->rate_limit_us; cached->up_rate_limit_us = tunables->up_rate_limit_us; cached->down_rate_limit_us = tunables->down_rate_limit_us; } static void sugov_tunables_free(struct sugov_tunables *tunables) Loading @@ -748,16 +821,14 @@ static void sugov_tunables_restore(struct cpufreq_policy *policy) tunables->pl = cached->pl; tunables->hispeed_load = cached->hispeed_load; tunables->hispeed_freq = cached->hispeed_freq; tunables->rate_limit_us = cached->rate_limit_us; sg_policy->freq_update_delay_ns = tunables->rate_limit_us * NSEC_PER_USEC; tunables->up_rate_limit_us = cached->up_rate_limit_us; tunables->down_rate_limit_us = cached->down_rate_limit_us; } static int sugov_init(struct cpufreq_policy *policy) { struct sugov_policy *sg_policy; struct sugov_tunables *tunables; unsigned int lat; int ret = 0; /* State should be equivalent to EXIT */ Loading Loading @@ -796,12 +867,15 @@ static int sugov_init(struct cpufreq_policy *policy) goto stop_kthread; } tunables->rate_limit_us = LATENCY_MULTIPLIER; /* * NOTE: * intializing up_rate/down_rate to 0 explicitly in kernel * since WALT expects so by default. */ tunables->up_rate_limit_us = 0; tunables->down_rate_limit_us = 0; tunables->hispeed_load = DEFAULT_HISPEED_LOAD; tunables->hispeed_freq = 0; lat = policy->cpuinfo.transition_latency / NSEC_PER_USEC; if (lat) tunables->rate_limit_us *= lat; policy->governor_data = sg_policy; sg_policy->tunables = tunables; Loading Loading @@ -865,7 +939,11 @@ static int sugov_start(struct cpufreq_policy *policy) struct sugov_policy *sg_policy = policy->governor_data; unsigned int cpu; sg_policy->freq_update_delay_ns = sg_policy->tunables->rate_limit_us * NSEC_PER_USEC; sg_policy->up_rate_delay_ns = sg_policy->tunables->up_rate_limit_us * NSEC_PER_USEC; sg_policy->down_rate_delay_ns = sg_policy->tunables->down_rate_limit_us * NSEC_PER_USEC; update_min_rate_limit_ns(sg_policy); sg_policy->last_freq_update_time = 0; sg_policy->next_freq = UINT_MAX; sg_policy->work_in_progress = false; Loading Loading
kernel/sched/cpufreq_schedutil.c +100 −22 Original line number Diff line number Diff line Loading @@ -23,7 +23,8 @@ struct sugov_tunables { struct gov_attr_set attr_set; unsigned int rate_limit_us; unsigned int up_rate_limit_us; unsigned int down_rate_limit_us; unsigned int hispeed_load; unsigned int hispeed_freq; bool pl; Loading @@ -37,7 +38,9 @@ struct sugov_policy { raw_spinlock_t update_lock; /* For shared policies */ u64 last_freq_update_time; s64 freq_update_delay_ns; s64 min_rate_limit_ns; s64 up_rate_delay_ns; s64 down_rate_delay_ns; u64 last_ws; u64 curr_cycles; u64 last_cyc_update_time; Loading Loading @@ -100,8 +103,32 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time) return true; } /* No need to recalculate next freq for min_rate_limit_us * at least. However we might still decide to further rate * limit once frequency change direction is decided, according * to the separate rate limits. */ delta_ns = time - sg_policy->last_freq_update_time; return delta_ns >= sg_policy->freq_update_delay_ns; return delta_ns >= sg_policy->min_rate_limit_ns; } static bool sugov_up_down_rate_limit(struct sugov_policy *sg_policy, u64 time, unsigned int next_freq) { s64 delta_ns; delta_ns = time - sg_policy->last_freq_update_time; if (next_freq > sg_policy->next_freq && delta_ns < sg_policy->up_rate_delay_ns) return true; if (next_freq < sg_policy->next_freq && delta_ns < sg_policy->down_rate_delay_ns) return true; return false; } static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time, Loading @@ -112,6 +139,9 @@ static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time, if (sg_policy->next_freq == next_freq) return; if (sugov_up_down_rate_limit(sg_policy, time, next_freq)) return; sg_policy->next_freq = next_freq; sg_policy->last_freq_update_time = time; Loading Loading @@ -361,6 +391,7 @@ static void sugov_update_single(struct update_util_data *hook, u64 time, if (busy && next_f < sg_policy->next_freq) next_f = sg_policy->next_freq; } sugov_update_commit(sg_policy, time, next_f); raw_spin_unlock(&sg_policy->update_lock); } Loading Loading @@ -506,15 +537,52 @@ static inline struct sugov_tunables *to_sugov_tunables(struct gov_attr_set *attr return container_of(attr_set, struct sugov_tunables, attr_set); } static ssize_t rate_limit_us_show(struct gov_attr_set *attr_set, char *buf) static DEFINE_MUTEX(min_rate_lock); static void update_min_rate_limit_ns(struct sugov_policy *sg_policy) { mutex_lock(&min_rate_lock); sg_policy->min_rate_limit_ns = min(sg_policy->up_rate_delay_ns, sg_policy->down_rate_delay_ns); mutex_unlock(&min_rate_lock); } static ssize_t up_rate_limit_us_show(struct gov_attr_set *attr_set, char *buf) { struct sugov_tunables *tunables = to_sugov_tunables(attr_set); return sprintf(buf, "%u\n", tunables->rate_limit_us); return sprintf(buf, "%u\n", tunables->up_rate_limit_us); } static ssize_t rate_limit_us_store(struct gov_attr_set *attr_set, const char *buf, size_t count) static ssize_t down_rate_limit_us_show(struct gov_attr_set *attr_set, char *buf) { struct sugov_tunables *tunables = to_sugov_tunables(attr_set); return sprintf(buf, "%u\n", tunables->down_rate_limit_us); } static ssize_t up_rate_limit_us_store(struct gov_attr_set *attr_set, const char *buf, size_t count) { struct sugov_tunables *tunables = to_sugov_tunables(attr_set); struct sugov_policy *sg_policy; unsigned int rate_limit_us; if (kstrtouint(buf, 10, &rate_limit_us)) return -EINVAL; tunables->up_rate_limit_us = rate_limit_us; list_for_each_entry(sg_policy, &attr_set->policy_list, tunables_hook) { sg_policy->up_rate_delay_ns = rate_limit_us * NSEC_PER_USEC; update_min_rate_limit_ns(sg_policy); } return count; } static ssize_t down_rate_limit_us_store(struct gov_attr_set *attr_set, const char *buf, size_t count) { struct sugov_tunables *tunables = to_sugov_tunables(attr_set); struct sugov_policy *sg_policy; Loading @@ -523,10 +591,12 @@ static ssize_t rate_limit_us_store(struct gov_attr_set *attr_set, const char *bu if (kstrtouint(buf, 10, &rate_limit_us)) return -EINVAL; tunables->rate_limit_us = rate_limit_us; tunables->down_rate_limit_us = rate_limit_us; list_for_each_entry(sg_policy, &attr_set->policy_list, tunables_hook) sg_policy->freq_update_delay_ns = rate_limit_us * NSEC_PER_USEC; list_for_each_entry(sg_policy, &attr_set->policy_list, tunables_hook) { sg_policy->down_rate_delay_ns = rate_limit_us * NSEC_PER_USEC; update_min_rate_limit_ns(sg_policy); } return count; } Loading Loading @@ -601,13 +671,15 @@ static ssize_t pl_store(struct gov_attr_set *attr_set, const char *buf, return count; } static struct governor_attr rate_limit_us = __ATTR_RW(rate_limit_us); static struct governor_attr up_rate_limit_us = __ATTR_RW(up_rate_limit_us); static struct governor_attr down_rate_limit_us = __ATTR_RW(down_rate_limit_us); static struct governor_attr hispeed_load = __ATTR_RW(hispeed_load); static struct governor_attr hispeed_freq = __ATTR_RW(hispeed_freq); static struct governor_attr pl = __ATTR_RW(pl); static struct attribute *sugov_attributes[] = { &rate_limit_us.attr, &up_rate_limit_us.attr, &down_rate_limit_us.attr, &hispeed_load.attr, &hispeed_freq.attr, &pl.attr, Loading Loading @@ -725,7 +797,8 @@ static void sugov_tunables_save(struct cpufreq_policy *policy, cached->pl = tunables->pl; cached->hispeed_load = tunables->hispeed_load; cached->hispeed_freq = tunables->hispeed_freq; cached->rate_limit_us = tunables->rate_limit_us; cached->up_rate_limit_us = tunables->up_rate_limit_us; cached->down_rate_limit_us = tunables->down_rate_limit_us; } static void sugov_tunables_free(struct sugov_tunables *tunables) Loading @@ -748,16 +821,14 @@ static void sugov_tunables_restore(struct cpufreq_policy *policy) tunables->pl = cached->pl; tunables->hispeed_load = cached->hispeed_load; tunables->hispeed_freq = cached->hispeed_freq; tunables->rate_limit_us = cached->rate_limit_us; sg_policy->freq_update_delay_ns = tunables->rate_limit_us * NSEC_PER_USEC; tunables->up_rate_limit_us = cached->up_rate_limit_us; tunables->down_rate_limit_us = cached->down_rate_limit_us; } static int sugov_init(struct cpufreq_policy *policy) { struct sugov_policy *sg_policy; struct sugov_tunables *tunables; unsigned int lat; int ret = 0; /* State should be equivalent to EXIT */ Loading Loading @@ -796,12 +867,15 @@ static int sugov_init(struct cpufreq_policy *policy) goto stop_kthread; } tunables->rate_limit_us = LATENCY_MULTIPLIER; /* * NOTE: * intializing up_rate/down_rate to 0 explicitly in kernel * since WALT expects so by default. */ tunables->up_rate_limit_us = 0; tunables->down_rate_limit_us = 0; tunables->hispeed_load = DEFAULT_HISPEED_LOAD; tunables->hispeed_freq = 0; lat = policy->cpuinfo.transition_latency / NSEC_PER_USEC; if (lat) tunables->rate_limit_us *= lat; policy->governor_data = sg_policy; sg_policy->tunables = tunables; Loading Loading @@ -865,7 +939,11 @@ static int sugov_start(struct cpufreq_policy *policy) struct sugov_policy *sg_policy = policy->governor_data; unsigned int cpu; sg_policy->freq_update_delay_ns = sg_policy->tunables->rate_limit_us * NSEC_PER_USEC; sg_policy->up_rate_delay_ns = sg_policy->tunables->up_rate_limit_us * NSEC_PER_USEC; sg_policy->down_rate_delay_ns = sg_policy->tunables->down_rate_limit_us * NSEC_PER_USEC; update_min_rate_limit_ns(sg_policy); sg_policy->last_freq_update_time = 0; sg_policy->next_freq = UINT_MAX; sg_policy->work_in_progress = false; Loading