All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Longhaul - Disable arbiter
@ 2006-08-01  5:51 Rafał Bilski
  0 siblings, 0 replies; 5+ messages in thread
From: Rafał Bilski @ 2006-08-01  5:51 UTC (permalink / raw)
  To: Dave Jones; +Cc: cpufreq

ACPI C3 works for "Powersaver" processors, so use it 
only for them.

Older CPU will change frequency on "halt" only. But we 
can protect transition in two ways:
- by ACPI PM2 register, there is "bus master arbiter 
  disable" bit. This isn't tested because VIA mainboards 
  don't have PM2 register,
- by PLE133 PCI/AGP arbiter disable register. There 
  are two bits in this register. First is "PCI arbiter 
  disable", second "AGP arbiter disable". This is 
  working on VIA Epia 800 mainboards.

Test on bm_control is more proper because this is true 
when PM2 register exist.

Signed-off-by: Rafa³ Bilski <rafalbilski@interia.pl>

---

diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -27,6 +27,7 @@ #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/cpufreq.h>
+#include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 
@@ -60,6 +61,7 @@ static int can_scale_voltage;
 static int vrmrev;
 static struct acpi_processor *pr = NULL;
 static struct acpi_processor_cx *cx = NULL;
+static int port22_en = 0;
 
 /* Module parameters */
 static int dont_scale_voltage;
@@ -124,10 +126,9 @@ static int longhaul_get_cpu_mult(void)
 
 /* For processor with BCR2 MSR */
 
