From 9c9a43ed2734081124407c779b36a4761c41139b Mon Sep 17 00:00:00 2001
From: Mattia Dongili <malattia@linux.it>
Date: Wed, 5 Jul 2006 23:12:20 +0200
Subject: [CPUFREQ] return error when failing to set minfreq

I just stumbled on this bug/feature, this is how to reproduce it:

# echo 450000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq
# echo 450000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
# echo powersave > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
# cpufreq-info -p
450000 450000 powersave
# echo 1800000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq ; echo $?
0
# cpufreq-info -p
450000 450000 powersave

Here it is. The kernel refuses to set a min_freq higher than the
max_freq but it allows a max_freq lower than min_freq (lowering min_freq
also).

This behaviour is pretty straightforward (but undocumented) and it
doesn't return an error altough failing to accomplish the requested
action (set min_freq).
The problem (IMO) is basically that userspace is not allowed to set a
full policy atomically while the kernel always does that thus it must
enforce an ordering on operations.

The attached patch returns -EINVAL if trying to increase frequencies
starting from scaling_min_freq and documents the correct ordering of writes.

Signed-off-by: Mattia Dongili <malattia@linux.it>
Signed-off-by: Dominik Brodowski <linux at dominikbrodowski.net>
Signed-off-by: Dave Jones <davej@redhat.com>

--
---
 Documentation/cpu-freq/user-guide.txt | 5 ++++-
 drivers/cpufreq/cpufreq.c             | 5 +++++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt
index 7fedc00c3d..555c8cf365 100644
--- a/Documentation/cpu-freq/user-guide.txt
+++ b/Documentation/cpu-freq/user-guide.txt
@@ -153,10 +153,13 @@ scaling_governor,		and by "echoing" the name of another
 				that some governors won't load - they only
 				work on some specific architectures or
 				processors.
-scaling_min_freq and 
+scaling_min_freq and
 scaling_max_freq		show the current "policy limits" (in
 				kHz). By echoing new values into these
 				files, you can change these limits.
+				NOTE: when setting a policy you need to
+				first set scaling_max_freq, then
+				scaling_min_freq.
 
 
 If you have selected the "userspace" governor which allows you to
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index bc1088d9b3..ad996c772c 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1343,6 +1343,11 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli
 
 	memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo));
 
+	if (policy->min > data->min && policy->min > policy->max) {
+		ret = -EINVAL;
+		goto error_out;
+	}
+
 	/* verify the cpu speed can be set within this limit */
 	ret = cpufreq_driver->verify(policy);
 	if (ret)
-- 
cgit v1.2.2


From dadb49d8746bc4a4b5a310dabf0c838e57a9b531 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=B3=20Bilski?= <rafalbilski@interia.pl>
Date: Mon, 3 Jul 2006 07:19:05 +0200
Subject: [CPUFREQ] Longhaul - Hook into ACPI C states.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Minimal change necessary for hardware support.

Changes in longhaul.c:
- most important - now C3 state is causing transition,
- code responsible for clearing "bus master" bit removed,
- protect bcr2 transition in the same way as longhaul.

Signed-off-by: Rafa� Bilski <rafalbilski@interia.pl>
Signed-off-by: Dave Jones <davej@redhat.com>
---
 arch/i386/kernel/cpu/cpufreq/Kconfig    |   2 +-
 arch/i386/kernel/cpu/cpufreq/longhaul.c | 194 ++++++++++++++++++--------------
 2 files changed, 109 insertions(+), 87 deletions(-)

diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig
index e44a4c6a4f..c593d73908 100644
--- a/arch/i386/kernel/cpu/cpufreq/Kconfig
+++ b/arch/i386/kernel/cpu/cpufreq/Kconfig
@@ -202,7 +202,7 @@ config X86_LONGRUN
 config X86_LONGHAUL
 	tristate "VIA Cyrix III Longhaul"
 	select CPU_FREQ_TABLE
-	depends on BROKEN
+	depends on ACPI_PROCESSOR
 	help
 	  This adds the CPUFreq driver for VIA Samuel/CyrixIII,
 	  VIA Cyrix Samuel/C3, VIA Cyrix Ezra and VIA Cyrix Ezra-T
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index 146f607e9c..d735cb4606 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -29,11 +29,13 @@
 #include <linux/cpufreq.h>
 #include <linux/slab.h>
 #include <linux/string.h>
