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 <linux@brodo.de>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# 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 <linux@brodo.de>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
# ChangeSet
#   2004/06/11 13:18:54+01:00 davej@redhat.com 
#   [CPUFREQ] Add missing include to p4-clockmod
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
# ChangeSet
#   2004/06/11 11:13:42+01:00 davej@redhat.com 
#   [CPUFREQ] small codingstyle fixes
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
# 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 <ducrot@poupinou.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# 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 <ducrot@poupinou.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# 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 <ducrot@poupinou.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# 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 <ducrot@poupinou.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# 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 <ducrot@poupinou.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
# 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 <davej@redhat.com>
#   
# 
# 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 <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
# 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 <linux@brodo.de>
#   Signed-off-by: Dave Jones <davej@redhat.com>
#    
# 
# 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 <linux@brodo.de>
#   Signed-off-by: Dave Jones <davej@redhat.com>
#    
# 
# 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 <linux@brodo.de>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# 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 <linux@brodo.de>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# 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 <linux@brodo.de>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# 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 <linux@brodo.de>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2004/06/10 22:29:30+01:00 davej@redhat.com 
#   [CPUFREQ] Cpufreq hotplug
#   From: "Pallipadi, Venkatesh" <venkatesh.pallipadi@intel.com>
#                                                                                                                                                                       
#   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 <davej@redhat.com>
# 
# drivers/cpufreq/cpufreq.c
#   2004/06/10 22:29:23+01:00 davej@redhat.com +6 -1
#   [CPUFREQ] Cpufreq hotplug
#   From: "Pallipadi, Venkatesh" <venkatesh.pallipadi@intel.com>
#                                                                                                                                                                       
#   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 <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
# 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 <davej@redhat.com>
# 
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 <r.schwebel@pengutronix.de>, Sven Geggus <sven@geggus.net>");
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 <linux/smp.h>
 #include <linux/cpufreq.h>
 #include <linux/slab.h>
+#include <linux/cpumask.h>
 
 #include <asm/processor.h> 
 #include <asm/msr.h>
@@ -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);