bk://linux-dj.bkbits.net/cpufreq davej@delerium.codemonkey.org.uk|ChangeSet|20040613211236|61865 davej # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/06/11 18:50:39+01:00 davej@redhat.com # [CPUFREQ] speedstep-ich: SMT/HT support, fix for notify change # Propagate the notify moving to speedstep-ich, and add SMT (HT) # awareness to the speedstep-ich. # # Patch was written in very large parts by Christian Hoelbling. # # Signed-off-by: Dominik Brodowski # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/speedstep-ich.c # 2004/06/11 18:50:29+01:00 davej@redhat.com +54 -16 # [CPUFREQ] speedstep-ich: SMT/HT support, fix for notify change # Propagate the notify moving to speedstep-ich, and add SMT (HT) # awareness to the speedstep-ich. # # Patch was written in very large parts by Christian Hoelbling. # # Signed-off-by: Dominik Brodowski # Signed-off-by: Dave Jones # # ChangeSet # 2004/06/11 18:49:00+01:00 davej@redhat.com # [CPUFREQ] AMD powernow documentation updates. # From: Paul Devriendt # Signed-off-by: Dave Jones # # Documentation/cpu-freq/amd-powernow.txt # 2004/06/11 18:48:53+01:00 davej@redhat.com +4 -3 # [CPUFREQ] AMD powernow documentation updates. # From: Paul Devriendt # Signed-off-by: Dave Jones # # ChangeSet # 2004/06/11 13:18:54+01:00 davej@redhat.com # [CPUFREQ] Add missing include to p4-clockmod # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/p4-clockmod.c # 2004/06/11 13:18:47+01:00 davej@redhat.com +1 -0 # [CPUFREQ] Add missing include to p4-clockmod # Signed-off-by: Dave Jones # # ChangeSet # 2004/06/11 12:51:48+01:00 davej@redhat.com # [CPUFREQ] replace for_each_cpu with for_each_cpu_mask in p4-clockmod # # From: Bruno Ducrot # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/p4-clockmod.c # 2004/06/11 12:51:41+01:00 davej@redhat.com +11 -17 # [CPUFREQ] replace for_each_cpu with for_each_cpu_mask in p4-clockmod # # From: Bruno Ducrot # Signed-off-by: Dave Jones # # ChangeSet # 2004/06/11 11:13:42+01:00 davej@redhat.com # [CPUFREQ] small codingstyle fixes # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/longhaul.c # 2004/06/11 11:13:33+01:00 davej@redhat.com +8 -8 # [CPUFREQ] small codingstyle fixes # Signed-off-by: Dave Jones # # ChangeSet # 2004/06/11 11:07:01+01:00 davej@redhat.com # [CPUFREQ] Detect P4M's in speedstep lib # From: Christian Hoelbling # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/speedstep-lib.c # 2004/06/11 11:06:54+01:00 davej@redhat.com +3 -4 # [CPUFREQ] Detect P4M's in speedstep lib # From: Christian Hoelbling # Signed-off-by: Dave Jones # # ChangeSet # 2004/06/10 22:48:57+01:00 davej@redhat.com # [CPUFREQ] Fix cpufreq on ARM # # cpufreq doesn't appear to initialise on ARM - cpufreq_register_driver() # fails with -ENODEV. # # This appears to be because we register cpus at subsys_initcall() time, # and cpufreq drivers at arch_initcall() time. We need cpufreq up and # running before any drivers are initialised since their timings depend # on the CPU clock rate. # # The following patch appears to fix these problems. # # From: Russell King # Signed-off-by: Dave Jones # # arch/arm/mach-sa1100/cpu-sa1110.c # 2004/06/10 22:48:50+01:00 davej@redhat.com +3 -2 # [CPUFREQ] Fix cpufreq on ARM # # cpufreq doesn't appear to initialise on ARM - cpufreq_register_driver() # fails with -ENODEV. # # This appears to be because we register cpus at subsys_initcall() time, # and cpufreq drivers at arch_initcall() time. We need cpufreq up and # running before any drivers are initialised since their timings depend # on the CPU clock rate. # # The following patch appears to fix these problems. # # From: Russell King # Signed-off-by: Dave Jones # # arch/arm/mach-sa1100/cpu-sa1100.c # 2004/06/10 22:48:50+01:00 davej@redhat.com +3 -2 # [CPUFREQ] Fix cpufreq on ARM # # cpufreq doesn't appear to initialise on ARM - cpufreq_register_driver() # fails with -ENODEV. # # This appears to be because we register cpus at subsys_initcall() time, # and cpufreq drivers at arch_initcall() time. We need cpufreq up and # running before any drivers are initialised since their timings depend # on the CPU clock rate. # # The following patch appears to fix these problems. # # From: Russell King # Signed-off-by: Dave Jones # # ChangeSet # 2004/06/10 22:47:04+01:00 davej@redhat.com # [CPUFREQ] Remove notify in speedstep_set_state [2/2] # # Signed-off-by: Bruno Ducrot # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/speedstep-smi.c # 2004/06/10 22:46:57+01:00 davej@redhat.com +13 -19 # [CPUFREQ] Remove notify in speedstep_set_state [2/2] # # Signed-off-by: Bruno Ducrot # Signed-off-by: Dave Jones # # ChangeSet # 2004/06/10 22:46:01+01:00 davej@redhat.com # [CPUFREQ] Remove notify in speedstep_set_state [1/2] # Remove 'notify' in speedstep_set_state for speedstep-lib # # Signed-off-by: Bruno Ducrot # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/speedstep-lib.h # 2004/06/10 22:45:52+01:00 davej@redhat.com +1 -1 # [CPUFREQ] Remove notify in speedstep_set_state [1/2] # Remove 'notify' in speedstep_set_state for speedstep-lib # # Signed-off-by: Bruno Ducrot # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/speedstep-lib.c # 2004/06/10 22:45:52+01:00 davej@redhat.com +4 -6 # [CPUFREQ] Remove notify in speedstep_set_state [1/2] # Remove 'notify' in speedstep_set_state for speedstep-lib # # Signed-off-by: Bruno Ducrot # Signed-off-by: Dave Jones # # ChangeSet # 2004/06/10 22:43:29+01:00 davej@redhat.com # [CPUFREQ] Limit return value of speedstep_get_state() # # Looking around speedstep-smi, there is a lot of call to # speedstep_get_state() which is used as an index for the array # speedstep_freqs. But speedstep_get_state() will return the value of ebx # after a call to a SMI handler. It's not safe IMHO. # # From: Bruno Ducrot # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/speedstep-smi.c # 2004/06/10 22:43:21+01:00 davej@redhat.com +1 -1 # [CPUFREQ] Limit return value of speedstep_get_state() # # Looking around speedstep-smi, there is a lot of call to # speedstep_get_state() which is used as an index for the array # speedstep_freqs. But speedstep_get_state() will return the value of ebx # after a call to a SMI handler. It's not safe IMHO. # # From: Bruno Ducrot # Signed-off-by: Dave Jones # # ChangeSet # 2004/06/10 22:39:58+01:00 davej@redhat.com # [CPUFREQ] Add documentation on AMD powernow drivers # From Paul Devriendt. # Signed-off-by: Dave Jones # # # Documentation/cpu-freq/amd-powernow.txt # 2004/06/10 22:39:51+01:00 davej@redhat.com +37 -0 # # Documentation/cpu-freq/amd-powernow.txt # 2004/06/10 22:39:51+01:00 davej@redhat.com +0 -0 # BitKeeper file /mnt/data/src/bk/cpufreq/Documentation/cpu-freq/amd-powernow.txt # # ChangeSet # 2004/06/10 22:36:43+01:00 davej@redhat.com # [CPUFREQ] powernow-k8: preempt fix # # Pavel's fix for preempt in the suspend scenario. # The driver protects itself from multiple entry already, and it does not care if # there is a long delay in the middle of a multi-step transition, so there # really is no need for it to disable preempt. # # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/powernow-k8.c # 2004/06/10 22:36:36+01:00 davej@redhat.com +1 -6 # [CPUFREQ] powernow-k8: preempt fix # # Pavel's fix for preempt in the suspend scenario. # The driver protects itself from multiple entry already, and it does not care if # there is a long delay in the middle of a multi-step transition, so there # really is no need for it to disable preempt. # # Signed-off-by: Dave Jones # # ChangeSet # 2004/06/10 22:33:54+01:00 davej@redhat.com # [CPUFREQ] powernow-k8: ignore double lo freq table entries # # Ignore two identical low freq entries in the ACPI tables for the powernow-k8 # driver. # # Signed-off-by: Dominik Brodowski # Signed-off-by: Dave Jones # # # arch/i386/kernel/cpu/cpufreq/powernow-k8.c # 2004/06/10 22:33:47+01:00 davej@redhat.com +16 -4 # [CPUFREQ] powernow-k8: ignore double lo freq table entries # # Ignore two identical low freq entries in the ACPI tables for the powernow-k8 # driver. # # Signed-off-by: Dominik Brodowski # Signed-off-by: Dave Jones # # # ChangeSet # 2004/06/10 22:32:02+01:00 davej@redhat.com # [CPUFREQ] convert gx-suspmod MODULE_PARM to module_param # # Convert gx-suspmod's MODULE_PARM to module_param. # # Signed-off-by: Dominik Brodowski # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/gx-suspmod.c # 2004/06/10 22:31:54+01:00 davej@redhat.com +2 -2 # [CPUFREQ] convert gx-suspmod MODULE_PARM to module_param # # Convert gx-suspmod's MODULE_PARM to module_param. # # Signed-off-by: Dominik Brodowski # Signed-off-by: Dave Jones # # ChangeSet # 2004/06/10 22:30:33+01:00 davej@redhat.com # [CPUFREQ] convert elanfreq MODULE_PARM to module_param # # Convert elanfreq's MODULE_PARM to module_param, and warn users that the setup parameter # "elanfreq" will go away in favor of "elanfreq.max_freq". # # Signed-off-by: Dominik Brodowski # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/elanfreq.c # 2004/06/10 22:30:23+01:00 davej@redhat.com +2 -1 # [CPUFREQ] convert elanfreq MODULE_PARM to module_param # # Convert elanfreq's MODULE_PARM to module_param, and warn users that the setup parameter # "elanfreq" will go away in favor of "elanfreq.max_freq". # # Signed-off-by: Dominik Brodowski # Signed-off-by: Dave Jones # # ChangeSet # 2004/06/10 22:29:30+01:00 davej@redhat.com # [CPUFREQ] Cpufreq hotplug # From: "Pallipadi, Venkatesh" # # I was trying to fix this hotplug force migration issue in # cpu/cpufreq/acpi.c. As you suggested, it made more sense to do this in # cpufreq.c, so that we need not do this in multiple low level drivers. # How does this simple patch look. Beyond this, we may have to change some # documentation, to tell to all low level drivers that they can assume # hotplug lock will be taken, when they are in the target() routine. # # Signed-off-by: Dave Jones # # drivers/cpufreq/cpufreq.c # 2004/06/10 22:29:23+01:00 davej@redhat.com +6 -1 # [CPUFREQ] Cpufreq hotplug # From: "Pallipadi, Venkatesh" # # I was trying to fix this hotplug force migration issue in # cpu/cpufreq/acpi.c. As you suggested, it made more sense to do this in # cpufreq.c, so that we need not do this in multiple low level drivers. # How does this simple patch look. Beyond this, we may have to change some # documentation, to tell to all low level drivers that they can assume # hotplug lock will be taken, when they are in the target() routine. # # Signed-off-by: Dave Jones # # ChangeSet # 2004/06/09 20:48:50+01:00 davej@redhat.com # [CPUFREQ] Fix longhaul's debug printk. # It printed garbage. # # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/longhaul.c # 2004/06/09 20:48:43+01:00 davej@redhat.com +5 -1 # [CPUFREQ] Fix longhaul's debug printk. # It printed garbage. # # Signed-off-by: Dave Jones # # ChangeSet # 2004/06/09 20:09:04+01:00 davej@redhat.com # [CPUFREQ] Now that maxmult is a global, don't need to pass it around in longhaul driver # # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/longhaul.c # 2004/06/09 20:08:57+01:00 davej@redhat.com +5 -5 # [CPUFREQ] Now that maxmult is a global, don't need to pass it around in longhaul driver # # Signed-off-by: Dave Jones # # ChangeSet # 2004/06/09 20:01:10+01:00 davej@redhat.com # [CPUFREQ] Reset longhaul to max speed on unload. # If we don't do this, and the speed was set to the minimum, # we trigger the lowest==highest assertion on subsequent loads. # # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/longhaul.c # 2004/06/09 20:01:00+01:00 davej@redhat.com +10 -1 # [CPUFREQ] Reset longhaul to max speed on unload. # If we don't do this, and the speed was set to the minimum, # we trigger the lowest==highest assertion on subsequent loads. # # Signed-off-by: Dave Jones # diff -Nru a/Documentation/cpu-freq/amd-powernow.txt b/Documentation/cpu-freq/amd-powernow.txt --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/Documentation/cpu-freq/amd-powernow.txt 2004-06-13 23:49:33 -07:00 @@ -0,0 +1,38 @@ + +PowerNow! and Cool'n'Quiet are AMD names for frequency +management capabilities in AMD processors. As the hardware +implementation changes in new generations of the processors, +there is a different cpu-freq driver for each generation. + +Note that the driver's will not load on the "wrong" hardware, +so it is safe to try each driver in turn when in doubt as to +which is the correct driver. + +Note that the functionality to change frequency (and voltage) +is not available in all processors. The drivers will refuse +to load on processors without this capability. The capability +is detected with the cpuid instruction. + +The drivers use BIOS supplied tables to obtain frequency and +voltage information appropriate for a particular platform. +Frequency transitions will be unavailable if the BIOS does +not supply these tables. + +6th Generation: powernow-k6 + +7th Generation: powernow-k7: Athlon, Duron, Geode. + +8th Generation: powernow-k8: Athlon, Athlon 64, Opteron, Sempron. +Documentation on this functionality in 8th generation processors +is available in the "BIOS and Kernel Developer's Guide", publication +26094, in chapter 9, available for download from www.amd.com. + +BIOS supplied data, for powernow-k7 and for powernow-k8, may be +from either the PSB table or from ACPI objects. The ACPI support +is only available if the kernel config sets CONFIG_ACPI_PROCESSOR. +The powernow-k8 driver will attempt to use ACPI if so configured, +and fall back to PST if that fails. +The powernow-k7 driver will try to use the PSB support first, and +fall back to ACPI if the PSB support fails. A module parameter, +acpi_force, is provided to force ACPI support to be used instead +of PSB support. diff -Nru a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c --- a/arch/arm/mach-sa1100/cpu-sa1100.c 2004-06-13 23:49:33 -07:00 +++ b/arch/arm/mach-sa1100/cpu-sa1100.c 2004-06-13 23:49:33 -07:00 @@ -230,8 +230,9 @@ } static struct cpufreq_driver sa1100_driver = { - .flags = (CPUFREQ_PANIC_OUTOFSYNC | - CPUFREQ_PANIC_RESUME_OUTOFSYNC), + .flags = CPUFREQ_STICKY | + CPUFREQ_PANIC_OUTOFSYNC | + CPUFREQ_PANIC_RESUME_OUTOFSYNC, .verify = sa11x0_verify_speed, .target = sa1100_target, .get = sa11x0_getspeed, diff -Nru a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c --- a/arch/arm/mach-sa1100/cpu-sa1110.c 2004-06-13 23:49:33 -07:00 +++ b/arch/arm/mach-sa1100/cpu-sa1110.c 2004-06-13 23:49:33 -07:00 @@ -329,8 +329,9 @@ } static struct cpufreq_driver sa1110_driver = { - .flags = (CPUFREQ_PANIC_OUTOFSYNC | - CPUFREQ_PANIC_RESUME_OUTOFSYNC), + .flags = CPUFREQ_STICKY | + CPUFREQ_PANIC_OUTOFSYNC | + CPUFREQ_PANIC_RESUME_OUTOFSYNC, .verify = sa11x0_verify_speed, .target = sa1110_target, .get = sa11x0_getspeed, diff -Nru a/arch/i386/kernel/cpu/cpufreq/elanfreq.c b/arch/i386/kernel/cpu/cpufreq/elanfreq.c --- a/arch/i386/kernel/cpu/cpufreq/elanfreq.c 2004-06-13 23:49:33 -07:00 +++ b/arch/i386/kernel/cpu/cpufreq/elanfreq.c 2004-06-13 23:49:33 -07:00 @@ -254,6 +254,7 @@ static int __init elanfreq_setup(char *str) { max_freq = simple_strtoul(str, &str, 0); + printk(KERN_WARNING "You're using the deprecated elanfreq command line option. Use elanfreq.max_freq instead, please!\n"); return 1; } __setup("elanfreq=", elanfreq_setup); @@ -300,7 +301,7 @@ } -MODULE_PARM (max_freq, "i"); +module_param (max_freq, int, 0444); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Robert Schwebel , Sven Geggus "); diff -Nru a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c --- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c 2004-06-13 23:49:33 -07:00 +++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c 2004-06-13 23:49:33 -07:00 @@ -124,7 +124,7 @@ /* PCI bus clock - defaults to 30.000 if cpu_khz is not available */ static int pci_busclk = 0; -MODULE_PARM(pci_busclk, "i"); +module_param (pci_busclk, int, 0444); /* maximum duration for which the cpu may be suspended * (32us * MAX_DURATION). If no parameter is given, this defaults @@ -133,7 +133,7 @@ * is suspended -- processing power is just 0.39% of what it used to be, * though. 781.25 kHz(!) for a 200 MHz processor -- wow. */ static int max_duration = 255; -MODULE_PARM(max_duration, "i"); +module_param (max_duration, int, 0444); /* For the default policy, we want at least some processing power * - let's say 5%. (min = maxfreq / POLICY_MIN_DIV) diff -Nru a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c 2004-06-13 23:49:33 -07:00 +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c 2004-06-13 23:49:33 -07:00 @@ -36,6 +36,7 @@ static unsigned int numscales=16, numvscales; static unsigned int fsb; static int minvid, maxvid; +static unsigned int minmult, maxmult; static int can_scale_voltage; static int vrmrev; @@ -45,11 +46,15 @@ static void dprintk(const char *fmt, ...) { + char s[256]; va_list args; + if (debug == 0) return; + va_start(args, fmt); - printk(fmt, args); + vsprintf(s, fmt, args); + printk(s); va_end(args); } @@ -65,7 +70,7 @@ static struct cpufreq_frequency_table *longhaul_table; -static unsigned int calc_speed (int mult, int fsb) +static unsigned int calc_speed(int mult, int fsb) { int khz; khz = (mult/10)*fsb; @@ -76,7 +81,7 @@ } -static int longhaul_get_cpu_mult (void) +static int longhaul_get_cpu_mult(void) { unsigned long invalue=0,lo, hi; @@ -97,7 +102,7 @@ * Sets a new clock ratio, and -if applicable- a new Front Side Bus */ -static void longhaul_setstate (unsigned int clock_ratio_index) +static void longhaul_setstate(unsigned int clock_ratio_index) { int speed, mult; struct cpufreq_freqs freqs; @@ -193,7 +198,7 @@ #define ROUNDING 0xf -static int _guess (int guess, int maxmult) +static int _guess(int guess) { int target; @@ -206,7 +211,7 @@ } -static int guess_fsb(int maxmult) +static int guess_fsb(void) { int speed = (cpu_khz/1000); int i; @@ -216,18 +221,17 @@ speed &= ~ROUNDING; for (i=0; i<3; i++) { - if (_guess(speeds[i],maxmult) == speed) + if (_guess(speeds[i]) == speed) return speeds[i]; } return 0; } -static int __init longhaul_get_ranges (void) +static int __init longhaul_get_ranges(void) { struct cpuinfo_x86 *c = cpu_data; unsigned long invalue; - unsigned int minmult=0, maxmult=0; unsigned int multipliers[32]= { 50,30,40,100,55,35,45,95,90,70,80,60,120,75,85,65, -1,110,120,-1,135,115,125,105,130,150,160,140,-1,155,-1,145 }; @@ -248,7 +252,7 @@ if (c->x86_model==6) fsb = eblcr_fsb_table_v1[invalue]; else - fsb = guess_fsb(maxmult); + fsb = guess_fsb(); break; case 2: @@ -398,7 +402,7 @@ } -static int longhaul_target (struct cpufreq_policy *policy, +static int longhaul_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { @@ -422,7 +426,7 @@ return (calc_speed (longhaul_get_cpu_mult(), fsb)); } -static int __init longhaul_cpu_init (struct cpufreq_policy *policy) +static int __init longhaul_cpu_init(struct cpufreq_policy *policy) { struct cpuinfo_x86 *c = cpu_data; char *cpuname=NULL; @@ -536,7 +540,7 @@ .attr = longhaul_attr, }; -static int __init longhaul_init (void) +static int __init longhaul_init(void) { struct cpuinfo_x86 *c = cpu_data; @@ -553,8 +557,17 @@ return -ENODEV; } -static void __exit longhaul_exit (void) +static void __exit longhaul_exit(void) { + int i=0; + unsigned int new_clock_ratio; + + while (clock_ratio[i] != maxmult) + i++; + + new_clock_ratio = longhaul_table[i].index & 0xFF; + longhaul_setstate(new_clock_ratio); + cpufreq_unregister_driver(&longhaul_driver); kfree(longhaul_table); } diff -Nru a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c --- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c 2004-06-13 23:49:33 -07:00 +++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c 2004-06-13 23:49:33 -07:00 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -132,34 +133,28 @@ #endif /* notifiers */ - for_each_cpu(i) { - if (cpu_isset(i, affected_cpu_map)) { - freqs.cpu = i; - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - } + for_each_cpu_mask(i, affected_cpu_map) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); } /* run on each logical CPU, see section 13.15.3 of IA32 Intel Architecture Software * Developer's Manual, Volume 3 */ - for_each_cpu(i) { - if (cpu_isset(i, affected_cpu_map)) { - cpumask_t this_cpu = cpumask_of_cpu(i); + for_each_cpu_mask(i, affected_cpu_map) { + cpumask_t this_cpu = cpumask_of_cpu(i); - set_cpus_allowed(current, this_cpu); - BUG_ON(smp_processor_id() != i); + set_cpus_allowed(current, this_cpu); + BUG_ON(smp_processor_id() != i); - cpufreq_p4_setdc(i, p4clockmod_table[newstate].index); - } + cpufreq_p4_setdc(i, p4clockmod_table[newstate].index); } set_cpus_allowed(current, cpus_allowed); /* notifiers */ - for_each_cpu(i) { - if (cpu_isset(i, affected_cpu_map)) { - freqs.cpu = i; - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - } + for_each_cpu_mask(i, affected_cpu_map) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); } return 0; diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c 2004-06-13 23:49:33 -07:00 +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c 2004-06-13 23:49:33 -07:00 @@ -733,10 +733,22 @@ continue; } - /* verify only 1 entry from the lo frequency table */ - if ((fid < HI_FID_TABLE_BOTTOM) && (cntlofreq++)) { - printk(KERN_ERR PFX "Too many lo freq table entries\n"); - goto err_out_mem; + if (fid < HI_FID_TABLE_BOTTOM) { + if (cntlofreq) { + /* if both entries are the same, ignore this + * one... + */ + if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) || + (powernow_table[i].index != powernow_table[cntlofreq].index)) { + printk(KERN_ERR PFX "Too many lo freq table entries\n"); + goto err_out_mem; + } + + dprintk(KERN_INFO PFX "double low frequency table entry, ignoring it.\n"); + powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; + continue; + } else + cntlofreq = i; } if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) { @@ -857,12 +869,9 @@ if (smp_processor_id() != pol->cpu) { printk(KERN_ERR "limiting to cpu %u failed\n", pol->cpu); - goto sched_out; + goto err_out; } - /* from this point, do not exit without restoring preempt and cpu */ - preempt_disable(); - if (pending_bit_stuck()) { printk(KERN_ERR PFX "failing targ, change pending bit set\n"); goto err_out; @@ -900,8 +909,6 @@ ret = 0; err_out: - preempt_enable_no_resched(); -sched_out: set_cpus_allowed(current, oldmask); schedule(); diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c --- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c 2004-06-13 23:49:33 -07:00 +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c 2004-06-13 23:49:33 -07:00 @@ -67,28 +67,19 @@ /** * speedstep_set_state - set the SpeedStep state * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) - * @notify: whether to call cpufreq_notify_transition for CPU speed changes * * Tries to change the SpeedStep state. */ -static void speedstep_set_state (unsigned int state, unsigned int notify) +static void speedstep_set_state (unsigned int state) { u32 pmbase; u8 pm2_blk; u8 value; unsigned long flags; - struct cpufreq_freqs freqs; if (!speedstep_chipset_dev || (state > 0x1)) return; - freqs.old = speedstep_get_processor_frequency(speedstep_processor); - freqs.new = speedstep_freqs[state].frequency; - freqs.cpu = 0; /* speedstep.c is UP only driver */ - - if (notify) - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - /* get PMBASE */ pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); if (!(pmbase & 0x01)) @@ -143,9 +134,6 @@ printk (KERN_ERR "cpufreq: change failed - I/O error\n"); } - if (notify) - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - return; } @@ -252,11 +240,47 @@ unsigned int relation) { unsigned int newstate = 0; + struct cpufreq_freqs freqs; + cpumask_t cpus_allowed, affected_cpu_map; + int i; if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate)) return -EINVAL; - speedstep_set_state(newstate, 1); + /* no transition necessary */ + if (freqs.old == freqs.new) + return 0; + + freqs.old = speedstep_get_processor_frequency(speedstep_processor); + freqs.new = speedstep_freqs[newstate].frequency; + freqs.cpu = policy->cpu; + + cpus_allowed = current->cpus_allowed; + + /* only run on CPU to be set, or on its sibling */ +#ifdef CONFIG_SMP + affected_cpu_map = cpu_sibling_map[policy->cpu]; +#else + affected_cpu_map = cpumask_of_cpu(policy->cpu); +#endif + + for_each_cpu_mask(i, affected_cpu_map) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + } + + /* switch to physical CPU where state is to be changed */ + set_cpus_allowed(current, affected_cpu_map); + + speedstep_set_state(newstate); + + /* allow to be run on all CPUs */ + set_cpus_allowed(current, cpus_allowed); + + for_each_cpu_mask(i, affected_cpu_map) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } return 0; } @@ -279,21 +303,35 @@ { int result = 0; unsigned int speed; + cpumask_t cpus_allowed,affected_cpu_map; + /* capability check */ - if (policy->cpu != 0) + if (policy->cpu != 0) /* FIXME: better support for SMT in cpufreq core. Up until then, it's better to register only one CPU */ return -ENODEV; + /* only run on CPU to be set, or on its sibling */ + cpus_allowed = current->cpus_allowed; +#ifdef CONFIG_SMP + affected_cpu_map = cpu_sibling_map[policy->cpu]; +#else + affected_cpu_map = cpumask_of_cpu(policy->cpu); +#endif + set_cpus_allowed(current, affected_cpu_map); + /* detect low and high frequency */ result = speedstep_get_freqs(speedstep_processor, &speedstep_freqs[SPEEDSTEP_LOW].frequency, &speedstep_freqs[SPEEDSTEP_HIGH].frequency, &speedstep_set_state); - if (result) + if (result) { + set_cpus_allowed(current, cpus_allowed); return result; + } /* get current speed setting */ speed = speedstep_get_processor_frequency(speedstep_processor); + set_cpus_allowed(current, cpus_allowed); if (!speed) return -EIO; diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c --- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c 2004-06-13 23:49:33 -07:00 +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c 2004-06-13 23:49:33 -07:00 @@ -252,11 +252,10 @@ * specific. * M-P4-Ms may have either ebx=0xe or 0xf [see above] * M-P4/533 have either ebx=0xe or 0xf. [25317607.pdf] - * So, how to distinguish all those processors with - * ebx=0xf? I don't know. Sort them out, and wait - * for someone to complain. + * also, M-P4M HTs have ebx=0x8, too + * For now, they are distinguished by the model_id string */ - if (ebx == 0x0e) + if ((ebx == 0x0e) || (strstr(c->x86_model_id,"Mobile Intel(R) Pentium(R) 4") != NULL)) return SPEEDSTEP_PROCESSOR_P4M; break; default: @@ -321,9 +320,7 @@ unsigned int speedstep_get_freqs(unsigned int processor, unsigned int *low_speed, unsigned int *high_speed, - void (*set_state) (unsigned int state, - unsigned int notify) - ) + void (*set_state) (unsigned int state)) { unsigned int prev_speed; unsigned int ret = 0; @@ -340,7 +337,7 @@ local_irq_save(flags); /* switch to low state */ - set_state(SPEEDSTEP_LOW, 0); + set_state(SPEEDSTEP_LOW); *low_speed = speedstep_get_processor_frequency(processor); if (!*low_speed) { ret = -EIO; @@ -348,7 +345,7 @@ } /* switch to high state */ - set_state(SPEEDSTEP_HIGH, 0); + set_state(SPEEDSTEP_HIGH); *high_speed = speedstep_get_processor_frequency(processor); if (!*high_speed) { ret = -EIO; @@ -362,7 +359,7 @@ /* switch to previous state, if necessary */ if (*high_speed != prev_speed) - set_state(SPEEDSTEP_LOW, 0); + set_state(SPEEDSTEP_LOW); out: local_irq_restore(flags); diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h --- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h 2004-06-13 23:49:33 -07:00 +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h 2004-06-13 23:49:33 -07:00 @@ -44,4 +44,4 @@ extern unsigned int speedstep_get_freqs(unsigned int processor, unsigned int *low_speed, unsigned int *high_speed, - void (*set_state) (unsigned int state, unsigned int notify)); + void (*set_state) (unsigned int state)); diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c --- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c 2004-06-13 23:49:33 -07:00 +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c 2004-06-13 23:49:33 -07:00 @@ -139,37 +139,24 @@ : "a" (command), "b" (function), "c" (0), "d" (smi_port), "S" (0) ); - return state; + return (state & 1); } /** * speedstep_set_state - set the SpeedStep state * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) - * @notify: whether to call cpufreq_notify_transition * */ -static void speedstep_set_state (unsigned int state, unsigned int notify) +static void speedstep_set_state (unsigned int state) { - unsigned int old_state, result = 0, command, new_state; + unsigned int result = 0, command, new_state; unsigned long flags; - struct cpufreq_freqs freqs; unsigned int function=SET_SPEEDSTEP_STATE; unsigned int retry = 0; if (state > 0x1) return; - old_state = speedstep_get_state(); - freqs.old = speedstep_freqs[old_state].frequency; - freqs.new = speedstep_freqs[state].frequency; - freqs.cpu = 0; /* speedstep.c is UP only driver */ - - if (old_state == state) - return; - - if (notify) - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - /* Disable IRQs */ local_irq_save(flags); @@ -198,9 +185,6 @@ printk(KERN_ERR "cpufreq: change failed with new_state %u and result %u\n", new_state, result); } - if (notify) - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - return; } @@ -217,11 +201,21 @@ unsigned int target_freq, unsigned int relation) { unsigned int newstate = 0; + struct cpufreq_freqs freqs; if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate)) return -EINVAL; - speedstep_set_state(newstate, 1); + freqs.old = speedstep_freqs[speedstep_get_state()].frequency; + freqs.new = speedstep_freqs[newstate].frequency; + freqs.cpu = 0; /* speedstep.c is UP only driver */ + + if (freqs.old == freqs.new) + return 0; + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + speedstep_set_state(newstate); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); return 0; } diff -Nru a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c --- a/drivers/cpufreq/cpufreq.c 2004-06-13 23:49:33 -07:00 +++ b/drivers/cpufreq/cpufreq.c 2004-06-13 23:49:33 -07:00 @@ -722,7 +722,12 @@ unsigned int target_freq, unsigned int relation) { - return cpufreq_driver->target(policy, target_freq, relation); + int retval = -EINVAL; + lock_cpu_hotplug(); + if (cpu_online(policy->cpu)) + retval = cpufreq_driver->target(policy, target_freq, relation); + unlock_cpu_hotplug(); + return retval; } EXPORT_SYMBOL_GPL(__cpufreq_driver_target);