-#include <linux/pci.h>
 
 #include <asm/msr.h>
 #include <asm/timex.h>
 #include <asm/io.h>
+#include <asm/acpi.h>
+#include <linux/acpi.h>
+#include <acpi/processor.h>
 
 #include "longhaul.h"
 
@@ -56,6 +58,8 @@ static int minvid, maxvid;
 static unsigned int minmult, maxmult;
 static int can_scale_voltage;
 static int vrmrev;
+static struct acpi_processor *pr = NULL;
+static struct acpi_processor_cx *cx = NULL;
 
 /* Module parameters */
 static int dont_scale_voltage;
@@ -118,84 +122,64 @@ static int longhaul_get_cpu_mult(void)
 	return eblcr_table[invalue];
 }
 
+/* For processor with BCR2 MSR */
 
-static void do_powersaver(union msr_longhaul *longhaul,
-			unsigned int clock_ratio_index)
+static void do_longhaul1(int cx_address, unsigned int clock_ratio_index)
 {
-	struct pci_dev *dev;
-	unsigned long flags;
-	unsigned int tmp_mask;
-	int version;
-	int i;
-	u16 pci_cmd;
-	u16 cmd_state[64];
+	union msr_bcr2 bcr2;
+	u32 t;
 
-	switch (cpu_model) {
-	case CPU_EZRA_T:
-		version = 3;
-		break;
-	case CPU_NEHEMIAH:
-		version = 0xf;
-		break;
-	default:
-		return;
-	}
+	rdmsrl(MSR_VIA_BCR2, bcr2.val);
+	/* Enable software clock multiplier */
+	bcr2.bits.ESOFTBF = 1;
+	bcr2.bits.CLOCKMUL = clock_ratio_index;
 
-	rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
-	longhaul->bits.SoftBusRatio = clock_ratio_index & 0xf;
-	longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
-	longhaul->bits.EnableSoftBusRatio = 1;
-	longhaul->bits.RevisionKey = 0;
+	/* Sync to timer tick */
+	safe_halt();
+	ACPI_FLUSH_CPU_CACHE();
+	/* Change frequency on next halt or sleep */
+	wrmsrl(MSR_VIA_BCR2, bcr2.val);
+	/* Invoke C3 */
+	inb(cx_address);
+	/* Dummy op - must do something useless after P_LVL3 read */
+	t = inl(acpi_fadt.xpm_tmr_blk.address);
+
+	/* Disable software clock multiplier */
+	local_irq_disable();
+	rdmsrl(MSR_VIA_BCR2, bcr2.val);
+	bcr2.bits.ESOFTBF = 0;
+	wrmsrl(MSR_VIA_BCR2, bcr2.val);
+}
 
-	preempt_disable();
-	local_irq_save(flags);
+/* For processor with Longhaul MSR */
 
