summaryrefslogtreecommitdiff
path: root/drivers/cpufreq/cpufreq_ondemand.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-23 17:56:39 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-23 17:56:39 -0700
commitcf821923ba9aa0917165a12573bdd6dc0a354421 (patch)
treea42f6e7db1eeddb67f6b78ef0336ad7d3ac0fd26 /drivers/cpufreq/cpufreq_ondemand.c
parent4416b0eaa3d51f3e360d6e171e603ff51848bcf5 (diff)
parenta7b422cda5084db7265c3b23310a959b43b47529 (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq
Pull cpufreq updates for 3.4 from Dave Jones: new drivers and some fixes. * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq: provide disable_cpufreq() function to disable the API. EXYNOS5250: Add support cpufreq for EXYNOS5250 EXYNOS4X12: Add support cpufreq for EXYNOS4X12 [CPUFREQ] CPUfreq ondemand: update sampling rate without waiting for next sampling [CPUFREQ] Add S3C2416/S3C2450 cpufreq driver [CPUFREQ] Fix exposure of ARM_EXYNOS4210_CPUFREQ [CPUFREQ] EXYNOS4210: update the name of EXYNOS clock register [CPUFREQ] EXYNOS: Initialize locking_frequency with initial frequency [CPUFREQ] s3c64xx: Fix mis-cherry pick of VDDINT Fix up trivial conflicts in Kconfig and Makefile due to just changes next to each other (OMAP2PLUS changes vs some new EXYNOS cpufreq drivers).
Diffstat (limited to 'drivers/cpufreq/cpufreq_ondemand.c')
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c58
1 files changed, 57 insertions, 1 deletions
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index c3e0652520a1..836e9b062e5e 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -257,6 +257,62 @@ show_one(sampling_down_factor, sampling_down_factor);
show_one(ignore_nice_load, ignore_nice);
show_one(powersave_bias, powersave_bias);
+/**
+ * update_sampling_rate - update sampling rate effective immediately if needed.
+ * @new_rate: new sampling rate
+ *
+ * If new rate is smaller than the old, simply updaing
+ * dbs_tuners_int.sampling_rate might not be appropriate. For example,
+ * if the original sampling_rate was 1 second and the requested new sampling
+ * rate is 10 ms because the user needs immediate reaction from ondemand
+ * governor, but not sure if higher frequency will be required or not,
+ * then, the governor may change the sampling rate too late; up to 1 second
+ * later. Thus, if we are reducing the sampling rate, we need to make the
+ * new value effective immediately.
+ */
+static void update_sampling_rate(unsigned int new_rate)
+{
+ int cpu;
+
+ dbs_tuners_ins.sampling_rate = new_rate
+ = max(new_rate, min_sampling_rate);
+
+ for_each_online_cpu(cpu) {
+ struct cpufreq_policy *policy;
+ struct cpu_dbs_info_s *dbs_info;
+ unsigned long next_sampling, appointed_at;
+
+ policy = cpufreq_cpu_get(cpu);
+ if (!policy)
+ continue;
+ dbs_info = &per_cpu(od_cpu_dbs_info, policy->cpu);
+ cpufreq_cpu_put(policy);
+
+ mutex_lock(&dbs_info->timer_mutex);
+
+ if (!delayed_work_pending(&dbs_info->work)) {
+ mutex_unlock(&dbs_info->timer_mutex);
+ continue;
+ }
+
+ next_sampling = jiffies + usecs_to_jiffies(new_rate);
+ appointed_at = dbs_info->work.timer.expires;
+
+
+ if (time_before(next_sampling, appointed_at)) {
+
+ mutex_unlock(&dbs_info->timer_mutex);
+ cancel_delayed_work_sync(&dbs_info->work);
+ mutex_lock(&dbs_info->timer_mutex);
+
+ schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work,
+ usecs_to_jiffies(new_rate));
+
+ }
+ mutex_unlock(&dbs_info->timer_mutex);
+ }
+}
+
static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
const char *buf, size_t count)
{
@@ -265,7 +321,7 @@ static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
ret = sscanf(buf, "%u", &input);
if (ret != 1)
return -EINVAL;
- dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate);
+ update_sampling_rate(input);
return count;
}