From mboxrd@z Thu Jan 1 00:00:00 1970 From: Fabio Baltieri Subject: [PATCH] cpufreq: ondemand: update sampling rate only on right CPUs Date: Mon, 26 Nov 2012 19:10:12 +0100 Message-ID: <1353953412-20667-1-git-send-email-fabio.baltieri@linaro.org> Return-path: Sender: linux-kernel-owner@vger.kernel.org To: "Rafael J. Wysocki" , cpufreq@vger.kernel.org, linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Fabio Baltieri List-Id: linux-pm@vger.kernel.org Fix cpufreq_gov_ondemand to skip CPU where another governor is used. The bug present itself as NULL pointer access on the mutex_lock() call, an can be reproduced on an SMP machine by setting the default governor to anything other than ondemand, setting a single CPU's governor to ondemand, then changing the sample rate by writing on: > /sys/devices/system/cpu/cpufreq/ondemand/sampling_rate Backtrace: Nov 26 17:36:54 balto kernel: [ 839.585241] BUG: unable to handle kernel NULL pointer dereference at (null) Nov 26 17:36:54 balto kernel: [ 839.585311] IP: [] __mutex_lock_slowpath+0xb2/0x170 [snip] Nov 26 17:36:54 balto kernel: [ 839.587005] Call Trace: Nov 26 17:36:54 balto kernel: [ 839.587030] [] mutex_lock+0x22/0x40 Nov 26 17:36:54 balto kernel: [ 839.587067] [] store_sampling_rate+0xbf/0x150 Nov 26 17:36:54 balto kernel: [ 839.587110] [] ? __do_page_fault+0x1cc/0x4c0 Nov 26 17:36:54 balto kernel: [ 839.587153] [] kobj_attr_store+0xf/0x20 Nov 26 17:36:54 balto kernel: [ 839.587192] [] sysfs_write_file+0xcd/0x140 Nov 26 17:36:54 balto kernel: [ 839.587234] [] vfs_write+0xac/0x180 Nov 26 17:36:54 balto kernel: [ 839.587271] [] sys_write+0x52/0xa0 Nov 26 17:36:54 balto kernel: [ 839.587306] [] ? do_page_fault+0xe/0x10 Nov 26 17:36:54 balto kernel: [ 839.587345] [] system_call_fastpath+0x16/0x1b Signed-off-by: Fabio Baltieri --- Hi Rafael, this is based on a clean linux-pm linux-next branch (i.e. not with my other patch-set applied), so expect a context conflict if both are applied. Thanks, Fabio drivers/cpufreq/cpufreq_ondemand.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index cca3e9f..7731f7c 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -40,6 +40,10 @@ static struct dbs_data od_dbs_data; static DEFINE_PER_CPU(struct od_cpu_dbs_info_s, od_cpu_dbs_info); +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND +static struct cpufreq_governor cpufreq_gov_ondemand; +#endif + static struct od_dbs_tuners od_tuners = { .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, @@ -279,6 +283,10 @@ static void update_sampling_rate(unsigned int new_rate) policy = cpufreq_cpu_get(cpu); if (!policy) continue; + if (policy->governor != &cpufreq_gov_ondemand) { + cpufreq_cpu_put(policy); + continue; + } dbs_info = &per_cpu(od_cpu_dbs_info, policy->cpu); cpufreq_cpu_put(policy); -- 1.7.12.1