-	/*
-	 * get current pci bus master state for all devices
-	 * and clear bus master bit
-	 */
-	dev = NULL;
-	i = 0;
-	do {
-		dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
-		if (dev != NULL) {
-			pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
-			cmd_state[i++] = pci_cmd;
-			pci_cmd &= ~PCI_COMMAND_MASTER;
-			pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
-		}
-	} while (dev != NULL);
+static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
+{
+	union msr_longhaul longhaul;
+	u32 t;
 
-	tmp_mask=inb(0x21);	/* works on C3. save mask. */
-	outb(0xFE,0x21);	/* TMR0 only */
-	outb(0xFF,0x80);	/* delay */
+	rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+	longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
+	longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
+	longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
 
+	/* Sync to timer tick */
 	safe_halt();
-	wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
-	halt();
-
+	ACPI_FLUSH_CPU_CACHE();
+	/* Change frequency on next halt or sleep */
+	wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+	/* Invoke C3 */
+	inb(cx_address);
+	/* Dummy op - must do something useless after P_LVL3 read */
+	t = inl(acpi_fadt.xpm_tmr_blk.address);
+
+	/* Disable bus ratio bit */
 	local_irq_disable();
-
-	outb(tmp_mask,0x21);	/* restore mask */
-
-	/* restore pci bus master state for all devices */
-	dev = NULL;
-	i = 0;
-	do {
-		dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
-		if (dev != NULL) {
-			pci_cmd = cmd_state[i++];
-			pci_write_config_byte(dev, PCI_COMMAND, pci_cmd);
-		}
-	} while (dev != NULL);
-	local_irq_restore(flags);
-	preempt_enable();
-
-	/* disable bus ratio bit */
-	rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
-	longhaul->bits.EnableSoftBusRatio = 0;
-	longhaul->bits.RevisionKey = version;
-	wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
+	longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
+	longhaul.bits.EnableSoftBusRatio = 0;
+	longhaul.bits.EnableSoftBSEL = 0;
+	longhaul.bits.EnableSoftVID = 0;
+	wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
 }
 
 /**
@@ -209,9 +193,9 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
 {
 	int speed, mult;
 	struct cpufreq_freqs freqs;
-	union msr_longhaul longhaul;
-	union msr_bcr2 bcr2;
 	static unsigned int old_ratio=-1;
+	unsigned long flags;
+	unsigned int pic1_mask, pic2_mask;
 
 	if (old_ratio == clock_ratio_index)
 		return;
@@ -234,6 +218,20 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
 	dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
 			fsb, mult/10, mult%10, print_speed(speed/1000));
 
+	preempt_disable();
+	local_irq_save(flags);
+
+	pic2_mask = inb(0xA1);
+	pic1_mask = inb(0x21);	/* works on C3. save mask. */
+	outb(0xFF,0xA1);	/* Overkill */
+	outb(0xFE,0x21);	/* TMR0 only */
+
+	/* Disable bus master arbitration */
+	if (pr->flags.bm_check) {
+		acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1,
+				  ACPI_MTX_DO_NOT_LOCK);
+	}
+
 	switch (longhaul_version) {
 
 	/*
@@ -245,20 +243,7 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
 	 */
 	case TYPE_LONGHAUL_V1:
 	case TYPE_LONGHAUL_V2:
-		rdmsrl (MSR_VIA_BCR2, bcr2.val);
-		/* Enable software clock multiplier */
-		bcr2.bits.ESOFTBF = 1;
-		bcr2.bits.CLOCKMUL = clock_ratio_index;
-		local_irq_disable();
-		wrmsrl (MSR_VIA_BCR2, bcr2.val);
-		safe_halt();
-
-		/* Disable software clock multiplier */
-		rdmsrl (MSR_VIA_BCR2, bcr2.val);
-		bcr2.bits.ESOFTBF = 0;
-		local_irq_disable();
-		wrmsrl (MSR_VIA_BCR2, bcr2.val);
-		local_irq_enable();
+		do_longhaul1(cx->address, clock_ratio_index);
 		break;
 
 	/*
@@ -273,10 +258,22 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
 	 * to work in practice.
 	 */
 	case TYPE_POWERSAVER:
-		do_powersaver(&longhaul, clock_ratio_index);
+		do_powersaver(cx->address, clock_ratio_index);
 		break;
 	}
 
+	/* Enable bus master arbitration */
+	if (pr->flags.bm_check) {
+		acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0,
+				  ACPI_MTX_DO_NOT_LOCK);
+	}
+
+	outb(pic2_mask,0xA1);	/* restore mask */
+	outb(pic1_mask,0x21);
+
+	local_irq_restore(flags);
+	preempt_enable();
+
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 }
 
@@ -527,6 +524,18 @@ static unsigned int longhaul_get(unsigned int cpu)
 	return calc_speed(longhaul_get_cpu_mult());
 }
 