-static void do_longhaul1(int cx_address, unsigned int clock_ratio_index)
+static void do_longhaul1(unsigned int clock_ratio_index)
 {
 	union msr_bcr2 bcr2;
-	u32 t;
 
 	rdmsrl(MSR_VIA_BCR2, bcr2.val);
 	/* Enable software clock multiplier */
@@ -136,13 +137,11 @@ static void do_longhaul1(int cx_address,
 
 	/* 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);
+	/* Invoke transition */
+	ACPI_FLUSH_CPU_CACHE();
+	halt();
 
 	/* Disable software clock multiplier */
 	local_irq_disable();
@@ -166,9 +165,9 @@ static void do_powersaver(int cx_address
 
 	/* Sync to timer tick */
 	safe_halt();
-	ACPI_FLUSH_CPU_CACHE();
 	/* Change frequency on next halt or sleep */
 	wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+	ACPI_FLUSH_CPU_CACHE();
 	/* Invoke C3 */
 	inb(cx_address);
 	/* Dummy op - must do something useless after P_LVL3 read */
@@ -227,10 +226,13 @@ static void longhaul_setstate(unsigned i
 	outb(0xFF,0xA1);	/* Overkill */
 	outb(0xFE,0x21);	/* TMR0 only */
 
-	/* Disable bus master arbitration */
-	if (pr->flags.bm_check) {
+	if (pr->flags.bm_control) {
+ 		/* Disable bus master arbitration */
 		acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1,
 				  ACPI_MTX_DO_NOT_LOCK);
+	} else if (port22_en) {
+		/* Disable AGP and PCI arbiters */
+		outb(3, 0x22);
 	}
 
 	switch (longhaul_version) {
@@ -244,7 +246,7 @@ static void longhaul_setstate(unsigned i
 	 */
 	case TYPE_LONGHAUL_V1:
 	case TYPE_LONGHAUL_V2:
-		do_longhaul1(cx->address, clock_ratio_index);
+		do_longhaul1(clock_ratio_index);
 		break;
 
 	/*
@@ -259,14 +261,20 @@ static void longhaul_setstate(unsigned i
 	 * to work in practice.
 	 */
 	case TYPE_POWERSAVER:
+		/* Don't allow wakeup */
+		acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0,
+				  ACPI_MTX_DO_NOT_LOCK);
 		do_powersaver(cx->address, clock_ratio_index);
 		break;
 	}
 
-	/* Enable bus master arbitration */
-	if (pr->flags.bm_check) {
+	if (pr->flags.bm_control) {
+		/* Enable bus master arbitration */
 		acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0,
 				  ACPI_MTX_DO_NOT_LOCK);
+	} else if (port22_en) {
+		/* Enable arbiters */
+		outb(0, 0x22);
 	}
 
 	outb(pic2_mask,0xA1);	/* restore mask */
@@ -540,21 +548,33 @@ static acpi_status longhaul_walk_callbac
 	return 1;
 }
 
+/* VIA don't support PM2 reg, but have something similar */
+static int enable_arbiter_disable(void)
+{
+	struct pci_dev *dev;
+	u8 pci_cmd;
+
+	/* Find PLE133 host bridge */
+	dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0, NULL);
+	if (dev != NULL) {
+		/* Enable access to port 0x22 */
+		pci_read_config_byte(dev, 0x78, &pci_cmd);
+		if ( !(pci_cmd & 1<<7) ) {
+			pci_cmd |= 1<<7;
+			pci_write_config_byte(dev, 0x78, pci_cmd);
+		}
+		return 1;
+	}
+	return 0;
+}
+
 static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
 {
 	struct cpuinfo_x86 *c = cpu_data;
 	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->address == 0 || cx->latency > 1000) goto err_acpi;
-
-	/* Now check what we have on this motherboard */
+	/* Check what we have on this motherboard */
 	switch (c->x86_model) {
 	case 6:
 		cpu_model = CPU_SAMUEL;
@@ -636,6 +656,26 @@ static int __init longhaul_cpu_init(stru
 		break;
 	};
 
+	/* Find ACPI data for processor */
+	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+			    &longhaul_walk_callback, NULL, (void *)&pr);
+	if (pr == NULL) goto err_acpi;
+
+	if (longhaul_version == TYPE_POWERSAVER) {
+		/* Check ACPI support for C3 state */
+		cx = &pr->power.states[ACPI_STATE_C3];
+		if (cx->address == 0 || cx->latency > 1000) goto err_acpi;
+	} else {
+		/* Check ACPI support for bus master arbiter disable */
+		if (!pr->flags.bm_control) {
+			if ( !enable_arbiter_disable() ) {
+				printk(KERN_ERR PFX "No ACPI support. No VT8601 host bridge. Aborting.\n");
+		    		return -ENODEV;
+			} else
+				port22_en = 1;
+		}
+	}
+
 	ret = longhaul_get_ranges();
 	if (ret != 0)
 		return ret;



------------------------------------------------------------------------
Szybko i tanio ubezpiecz samochod! 
Kupno polisy zajmie Ci 15 minut! Kontakt przez telefon albo Internet. 
Kliknij i sprawdz: http://link.interia.pl/f198b

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH] Longhaul - Disable arbiter
@ 2006-08-08 17:12 Rafał Bilski
  2006-08-08 19:58 ` Dave Jones
  0 siblings, 1 reply; 5+ messages in thread
From: Rafał Bilski @ 2006-08-08 17:12 UTC (permalink / raw)
  To: Dave Jones; +Cc: cpufreq

ACPI C3 works for "Powersaver" processors, so use it 
only for them.

Older CPU will change frequency on "halt" only. But we 
can protect transition in two ways:
- by ACPI PM2 register, there is "bus master arbiter 
  disable" bit. This isn't tested because VIA mainboards 
  don't have PM2 register,
- by PLE133 PCI/AGP arbiter disable register. There 
  are two bits in this register. First is "PCI arbiter 
  disable", second "AGP arbiter disable". This is 
  working on VIA Epia 800 mainboards.

Test on bm_control is more proper because this is true 
when PM2 register exist.

Signed-off-by: Rafa³ Bilski <rafalbilski@interia.pl>

---

diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -27,6 +27,7 @@ #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/cpufreq.h>
+#include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 
@@ -60,6 +61,7 @@ static int can_scale_voltage;
 static int vrmrev;
 static struct acpi_processor *pr = NULL;
 static struct acpi_processor_cx *cx = NULL;
+static int port22_en = 0;
 
 /* Module parameters */
 static int dont_scale_voltage;
@@ -124,10 +126,9 @@ static int longhaul_get_cpu_mult(void)
 
 /* For processor with BCR2 MSR */
 
-static void do_longhaul1(int cx_address, unsigned int clock_ratio_index)
+static void do_longhaul1(unsigned int clock_ratio_index)
 {
 	union msr_bcr2 bcr2;
-	u32 t;
 
 	rdmsrl(MSR_VIA_BCR2, bcr2.val);
 	/* Enable software clock multiplier */
@@ -136,13 +137,11 @@ static void do_longhaul1(int cx_address,
 
 	/* 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);
+	/* Invoke transition */
+	ACPI_FLUSH_CPU_CACHE();
+	halt();
 
 	/* Disable software clock multiplier */
 	local_irq_disable();
@@ -166,9 +165,9 @@ static void do_powersaver(int cx_address
 
 	/* Sync to timer tick */
 	safe_halt();
-	ACPI_FLUSH_CPU_CACHE();
 	/* Change frequency on next halt or sleep */
 	wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+	ACPI_FLUSH_CPU_CACHE();
 	/* Invoke C3 */
 	inb(cx_address);
 	/* Dummy op - must do something useless after P_LVL3 read */
@@ -227,10 +226,13 @@ static void longhaul_setstate(unsigned i
 	outb(0xFF,0xA1);	/* Overkill */
 	outb(0xFE,0x21);	/* TMR0 only */
 
-	/* Disable bus master arbitration */
-	if (pr->flags.bm_check) {
+	if (pr->flags.bm_control) {
+ 		/* Disable bus master arbitration */
 		acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1,
 				  ACPI_MTX_DO_NOT_LOCK);
+	} else if (port22_en) {
+		/* Disable AGP and PCI arbiters */
+		outb(3, 0x22);
 	}
 
 	switch (longhaul_version) {
@@ -244,7 +246,7 @@ static void longhaul_setstate(unsigned i
 	 */
 	case TYPE_LONGHAUL_V1:
 	case TYPE_LONGHAUL_V2:
-		do_longhaul1(cx->address, clock_ratio_index);
+		do_longhaul1(clock_ratio_index);
 		break;
 
 	/*
@@ -259,14 +261,20 @@ static void longhaul_setstate(unsigned i
 	 * to work in practice.
 	 */
 	case TYPE_POWERSAVER:
+		/* Don't allow wakeup */
+		acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0,
+				  ACPI_MTX_DO_NOT_LOCK);
 		do_powersaver(cx->address, clock_ratio_index);
 		break;
 	}
 
-	/* Enable bus master arbitration */
-	if (pr->flags.bm_check) {
+	if (pr->flags.bm_control) {
+		/* Enable bus master arbitration */
 		acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0,
 				  ACPI_MTX_DO_NOT_LOCK);
+	} else if (port22_en) {
+		/* Enable arbiters */
+		outb(0, 0x22);
 	}
 
 	outb(pic2_mask,0xA1);	/* restore mask */
@@ -540,21 +548,33 @@ static acpi_status longhaul_walk_callbac
 	return 1;
 }
 
+/* VIA don't support PM2 reg, but have something similar */
+static int enable_arbiter_disable(void)
+{
+	struct pci_dev *dev;
+	u8 pci_cmd;
+
+	/* Find PLE133 host bridge */
+	dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0, NULL);
+	if (dev != NULL) {
+		/* Enable access to port 0x22 */
+		pci_read_config_byte(dev, 0x78, &pci_cmd);
+		if ( !(pci_cmd & 1<<7) ) {
+			pci_cmd |= 1<<7;
+			pci_write_config_byte(dev, 0x78, pci_cmd);
+		}
+		return 1;
+	}
+	return 0;
+}
+
 static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
 {
 	struct cpuinfo_x86 *c = cpu_data;
 	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->address == 0 || cx->latency > 1000) goto err_acpi;
-
-	/* Now check what we have on this motherboard */
+	/* Check what we have on this motherboard */
 	switch (c->x86_model) {
 	case 6:
 		cpu_model = CPU_SAMUEL;
@@ -636,6 +656,26 @@ static int __init longhaul_cpu_init(stru
 		break;
 	};
 
+	/* Find ACPI data for processor */
+	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+			    &longhaul_walk_callback, NULL, (void *)&pr);
+	if (pr == NULL) goto err_acpi;
+
+	if (longhaul_version == TYPE_POWERSAVER) {
+		/* Check ACPI support for C3 state */
+		cx = &pr->power.states[ACPI_STATE_C3];
+		if (cx->address == 0 || cx->latency > 1000) goto err_acpi;
+	} else {
+		/* Check ACPI support for bus master arbiter disable */
+		if (!pr->flags.bm_control) {
+			if ( !enable_arbiter_disable() ) {
+				printk(KERN_ERR PFX "No ACPI support. No VT8601 host bridge. Aborting.\n");
+		    		return -ENODEV;
+			} else
+				port22_en = 1;
+		}
+	}
+
 	ret = longhaul_get_ranges();
 	if (ret != 0)
 		return ret;




----------------------------------------------------------------------
PS. Fajny portal... >>> http://link.interia.pl/f196a

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Longhaul - Disable arbiter
  2006-08-08 17:12 Rafał Bilski
@ 2006-08-08 19:58 ` Dave Jones
  2006-08-08 20:57   ` Rafał Bilski
  0 siblings, 1 reply; 5+ messages in thread
From: Dave Jones @ 2006-08-08 19:58 UTC (permalink / raw)
  To: Rafał Bilski; +Cc: cpufreq

On Tue, Aug 08, 2006 at 07:12:20PM +0200, Rafał Bilski wrote:
 > ACPI C3 works for "Powersaver" processors, so use it 
 > only for them.
 > 
 > Older CPU will change frequency on "halt" only. But we 
 > can protect transition in two ways:
 > - by ACPI PM2 register, there is "bus master arbiter 
 >   disable" bit. This isn't tested because VIA mainboards 
 >   don't have PM2 register,
 > - by PLE133 PCI/AGP arbiter disable register. There 
 >   are two bits in this register. First is "PCI arbiter 
 >   disable", second "AGP arbiter disable". This is 
 >   working on VIA Epia 800 mainboards.

The only part about this I don't like is that we now need to add
code to do similar things on every possible VIA chipset that
could take a C3, and there's quite a few of them, and until
we have good coverage...

 >  
 > +	/* Find ACPI data for processor */
 > +	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
 > +			    &longhaul_walk_callback, NULL, (void *)&pr);
 > +	if (pr == NULL) goto err_acpi;
 > +
 > +	if (longhaul_version == TYPE_POWERSAVER) {
 > +		/* Check ACPI support for C3 state */
 > +		cx = &pr->power.states[ACPI_STATE_C3];
 > +		if (cx->address == 0 || cx->latency > 1000) goto err_acpi;
 > +	} else {
 > +		/* Check ACPI support for bus master arbiter disable */
 > +		if (!pr->flags.bm_control) {
 > +			if ( !enable_arbiter_disable() ) {
 > +				printk(KERN_ERR PFX "No ACPI support. No VT8601 host bridge. Aborting.\n");
 > +		    		return -ENODEV;
 > +			} else
 > +				port22_en = 1;
 > +		}
 > +	}

We're going to -ENODEV, possibly breaking some setups that it might actually
already work on (even if only by chance).

		Dave

-- 
http://www.codemonkey.org.uk

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Longhaul - Disable arbiter
  2006-08-08 19:58 ` Dave Jones
@ 2006-08-08 20:57   ` Rafał Bilski
  2006-08-08 21:06     ` Dave Jones
  0 siblings, 1 reply; 5+ messages in thread
From: Rafał Bilski @ 2006-08-08 20:57 UTC (permalink / raw)
  To: Dave Jones; +Cc: cpufreq

> The only part about this I don't like is that we now need to add
> code to do similar things on every possible VIA chipset that
> could take a C3, and there's quite a few of them, and until
> we have good coverage...
> 

Would be nice, but I have datasheet only for PLE133.
Older non VIA chipsets have this port enabled and its address is 
returned by BIOS as PM2 address, or maybe BIOS is enabling.

Coverage is big enough because mainboards with newer chipsets seems 
to have new, C3 capable, CPU's on board.

> 
> We're going to -ENODEV, possibly breaking some setups that it might actually
> already work on (even if only by chance).
> 
> 		Dave
> 

It isn't working for BCR2. Cpufreq is saying that it is, but cpuinfo_cur_freq 
returns max f all the time.

Rafa³


----------------------------------------------------------------------
PS. Fajny portal... >>> http://link.interia.pl/f196a

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Longhaul - Disable arbiter
  2006-08-08 20:57   ` Rafał Bilski
@ 2006-08-08 21:06     ` Dave Jones
  0 siblings, 0 replies; 5+ messages in thread
From: Dave Jones @ 2006-08-08 21:06 UTC (permalink / raw)
  To: Rafał Bilski; +Cc: cpufreq

On Tue, Aug 08, 2006 at 10:57:37PM +0200, Rafał Bilski wrote:
 > > The only part about this I don't like is that we now need to add
 > > code to do similar things on every possible VIA chipset that
 > > could take a C3, and there's quite a few of them, and until
 > > we have good coverage...
 > > 
 > 
 > Would be nice, but I have datasheet only for PLE133.
 > Older non VIA chipsets have this port enabled and its address is 
 > returned by BIOS as PM2 address, or maybe BIOS is enabling.
 > 
 > Coverage is big enough because mainboards with newer chipsets seems 
 > to have new, C3 capable, CPU's on board.
 > 
 > > 
 > > We're going to -ENODEV, possibly breaking some setups that it might actually
 > > already work on (even if only by chance).
 > 
 > It isn't working for BCR2. Cpufreq is saying that it is, but cpuinfo_cur_freq 
 > returns max f all the time.

Ok, I'll apply this, and see if I can dig up some of the datasheets
on the older chipsets for completeness.

		Dave

-- 
http://www.codemonkey.org.uk

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2006-08-08 21:06 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-08-01  5:51 [PATCH] Longhaul - Disable arbiter Rafał Bilski
  -- strict thread matches above, loose matches on Subject: below --
2006-08-08 17:12 Rafał Bilski
2006-08-08 19:58 ` Dave Jones
2006-08-08 20:57   ` Rafał Bilski
2006-08-08 21:06     ` Dave Jones

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.