From df8b59be0976c56820453730078bef99a8d1dbda Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 20 Sep 2005 12:39:35 -0700 Subject: [CPUFREQ] Avoid the ondemand cpufreq governor to use a too high frequency for stats. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The problem is in the ondemand governor, there is a periodic measurement of the CPU usage. This CPU usage is updated by the scheduler after every tick (basically, by adding 1 either to "idle" or to "user" or to "system"). So if the frequency of the governor is too high, the stat will be meaningless (as mostly no number have changed). So this patch checks that the measurements are separated by at least 10 ticks. It means that by default, stats will have about 5% error (20 ticks). Of course those numbers can be argued but, IMHO, they look sane. The patch also includes a small clean-up to check more explictly the result of the conversion from ns to µs being null. Let's note that (on x86) this has never been really needed before 2.6.13 because HZ was always 1000. Now that HZ can be 100, some CPU might be affected by this problem. For instance when HZ=100, the centrino ,which has a 10µs transition latency, would lead to the governor allowing to read stats every tick (10ms)! Signed-off-by: Eric Piel Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_ondemand.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers/cpufreq') diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index c1fc9c6..1774111 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -48,7 +48,10 @@ * All times here are in uS. */ static unsigned int def_sampling_rate; -#define MIN_SAMPLING_RATE (def_sampling_rate / 2) +#define MIN_SAMPLING_RATE_RATIO (2) +/* for correct statistics, we need at least 10 ticks between each measure */ +#define MIN_STAT_SAMPLING_RATE (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10)) +#define MIN_SAMPLING_RATE (def_sampling_rate / MIN_SAMPLING_RATE_RATIO) #define MAX_SAMPLING_RATE (500 * def_sampling_rate) #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) #define DEF_SAMPLING_DOWN_FACTOR (1) @@ -416,13 +419,16 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, if (dbs_enable == 1) { unsigned int latency; /* policy latency is in nS. Convert it to uS first */ + latency = policy->cpuinfo.transition_latency / 1000; + if (latency == 0) + latency = 1; - latency = policy->cpuinfo.transition_latency; - if (latency < 1000) - latency = 1000; - - def_sampling_rate = (latency / 1000) * + def_sampling_rate = latency * DEF_SAMPLING_RATE_LATENCY_MULTIPLIER; + + if (def_sampling_rate < MIN_STAT_SAMPLING_RATE) + def_sampling_rate = MIN_STAT_SAMPLING_RATE; + dbs_tuners_ins.sampling_rate = def_sampling_rate; dbs_tuners_ins.ignore_nice = 0; -- cgit v1.1 From e98df50c5200ae3c748d69002a8827afc9d2eae2 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 20 Oct 2005 15:17:43 -0700 Subject: [CPUFREQ] kzalloc conversions for cpufreq core. Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq.c | 3 +-- drivers/cpufreq/cpufreq_stats.c | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/cpufreq') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 109d62c..cfe1d0a 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -595,12 +595,11 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) goto module_out; } - policy = kmalloc(sizeof(struct cpufreq_policy), GFP_KERNEL); + policy = kzalloc(sizeof(struct cpufreq_policy), GFP_KERNEL); if (!policy) { ret = -ENOMEM; goto nomem_out; } - memset(policy, 0, sizeof(struct cpufreq_policy)); policy->cpu = cpu; policy->cpus = cpumask_of_cpu(cpu); diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 741b6b1..ff16a87 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -192,9 +192,8 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy, unsigned int cpu = policy->cpu; if (cpufreq_stats_table[cpu]) return -EBUSY; - if ((stat = kmalloc(sizeof(struct cpufreq_stats), GFP_KERNEL)) == NULL) + if ((stat = kzalloc(sizeof(struct cpufreq_stats), GFP_KERNEL)) == NULL) return -ENOMEM; - memset(stat, 0, sizeof (struct cpufreq_stats)); data = cpufreq_cpu_get(cpu); if ((ret = sysfs_create_group(&data->kobj, &stats_attr_group))) @@ -216,12 +215,11 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy, alloc_size += count * count * sizeof(int); #endif stat->max_state = count; - stat->time_in_state = kmalloc(alloc_size, GFP_KERNEL); + stat->time_in_state = kzalloc(alloc_size, GFP_KERNEL); if (!stat->time_in_state) { ret = -ENOMEM; goto error_out; } - memset(stat->time_in_state, 0, alloc_size); stat->freq_table = (unsigned int *)(stat->time_in_state + count); #ifdef CONFIG_CPU_FREQ_STAT_DETAILS -- cgit v1.1 From bc7b26fd7ca5e0c6e769d3886c022f0a98fd88ec Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 27 Oct 2005 16:02:06 -0700 Subject: [CPUFREQ] Check return value of cpufreq_cpu_get in cpufreq_stats This fixes an issue found in drivers/cpufreq/cpufreq_stats.c by Coverity. Error reported: CID: 2642 Checker: NULL_RETURNS (help) File: /export2/p4-coverity/mc2/linux26/drivers/cpufreq/cpufreq_stats.c Function: cpufreq_stats_create_table Description: Dereferencing NULL value "data" Patch description: The return of cpufreq_cpu_get can be NULL, check return code and return -EINVAL if it is NULL. Signed-off-by: Jayachandran C. Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_stats.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/cpufreq') diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index ff16a87..19b4c3e 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -196,6 +196,11 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy, return -ENOMEM; data = cpufreq_cpu_get(cpu); + if (data == NULL) { + ret = -EINVAL; + goto error_get_fail; + } + if ((ret = sysfs_create_group(&data->kobj, &stats_attr_group))) goto error_out; -- cgit v1.1 From b7fb358c7c36a14927d5523ea674e69f90c51d1d Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 1 Nov 2005 23:13:45 -0800 Subject: [CPUFREQ] Fix up compile of cpufreq_stats Whoops, I lost a hunk of the last patch somehow. Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_stats.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/cpufreq') diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 19b4c3e..7ddf714 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -247,6 +247,7 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy, return 0; error_out: cpufreq_cpu_put(data); +error_get_fail: kfree(stat); cpufreq_stats_table[cpu] = NULL; return ret; -- cgit v1.1