+acpi_status longhaul_walk_callback(acpi_handle obj_handle,
+				  u32 nesting_level,
+				  void *context, void **return_value)
+{
+	struct acpi_device *d;
+
+	if ( acpi_bus_get_device(obj_handle, &d) ) {
+		return 0;
+	}
+	*return_value = (void *)acpi_driver_data(d);
+	return 1;
+}
 
 static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
 {
@@ -534,6 +543,15 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
 	char *cpuname=NULL;
 	int ret;
 
+	/* Check ACPI support for C3 state */
+	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+			 &longhaul_walk_callback, NULL, (void *)&pr);
+	if (pr == NULL) goto err_acpi;
+
+	cx = &pr->power.states[ACPI_STATE_C3];
+	if (cx == NULL || cx->latency > 1000) goto err_acpi;
+
+	/* Now check what we have on this motherboard */
 	switch (c->x86_model) {
 	case 6:
 		cpu_model = CPU_SAMUEL;
@@ -634,6 +652,10 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
 	cpufreq_frequency_table_get_attr(longhaul_table, policy->cpu);
 
 	return 0;
+
+err_acpi:
+	printk(KERN_ERR PFX "No ACPI support for CPU frequency changes.\n");
+	return -ENODEV;
 }
 
 static int __devexit longhaul_cpu_exit(struct cpufreq_policy *policy)
-- 
cgit v1.2.2


From 48b7bde0f6d5fd08d046b583cfa0118ad74c6caf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=B3=20Bilski?= <rafalbilski@interia.pl>
Date: Tue, 4 Jul 2006 17:50:57 +0200
Subject: [CPUFREQ] Longhaul - Workaround issues with APIC.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

There is no need to worry about local APIC.
There is need to worry about I/O APIC, because I/O APIC
is replacing good old 8259. According to Nehemiah datasheet VIA is
using 3-wire bus to connect local APIC to I/O APIC.

"[...] When IA32_APIC_BASE[11] is set to 0, processor APICs based on the 3-wire APIC
 bus cannot be generally re-enabled until a system hardware reset. The 3-wire bus
 looses track of arbitration that would be necessary for complete re-enabling. Certain
 (local) APIC functionality can be enabled. [...]"

So we must set disable bit for each interrupt in I/O APIC registers.
Same situation as for PIC - we must poke registers direcly.
How to do this? I don't know. So at the moment it is better to fail.

Signed-off-by: Rafa� Bilski <rafalbilski@interia.pl>
Signed-off-by: Dave Jones <davej@redhat.com>
---
 arch/i386/kernel/cpu/cpufreq/longhaul.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index d735cb4606..dfd243f497 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -688,6 +688,18 @@ static int __init longhaul_init(void)
 	if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6)
 		return -ENODEV;
 
