diff --git a/drivers/cpufreq/cpu-boost.c b/drivers/cpufreq/cpu-boost.c index 45b38b3a6754..18edb699c1fa 100644 --- a/drivers/cpufreq/cpu-boost.c +++ b/drivers/cpufreq/cpu-boost.c @@ -38,6 +38,7 @@ struct cpu_sync { unsigned int boost_min; unsigned int input_boost_min; unsigned int task_load; + unsigned int input_boost_freq; }; static DEFINE_PER_CPU(struct cpu_sync, sync_info); @@ -51,8 +52,7 @@ module_param(boost_ms, uint, 0644); static unsigned int sync_threshold; module_param(sync_threshold, uint, 0644); -static unsigned int input_boost_freq; -module_param(input_boost_freq, uint, 0644); +static bool input_boost_enabled; static unsigned int input_boost_ms = 40; module_param(input_boost_ms, uint, 0644); @@ -66,6 +66,73 @@ module_param(load_based_syncs, bool, 0644); static u64 last_input_time; #define MIN_INPUT_INTERVAL (150 * USEC_PER_MSEC) +static int set_input_boost_freq(const char *buf, const struct kernel_param *kp) +{ + int i, ntokens = 0; + unsigned int val, cpu; + const char *cp = buf; + bool enabled = false; + + while ((cp = strpbrk(cp + 1, " :"))) + ntokens++; + + /* single number: apply to all CPUs */ + if (!ntokens) { + if (sscanf(buf, "%u\n", &val) != 1) + return -EINVAL; + for_each_possible_cpu(i) + per_cpu(sync_info, i).input_boost_freq = val; + goto check_enable; + } + + /* CPU:value pair */ + if (!(ntokens % 2)) + return -EINVAL; + + cp = buf; + for (i = 0; i < ntokens; i += 2) { + if (sscanf(cp, "%u:%u", &cpu, &val) != 2) + return -EINVAL; + if (cpu > num_possible_cpus()) + return -EINVAL; + + per_cpu(sync_info, cpu).input_boost_freq = val; + cp = strchr(cp, ' '); + cp++; + } + +check_enable: + for_each_possible_cpu(i) { + if (per_cpu(sync_info, i).input_boost_freq) { + enabled = true; + break; + } + } + input_boost_enabled = enabled; + + return 0; +} + +static int get_input_boost_freq(char *buf, const struct kernel_param *kp) +{ + int cnt = 0, cpu; + struct cpu_sync *s; + + for_each_possible_cpu(cpu) { + s = &per_cpu(sync_info, cpu); + cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, + "%d:%u ", cpu, s->input_boost_freq); + } + cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, "\n"); + return cnt; +} + +static const struct kernel_param_ops param_ops_input_boost_freq = { + .set = set_input_boost_freq, + .get = get_input_boost_freq, +}; +module_param_cb(input_boost_freq, ¶m_ops_input_boost_freq, NULL, 0644); + /* * The CPUFREQ_ADJUST notifier is used to override the current policy min to * make sure policy min >= boost_min. The cpufreq framework then does the job @@ -252,11 +319,11 @@ static void do_input_boost(struct work_struct *work) ret = cpufreq_get_policy(&policy, i); if (ret) continue; - if (policy.cur >= input_boost_freq) + if (policy.cur >= i_sync_info->input_boost_freq) continue; cancel_delayed_work_sync(&i_sync_info->input_boost_rem); - i_sync_info->input_boost_min = input_boost_freq; + i_sync_info->input_boost_min = i_sync_info->input_boost_freq; cpufreq_update_policy(i); queue_delayed_work_on(i_sync_info->cpu, cpu_boost_wq, &i_sync_info->input_boost_rem, @@ -270,7 +337,7 @@ static void cpuboost_input_event(struct input_handle *handle, { u64 now; - if (!input_boost_freq) + if (!input_boost_enabled) return; now = ktime_to_us(ktime_get());