From mboxrd@z Thu Jan 1 00:00:00 1970 From: Thomas Renninger Subject: RE: cpufreq stops working after a while Date: Thu, 17 Aug 2006 12:46:58 +0200 Message-ID: <1155811619.4302.1271.camel@queen.suse.de> References: <1155752344.3554.4.camel@localhost.localdomain> Reply-To: trenn@suse.de Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-EESErr/fS6f7nDOY+j0V" Return-path: In-Reply-To: <1155752344.3554.4.camel@localhost.localdomain> List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: cpufreq-bounces@lists.linux.org.uk Errors-To: cpufreq-bounces+glkc-cpufreq=m.gmane.org+glkc-cpufreq=m.gmane.org@lists.linux.org.uk To: Carlos Garcia Campos Cc: cpufreq@lists.linux.org.uk --=-EESErr/fS6f7nDOY+j0V Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit On Wed, 2006-08-16 at 20:19 +0200, Carlos Garcia Campos wrote: > El mié, 16-08-2006 a las 06:27 -0700, Pallipadi, Venkatesh escribió: > > > Here is what I got from debug messages: > > 1.- scaling_max_freq is set to 600000 > > speedstep-centrino: target=1520000kHz old=1600000 new=1400000 msr=0e24 > cpufreq-core: notification 0 of frequency transition to 1400000 kHz > userspace: saving cpu_cur_freq of cpu 0 to be 1400000 kHz > cpufreq-core: notification 1 of frequency transition to 1400000 kHz > cpufreq-core: scaling loops_per_jiffy to 1395912 for frequency 1400000 kHz > userspace: saving cpu_cur_freq of cpu 0 to be 1400000 kHz > cpufreq-core: target for CPU 0: 1440000 kHz, relation 1 > printk: 42 messages suppressed. > cpufreq-core: updating policy for CPU 0 > cpufreq-core: Warning: CPU frequency out of sync: cpufreq and timing core thinks of 1600000, is 600000 kHz. BIOS probably reduced freq behind kernel's back (you didn't unplug AC?, so this machine might also just reduce freq by BIOS for thermal issues?): I expect you run through: drivers/cpufreq/cpufreq.c:cpufreq_update_policy(): /* BIOS might change freq behind our back -> ask driver for current freq and notify governors about a change */ if (cpufreq_driver->get) { policy.cur = cpufreq_driver->get(cpu); if (!data->cur) { dprintk("Driver did not initialize current freq"); data->cur = policy.cur; } else { if (data->cur != policy.cur) cpufreq_out_of_sync(cpu, data->cur, policy.cur); } } > cpufreq-core: notification 0 of frequency transition to 600000 kHz > userspace: saving cpu_cur_freq of cpu 0 to be 600000 kHz > cpufreq-core: notification 1 of frequency transition to 600000 kHz > cpufreq-core: scaling loops_per_jiffy to 598248 for frequency 600000 kHz > userspace: saving cpu_cur_freq of cpu 0 to be 600000 kHz > cpufreq-core: setting new policy for CPU 0: 600000 - 1600000 kHz > freq-table: request for verification of policy (600000 - 1600000 kHz) for cpu 0 > freq-table: verification lead to (600000 - 1600000 kHz) for cpu 0 > freq-table: request for verification of policy (600000 - 600000 kHz) for cpu 0 > freq-table: verification lead to (600000 - 600000 kHz) for cpu 0 > cpufreq-core: new min and max freqs are 600000 - 600000 kHz > cpufreq-core: governor: change or update limits > cpufreq-core: __cpufreq_governor for CPU 0, event 3 > cpufreq-core: target for CPU 0: 600000 kHz, relation 1 > freq-table: request for target 600000 kHz (relation: 1) for cpu 0 > > 2.- I can set 1600000 again and it works > > cpufreq-core: updating policy for CPU 0 > cpufreq-core: Warning: CPU frequency out of sync: cpufreq and timing core thinks of 600000, is 1600000 kHz. Looks like BIOS decided that we can use highest freq again and directly sets the freq to 1600 and kernel didn't notice. > cpufreq-core: notification 0 of frequency transition to 1600000 kHz > userspace: saving cpu_cur_freq of cpu 0 to be 1600000 kHz > cpufreq-core: scaling loops_per_jiffy to 1595328 for frequency 1600000 kHz > cpufreq-core: notification 1 of frequency transition to 1600000 kHz > userspace: saving cpu_cur_freq of cpu 0 to be 1600000 kHz > cpufreq-core: setting new policy for CPU 0: 600000 - 600000 kHz > freq-table: request for verification of policy (600000 - 600000 kHz) for cpu 0 Oh something went wrong, request should always be from (600000-1600000). > freq-table: verification lead to (600000 - 600000 kHz) for cpu 0 > freq-table: request for verification of policy (600000 - 600000 kHz) for cpu 0 > freq-table: verification lead to (600000 - 600000 kHz) for cpu 0 Eventually freq could get limited here if BIOS (_PPC) still does not allow highest freq. But here it would/should allow it again. It seems as if the "real" max_freq can still be accidently overridden by the temporary limited max_freq. I think this could only happen by calling cpufreq_set_policy(..) (or the one used by min,max sysfs writes), but maybe it may also happen somewhere else... > cpufreq-core: new min and max freqs are 600000 - 600000 kHz > cpufreq-core: governor: change or update limits > cpufreq-core: __cpufreq_governor for CPU 0, event 3 > cpufreq-core: target for CPU 0: 600000 kHz, relation 1 > freq-table: request for target 600000 kHz (relation: 1) for cpu 0 > freq-table: target is 7 (600000 kHz, 1554) > speedstep-centrino: target=600000kHz old=1600000 new=600000 msr=0612 > > I hope it helps to catch the problem. If you could tell us what kind of userspace tool you are using to control cpufreq, that would help a lot. If this tool still makes use of the deprecated /proc/ interface then better upgrade this one. IMO cpufreq_set_policy should not be exported as it is quite dangerous, doing: policy.max=xy cpufreq_set_policy(&policy) Will override the static max_freq (data->user_policy.max) with the temporarily limited one (what should only happen if writing to scaling_max_freq). Only place I found this call was in drivers/acpi/processor_perflib.c If your userspace tool sets frequency over that one (what it should not do): /proc/acpi/processor/XY/performance this patch might help, otherwise it will not. But instead of this patch, I think it's better to rip out this file totally as it also does not provide SMP capabilities (on an SMP system writing to it, may randomly modify frequency of one of the CPUs). Compile tested and patched again 2.6.18-rc4: drivers/acpi/processor_perflib.c | 9 +++++---- drivers/cpufreq/cpufreq.c | 4 +--- 2 files changed, 6 insertions(+), 7 deletions(-) Index: linux-2.6.18-rc4/drivers/acpi/processor_perflib.c =================================================================== --- linux-2.6.18-rc4.orig/drivers/acpi/processor_perflib.c +++ linux-2.6.18-rc4/drivers/acpi/processor_perflib.c @@ -457,7 +457,7 @@ acpi_processor_write_performance(struct struct acpi_processor *pr = (struct acpi_processor *)m->private; struct acpi_processor_performance *perf; char state_string[12] = { '\0' }; - unsigned int new_state = 0; + unsigned int new_state, new_freq = 0; struct cpufreq_policy policy; @@ -480,10 +480,11 @@ acpi_processor_write_performance(struct cpufreq_get_policy(&policy, pr->id); policy.cpu = pr->id; - policy.min = perf->states[new_state].core_frequency * 1000; - policy.max = perf->states[new_state].core_frequency * 1000; + new_freq = perf->states[new_state].core_frequency * 1000; + + __cpufreq_driver_target(&policy, new_freq, CPUFREQ_RELATION_L); + - result = cpufreq_set_policy(&policy); if (result) return result; Index: linux-2.6.18-rc4/drivers/cpufreq/cpufreq.c =================================================================== --- linux-2.6.18-rc4.orig/drivers/cpufreq/cpufreq.c +++ linux-2.6.18-rc4/drivers/cpufreq/cpufreq.c @@ -1448,7 +1448,7 @@ error_out: * * Sets a new CPU frequency and voltage scaling policy. */ -int cpufreq_set_policy(struct cpufreq_policy *policy) +static int cpufreq_set_policy(struct cpufreq_policy *policy) { int ret = 0; struct cpufreq_policy *data; @@ -1478,8 +1478,6 @@ int cpufreq_set_policy(struct cpufreq_po return ret; } -EXPORT_SYMBOL(cpufreq_set_policy); - /** * cpufreq_update_policy - re-evaluate an existing cpufreq policy --=-EESErr/fS6f7nDOY+j0V Content-Disposition: attachment; filename=cpufreq_dont_override_max_freq.patch Content-Type: text/x-patch; name=cpufreq_dont_override_max_freq.patch; charset=utf-8 Content-Transfer-Encoding: 7bit drivers/acpi/processor_perflib.c | 9 +++++---- drivers/cpufreq/cpufreq.c | 4 +--- 2 files changed, 6 insertions(+), 7 deletions(-) Index: linux-2.6.18-rc4/drivers/acpi/processor_perflib.c =================================================================== --- linux-2.6.18-rc4.orig/drivers/acpi/processor_perflib.c +++ linux-2.6.18-rc4/drivers/acpi/processor_perflib.c @@ -457,7 +457,7 @@ acpi_processor_write_performance(struct struct acpi_processor *pr = (struct acpi_processor *)m->private; struct acpi_processor_performance *perf; char state_string[12] = { '\0' }; - unsigned int new_state = 0; + unsigned int new_state, new_freq = 0; struct cpufreq_policy policy; @@ -480,10 +480,11 @@ acpi_processor_write_performance(struct cpufreq_get_policy(&policy, pr->id); policy.cpu = pr->id; - policy.min = perf->states[new_state].core_frequency * 1000; - policy.max = perf->states[new_state].core_frequency * 1000; + new_freq = perf->states[new_state].core_frequency * 1000; + + __cpufreq_driver_target(&policy, new_freq, CPUFREQ_RELATION_L); + - result = cpufreq_set_policy(&policy); if (result) return result; Index: linux-2.6.18-rc4/drivers/cpufreq/cpufreq.c =================================================================== --- linux-2.6.18-rc4.orig/drivers/cpufreq/cpufreq.c +++ linux-2.6.18-rc4/drivers/cpufreq/cpufreq.c @@ -1448,7 +1448,7 @@ error_out: * * Sets a new CPU frequency and voltage scaling policy. */ -int cpufreq_set_policy(struct cpufreq_policy *policy) +static int cpufreq_set_policy(struct cpufreq_policy *policy) { int ret = 0; struct cpufreq_policy *data; @@ -1478,8 +1478,6 @@ int cpufreq_set_policy(struct cpufreq_po return ret; } -EXPORT_SYMBOL(cpufreq_set_policy); - /** * cpufreq_update_policy - re-evaluate an existing cpufreq policy --=-EESErr/fS6f7nDOY+j0V Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Cpufreq mailing list Cpufreq@lists.linux.org.uk http://lists.linux.org.uk/mailman/listinfo/cpufreq --=-EESErr/fS6f7nDOY+j0V--