+#ifdef CONFIG_SMP
+	if (num_online_cpus() > 1) {
+		return -ENODEV;
+		printk(KERN_ERR PFX "More than 1 CPU detected, longhaul disabled.\n");
+	}
+#endif
+#ifdef CONFIG_X86_IO_APIC
+	if (cpu_has_apic) {
+		printk(KERN_ERR PFX "APIC detected. Longhaul is currently broken in this configuration.\n");
+		return -ENODEV;
+	}
+#endif
 	switch (c->x86_model) {
 	case 6 ... 9:
 		return cpufreq_register_driver(&longhaul_driver);
-- 
cgit v1.2.2


From 0d6daba5faed26a2f50a40adf5d4674a9a54717e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=B3=20Bilski?= <rafalbilski@interia.pl>
Date: Fri, 7 Jul 2006 08:48:26 +0200
Subject: [CPUFREQ] Longhaul - Initialise later.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Without this longhaul will always fail when compiled into kernel,
as it needs to initialise after the ACPI processor module.

I lost this when I was splitting patches. Sorry.

Signed-off-by: Rafa� Bilski <rafalbilski@interia.pl>
Signed-off-by: Dave Jones <davej@redhat.com>
---
 arch/i386/kernel/cpu/cpufreq/longhaul.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index dfd243f497..7388fc3239 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -733,6 +733,6 @@ MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
 MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");
 MODULE_LICENSE ("GPL");
 
-module_init(longhaul_init);
+late_initcall(longhaul_init);
 module_exit(longhaul_exit);
 
-- 
cgit v1.2.2


From 95a53249db330a3f08090611fdb5fe168a73e650 Mon Sep 17 00:00:00 2001
From: Adrian Bunk <bunk@stusta.de>
Date: Sat, 8 Jul 2006 22:20:26 +0200
Subject: [CPUFREQ] X86_GX_SUSPMOD must depend on PCI
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

It seems commit 32ee8c3e470d86588b51dc42ed01e85c5fa0f180 accidentially
reverted cdc9cc1d740ffc3d8d8207fbf5df9bf05fcc9955, IOW, it reintroduced
the following compile error with CONFIG_PCI=n:

<--  snip  -->

...
  CC      arch/i386/kernel/cpu/cpufreq/gx-suspmod.o
arch/i386/kernel/cpu/cpufreq/gx-suspmod.c: In function ‘gx_detect_chipset’:
arch/i386/kernel/cpu/cpufreq/gx-suspmod.c:193: error: implicit declaration of function ‘pci_match_id’
arch/i386/kernel/cpu/cpufreq/gx-suspmod.c:193: warning: comparison between pointer and integer
make[3]: *** [arch/i386/kernel/cpu/cpufreq/gx-suspmod.o] Error 1

<--  snip  -->

This patch therefore re-adds the dependency of X86_GX_SUSPMOD on PCI.

Signed-off-by: Adrian Bunk <bunk@stusta.de>
Signed-off-by: Dave Jones <davej@redhat.com>
---
 arch/i386/kernel/cpu/cpufreq/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig
index c593d73908..ccc1edff5c 100644
--- a/arch/i386/kernel/cpu/cpufreq/Kconfig
+++ b/arch/i386/kernel/cpu/cpufreq/Kconfig
@@ -96,6 +96,7 @@ config X86_POWERNOW_K8_ACPI
 
 config X86_GX_SUSPMOD
 	tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation"
+	depends on PCI
 	help
 	 This add the CPUFreq driver for NatSemi Geode processors which
 	 support suspend modulation.
-- 
cgit v1.2.2


From c4a96c1eba206bd4a58a0f2acf2450126bd2b5da Mon Sep 17 00:00:00 2001
From: Adrian Bunk <bunk@stusta.de>
Date: Sun, 9 Jul 2006 19:53:08 +0200
Subject: [CPUFREQ] Make longhaul_walk_callback() static

This patch makes the needlessly global longhaul_walk_callback() static.

Signed-off-by: Adrian Bunk <bunk@stusta.de>
Signed-off-by: Dave Jones <davej@redhat.com>
---
 arch/i386/kernel/cpu/cpufreq/longhaul.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index 7388fc3239..3cfa074186 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -524,9 +524,9 @@ static unsigned int longhaul_get(unsigned int cpu)
 	return calc_speed(longhaul_get_cpu_mult());
 }
 
