cpufreq: cpu-boost: Support separate input_boost_freq for different CPUs

Different types of CPUs could have different frequency to satisfy same
input workload. Add support for using different input_boost_freq on
different CPUs.

input_boost_freq now either takes a single number which applies to all
CPUs, or cpuid:freq pairs separated by space for different CPUs.

Change-Id: I20506a9fbdb4d532d94168bbd61744595bebc8e5
Signed-off-by: Junjie Wu <junjiew@codeaurora.org>
This commit is contained in:
Junjie Wu 2014-05-28 16:36:25 -07:00 committed by David Keitel
parent e1d864dc94
commit 1bf8600f7c

View file

@ -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, &param_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());