Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cpufreq: Support per-policy performance boost

The boost control currently applies to the whole system. However, users
may prefer to boost a subset of cores in order to provide prioritized
performance to workloads running on the boosted cores.

Enable per-policy boost by adding a 'boost' sysfs interface under each
policy path. This can be found at:

/sys/devices/system/cpu/cpufreq/policy<*>/boost

Same to the global boost switch, writing 1/0 to the per-policy 'boost'
enables/disables boost on a cpufreq policy respectively.

The user view of global and per-policy boost controls should be:

1. Enabling global boost initially enables boost on all policies, and
per-policy boost can then be enabled or disabled individually, given that
the platform does support so.

2. Disabling global boost makes the per-policy boost interface illegal.

Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
Reviewed-by: Wei Xu <xuwei5@hisilicon.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Jie Zhan and committed by
Rafael J. Wysocki
218a06a7 4c2fdf73

+46
+43
drivers/cpufreq/cpufreq.c
··· 86 86 static int cpufreq_set_policy(struct cpufreq_policy *policy, 87 87 struct cpufreq_governor *new_gov, 88 88 unsigned int new_pol); 89 + static bool cpufreq_boost_supported(void); 89 90 90 91 /* 91 92 * Two notifier lists: the "policy" list is involved in the ··· 624 623 } 625 624 define_one_global_rw(boost); 626 625 626 + static ssize_t show_local_boost(struct cpufreq_policy *policy, char *buf) 627 + { 628 + return sysfs_emit(buf, "%d\n", policy->boost_enabled); 629 + } 630 + 631 + static ssize_t store_local_boost(struct cpufreq_policy *policy, 632 + const char *buf, size_t count) 633 + { 634 + int ret, enable; 635 + 636 + ret = kstrtoint(buf, 10, &enable); 637 + if (ret || enable < 0 || enable > 1) 638 + return -EINVAL; 639 + 640 + if (!cpufreq_driver->boost_enabled) 641 + return -EINVAL; 642 + 643 + if (policy->boost_enabled == enable) 644 + return count; 645 + 646 + cpus_read_lock(); 647 + ret = cpufreq_driver->set_boost(policy, enable); 648 + cpus_read_unlock(); 649 + 650 + if (ret) 651 + return ret; 652 + 653 + policy->boost_enabled = enable; 654 + 655 + return count; 656 + } 657 + 658 + static struct freq_attr local_boost = __ATTR(boost, 0644, show_local_boost, store_local_boost); 659 + 627 660 static struct cpufreq_governor *find_governor(const char *str_governor) 628 661 { 629 662 struct cpufreq_governor *t; ··· 1088 1053 1089 1054 if (cpufreq_driver->bios_limit) { 1090 1055 ret = sysfs_create_file(&policy->kobj, &bios_limit.attr); 1056 + if (ret) 1057 + return ret; 1058 + } 1059 + 1060 + if (cpufreq_boost_supported()) { 1061 + ret = sysfs_create_file(&policy->kobj, &local_boost.attr); 1091 1062 if (ret) 1092 1063 return ret; 1093 1064 } ··· 2759 2718 ret = cpufreq_driver->set_boost(policy, state); 2760 2719 if (ret) 2761 2720 goto err_reset_state; 2721 + 2722 + policy->boost_enabled = state; 2762 2723 } 2763 2724 cpus_read_unlock(); 2764 2725
+3
include/linux/cpufreq.h
··· 141 141 */ 142 142 bool dvfs_possible_from_any_cpu; 143 143 144 + /* Per policy boost enabled flag. */ 145 + bool boost_enabled; 146 + 144 147 /* Cached frequency lookup from cpufreq_driver_resolve_freq. */ 145 148 unsigned int cached_target_freq; 146 149 unsigned int cached_resolved_idx;