-acpi_status longhaul_walk_callback(acpi_handle obj_handle,
-				  u32 nesting_level,
-				  void *context, void **return_value)
+static acpi_status longhaul_walk_callback(acpi_handle obj_handle,
+					  u32 nesting_level,
+					  void *context, void **return_value)
 {
 	struct acpi_device *d;
 
-- 
cgit v1.2.2


From eb23c751d837848c87fda6b1347d194f6b333681 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=B3=20Bilski?= <rafalbilski@interia.pl>
Date: Sun, 9 Jul 2006 21:47:04 +0200
Subject: [CPUFREQ] Longhaul - Readd accidentally dropped line
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

I lost very important line in do_powersaver

Signed-off-by: Rafa� Bilski <rafalbilski@interia.pl>
Signed-off-by: Dave Jones <davej@redhat.com>
---
 arch/i386/kernel/cpu/cpufreq/longhaul.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index 3cfa074186..fdf8a6424f 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -162,6 +162,7 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
 	longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
 	longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
 	longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
+	longhaul.bits.EnableSoftBusRatio = 1;
 
 	/* Sync to timer tick */
 	safe_halt();
-- 
cgit v1.2.2


From 9fb31c3a1d9f42e10e541ee0e2be8d1f27115141 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=B3=20Bilski?= <rafalbilski@interia.pl>
Date: Thu, 13 Jul 2006 19:26:10 +0200
Subject: [CPUFREQ] Longhaul - Fix power state test to do something more useful
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This is changing "always true" test to something usefull.

Signed-off-by: Rafa� Bilski <rafalbilski@interia.pl>
Signed-off-by: Dave Jones <davej@redhat.com>
---
 arch/i386/kernel/cpu/cpufreq/longhaul.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index fdf8a6424f..ccd1f2c39e 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -550,7 +550,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
 	if (pr == NULL) goto err_acpi;
 
 	cx = &pr->power.states[ACPI_STATE_C3];
-	if (cx == NULL || cx->latency > 1000) goto err_acpi;
+	if (cx->address == 0 || cx->latency > 1000) goto err_acpi;
 
 	/* Now check what we have on this motherboard */
 	switch (c->x86_model) {
-- 
cgit v1.2.2


From 32deb2d5c4c291d7d9a73198dc357a151e4b978c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=B3=20Bilski?= <rafalbilski@interia.pl>
Date: Sat, 15 Jul 2006 19:31:30 +0200
Subject: [CPUFREQ] Longhaul - Rename & fix multipliers table
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This table is only used by Ezra-T CPUs currently, and has values
for some other CPU. Fix them to match the values used by that CPU,
and for now make it clearer by renaming the variable.

Signed-off-by: Rafa� Bilski <rafalbilski@interia.pl>
Signed-off-by: Dave Jones <davej@redhat.com>
---
 arch/i386/kernel/cpu/cpufreq/longhaul.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index ccd1f2c39e..4f2c3aeef7 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -322,9 +322,11 @@ static int guess_fsb(void)
 static int __init longhaul_get_ranges(void)
 {
 	unsigned long invalue;
-	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 };
+	unsigned int ezra_t_multipliers[32]= {
+			90,  30,  40, 100,  55,  35,  45,  95,
+			50,  70,  80,  60, 120,  75,  85,  65,
+			-1, 110, 120,  -1, 135, 115, 125, 105,
+			130, 150, 160, 140,  -1, 155,  -1, 145 };
 	unsigned int j, k = 0;
 	union msr_longhaul longhaul;
 	unsigned long lo, hi;
@@ -353,13 +355,13 @@ static int __init longhaul_get_ranges(void)
 			invalue = longhaul.bits.MaxMHzBR;
 			if (longhaul.bits.MaxMHzBR4)
 				invalue += 16;
-			maxmult=multipliers[invalue];
+			maxmult=ezra_t_multipliers[invalue];
 
 			invalue = longhaul.bits.MinMHzBR;
 			if (longhaul.bits.MinMHzBR4 == 1)
 				minmult = 30;
 			else
-				minmult = multipliers[invalue];
+				minmult = ezra_t_multipliers[invalue];
 			fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
 			break;
 		}
-- 
cgit v1.2.2


From 3bcb09a35641f2840bd59d8f82154f830dca282c Mon Sep 17 00:00:00 2001
From: Jeremy Fitzhardinge <jeremy@goop.org>
Date: Thu, 6 Jul 2006 12:30:26 -0700
Subject: [CPUFREQ] [1/2] add __find_governor helper and clean up some error
 handling.

Adds a __find_governor() helper function to look up a governor by
name.  Also restructures some error handling to conform to the
"single-exit" model which is generally preferred for kernel code.

Signed-off-by: Jeremy Fitzhardinge <jeremy@goop.org>
Signed-off-by: Dave Jones <davej@redhat.com>
---
 drivers/cpufreq/cpufreq.c | 57 ++++++++++++++++++++++++++++-------------------
 1 file changed, 34 insertions(+), 23 deletions(-)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index ad996c772c..9b416372a8 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -284,39 +284,52 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
  *                          SYSFS INTERFACE                          *
  *********************************************************************/
 
+static struct cpufreq_governor *__find_governor(const char *str_governor)
+{
+	struct cpufreq_governor *t;
+
+	list_for_each_entry(t, &cpufreq_governor_list, governor_list)
+		if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN))
+			return t;
+
+	return NULL;
+}
+
 /**
  * cpufreq_parse_governor - parse a governor string
  */
 static int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
 				struct cpufreq_governor **governor)
 {
+	int err = -EINVAL;
+
 	if (!cpufreq_driver)
-		return -EINVAL;
+		goto out;
+
 	if (cpufreq_driver->setpolicy) {
 		if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
 			*policy = CPUFREQ_POLICY_PERFORMANCE;
-			return 0;
+			err = 0;
 		} else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
 			*policy = CPUFREQ_POLICY_POWERSAVE;
-			return 0;
+			err = 0;
 		}
-		return -EINVAL;
-	} else {
+	} else if (cpufreq_driver->target) {
 		struct cpufreq_governor *t;
+
 		mutex_lock(&cpufreq_governor_mutex);
-		if (!cpufreq_driver || !cpufreq_driver->target)
-			goto out;
-		list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
-			if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) {
-				*governor = t;
-				mutex_unlock(&cpufreq_governor_mutex);
-				return 0;
-			}
+
+		t = __find_governor(str_governor);
+
+		if (t != NULL) {
+			*governor = t;
+			err = 0;
 		}
-out:
+
 		mutex_unlock(&cpufreq_governor_mutex);
 	}
-	return -EINVAL;
+  out:
+	return err;
 }
 
 
@@ -1265,23 +1278,21 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
 
 int cpufreq_register_governor(struct cpufreq_governor *governor)
 {
-	struct cpufreq_governor *t;
+	int err;
 
 	if (!governor)
 		return -EINVAL;
 
 	mutex_lock(&cpufreq_governor_mutex);
 
-	list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
-		if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) {
-			mutex_unlock(&cpufreq_governor_mutex);
-			return -EBUSY;
-		}
+	err = -EBUSY;
+	if (__find_governor(governor->name) == NULL) {
+		err = 0;
+		list_add(&governor->governor_list, &cpufreq_governor_list);
 	}
-	list_add(&governor->governor_list, &cpufreq_governor_list);
 
 	mutex_unlock(&cpufreq_governor_mutex);
-	return 0;
+	return err;
 }
 EXPORT_SYMBOL_GPL(cpufreq_register_governor);
 
-- 
cgit v1.2.2


From ea71497020c55cd39221e0abad5c1752ac6e3f47 Mon Sep 17 00:00:00 2001
From: Jeremy Fitzhardinge <jeremy@goop.org>
Date: Thu, 6 Jul 2006 12:32:01 -0700
Subject: [CPUFREQ] [2/2] demand load governor modules.

Demand-load cpufreq governor modules if needed.

Signed-off-by: Jeremy Fitzhardinge <jeremy@goop.org>
Signed-off-by: Dave Jones <davej@redhat.com>
---
 drivers/cpufreq/cpufreq.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 9b416372a8..b3df613ae4 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -321,6 +321,23 @@ static int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
 
 		t = __find_governor(str_governor);
 
+		if (t == NULL) {
+			char *name = kasprintf(GFP_KERNEL, "cpufreq_%s", str_governor);
+
+			if (name) {
+				int ret;
+
+				mutex_unlock(&cpufreq_governor_mutex);
+				ret = request_module(name);
+				mutex_lock(&cpufreq_governor_mutex);
+
+				if (ret == 0)
+					t = __find_governor(str_governor);
+			}
+
+			kfree(name);
+		}
+
 		if (t != NULL) {
 			*governor = t;
 			err = 0;
-- 
cgit v1.2.2


From 12e704db809cd4101b7d3594fc9a96f30fe88a31 Mon Sep 17 00:00:00 2001
From: bert hubert <bert.hubert@netherlabs.nl>
Date: Sun, 30 Jul 2006 21:19:32 +0200
Subject: [CPUFREQ] Propagate acpi_processor_preregister_performance return
 value.

Note how any error from acpi_processor_preregister_performance is ignored.

From: bert hubert <bert.hubert@netherlabs.nl>
Signed-off-by: Dave Jones <davej@redhat.com>
---
 arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
index 567b39bea0..efb41e8135 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -384,8 +384,7 @@ static int acpi_cpufreq_early_init_acpi(void)
 	}
 
 	/* Do initialization in ACPI core */
-	acpi_processor_preregister_performance(acpi_perf_data);
-	return 0;
+	return acpi_processor_preregister_performance(acpi_perf_data);
 }
 
 static int
-- 
cgit v1.2.2