* [PATCH] Longhaul
@ 2006-05-29 13:25 Rafał Bilski
0 siblings, 0 replies; 5+ messages in thread
From: Rafał Bilski @ 2006-05-29 13:25 UTC (permalink / raw)
To: Dave Jones; +Cc: cpufreq
(HZ_100 | HZ_250) - for BCR2 MSR CPU's.
How it works:
1. Stop processes.
2. Call suspend(PMSG_FREEZE) for all devices.
3. Change frequency
4. Call resume() for all devices.
5. Start processes.
Adventages:
- works (sadly avg rate drops to 8MB/s),
- using infrastructure already in kernel,
- no need to poke PIC registers - all interrupts are disabled anyway
(APIC compatible?),
- seems to be PREEMPT compatible (no more "sheduling while atomic").
Disadventages:
- suspend(FREEZE) == suspend(SUSPEND) for most devices currently.
But this will be fixed anyway.
- it takes a moment.
diff -uprN -X linux-2.6.16.18-vanilla/Documentation/dontdiff linux-2.6.16.18-vanilla/arch/i386/kernel/cpu/cpufreq/Kconfig linux-2.6.16.18/arch/i386/kernel/cpu/cpufreq/Kconfig
--- linux-2.6.16.18-vanilla/arch/i386/kernel/cpu/cpufreq/Kconfig 2006-05-28 15:04:34.000000000 +0200
+++ linux-2.6.16.18/arch/i386/kernel/cpu/cpufreq/Kconfig 2006-05-29 14:26:51.000000000 +0200
@@ -201,9 +201,11 @@ config X86_LONGRUN
If in doubt, say N.
config X86_LONGHAUL
- tristate "VIA Cyrix III Longhaul"
+ bool "VIA Cyrix III Longhaul (EXPERIMENTAL)"
+ default n
select CPU_FREQ_TABLE
- depends on BROKEN
+ depends on EXPERIMENTAL
+ depends on !SMP && (HZ_100 || HZ_250)
help
This adds the CPUFreq driver for VIA Samuel/CyrixIII,
VIA Cyrix Samuel/C3, VIA Cyrix Ezra and VIA Cyrix Ezra-T
diff -uprN -X linux-2.6.16.18-vanilla/Documentation/dontdiff linux-2.6.16.18-vanilla/arch/i386/kernel/cpu/cpufreq/longhaul.c linux-2.6.16.18/arch/i386/kernel/cpu/cpufreq/longhaul.c
--- linux-2.6.16.18-vanilla/arch/i386/kernel/cpu/cpufreq/longhaul.c 2006-03-20 06:53:29.000000000 +0100
+++ linux-2.6.16.18/arch/i386/kernel/cpu/cpufreq/longhaul.c 2006-05-29 14:23:30.000000000 +0200
@@ -30,6 +30,8 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/pci.h>
+#include <linux/pm.h>
+#include <linux/sched.h>
#include <asm/msr.h>
#include <asm/timex.h>
@@ -115,36 +117,17 @@ static int longhaul_get_cpu_mult(void)
}
-static void do_powersaver(union msr_longhaul *longhaul,
- unsigned int clock_ratio_index)
+/**
+ * Just to be 100% sure
+ */
+
+static u16 cmd_state[64];
+
+static void clear_bus_master(void)
{
struct pci_dev *dev;
- unsigned long flags;
- unsigned int tmp_mask;
- int version;
- int i;
u16 pci_cmd;
- u16 cmd_state[64];
-
- switch (cpu_model) {
- case CPU_EZRA_T:
- version = 3;
- break;
- case CPU_NEHEMIAH:
- version = 0xf;
- break;
- default:
- return;
- }
-
- 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;
-
- preempt_disable();
- local_irq_save(flags);
+ int i;
/*
* get current pci bus master state for all devices
@@ -157,22 +140,20 @@ static void do_powersaver(union msr_long
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);
+ if (pci_cmd & PCI_COMMAND_MASTER) {
+ pci_cmd &= ~PCI_COMMAND_MASTER;
+ pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
+ }
}
} while (dev != NULL);
+}
- tmp_mask=inb(0x21); /* works on C3. save mask. */
- outb(0xFE,0x21); /* TMR0 only */
- outb(0xFF,0x80); /* delay */
-
- safe_halt();
- wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
- halt();
-
- local_irq_disable();
- outb(tmp_mask,0x21); /* restore mask */
+static void restore_bus_master(void)
+{
+ struct pci_dev *dev;
+ u16 pci_cmd;
+ int i;
/* restore pci bus master state for all devices */
dev = NULL;
@@ -181,11 +162,62 @@ static void do_powersaver(union msr_long
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);
+ if (pci_cmd & PCI_COMMAND_MASTER)
+ pci_write_config_byte(dev, PCI_COMMAND, pci_cmd);
}
} while (dev != NULL);
- local_irq_restore(flags);
- preempt_enable();
+}
+
+
+static void do_longhaul1(int reserved, unsigned int clock_ratio_index)
+{
+ union msr_bcr2 bcr2;
+
+ local_irq_disable();
+ rdmsrl(MSR_VIA_BCR2, bcr2.val);
+ /* Enable software clock multiplier */
+ bcr2.bits.ESOFTBF = 1;
+ bcr2.bits.CLOCKMUL = clock_ratio_index;
+ safe_halt(); /* Sync */
+ wrmsrl(MSR_VIA_BCR2, bcr2.val); /* Change */
+ halt();
+
+ /* Disable software clock multiplier */
+ local_irq_disable();
+ rdmsrl(MSR_VIA_BCR2, bcr2.val);
+ bcr2.bits.ESOFTBF = 0;
+ wrmsrl(MSR_VIA_BCR2, bcr2.val);
+}
+
+
+static void do_powersaver(union msr_longhaul *longhaul,
+ unsigned int clock_ratio_index)
+{
+ int version;
+
+ switch (cpu_model) {
+ case CPU_EZRA_T:
+ version = 3;
+ break;
+ case CPU_NEHEMIAH:
+ version = 0xf;
+ break;
+ default:
+ return;
+ }
+
+ local_irq_disable();
+ 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;
+
+ safe_halt(); /* Sync */
+ wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); /* Change */
+ halt();
+
+ local_irq_disable();
/* disable bus ratio bit */
rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
@@ -206,8 +238,8 @@ static void longhaul_setstate(unsigned i
int speed, mult;
struct cpufreq_freqs freqs;
union msr_longhaul longhaul;
- union msr_bcr2 bcr2;
static unsigned int old_ratio=-1;
+ unsigned long flags;
if (old_ratio == clock_ratio_index)
return;
@@ -230,6 +262,15 @@ static void longhaul_setstate(unsigned i
dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
fsb, mult/10, mult%10, print_speed(speed/1000));
+ if ( freeze_processes() )
+ goto thaw;
+ if ( device_suspend(PMSG_FREEZE) ) {
+ printk(KERN_INFO PFX "Some devices failed to freeze\n");
+ goto resume;
+ }
+ clear_bus_master();
+ local_irq_save(flags);
+
switch (longhaul_version) {
/*
@@ -241,20 +282,7 @@ static void longhaul_setstate(unsigned i
*/
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(0, clock_ratio_index);
break;
/*
@@ -273,6 +301,12 @@ static void longhaul_setstate(unsigned i
break;
}
+ local_irq_restore(flags);
+ restore_bus_master();
+resume:
+ device_resume();
+thaw:
+ thaw_processes();
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
----------------------------------------------------------------------
Tysiace zdjec swietnych samochodow! >>> http://link.interia.pl/f1944
^ permalink raw reply [flat|nested] 5+ messages in thread* RE: [PATCH] longhaul
@ 2005-04-20 18:18 ken_staton
2005-04-20 18:47 ` Dave Jones
0 siblings, 1 reply; 5+ messages in thread
From: ken_staton @ 2005-04-20 18:18 UTC (permalink / raw)
To: davej; +Cc: cpufreq
> From: Dave Jones [mailto:davej@redhat.com]
> Sent: Wednesday, April 20, 2005 11:04 AM
> To: STATON,KEN (A-Labs,ex1)
> Cc: cpufreq@lists.linux.org.uk
> Subject: Re: [PATCH] longhaul
>
>
> On Wed, Apr 20, 2005 at 09:49:20AM -0700,
> ken_staton@agilent.com wrote:
>
> > +void ide_idle(void) {
> > + int i;
> > + ide_hwif_t *hwif = ide_hwifs;
> > + ide_drive_t *drive;
> > +
> > + i = 0;
> > + do {
> > + drive = &hwif->drives[i];
> > + i++;
> > + if (strncmp(drive->name,"hd",2) == 0) {
> > + while (drive->waiting_for_dma) udelay(10) ;
> > + } else {
> > + i = 0;
> > + }
> > + } while (i != 0);
> > +}
>
> I wonder if the ide layer should have a way to quiesce dma that
> we can use instead of doing this here.
> Maybe it already does, I'm not too familiar with its internals.
i'll look again. i didn't find a more direct way.
>
> > @@ -133,21 +170,77 @@
> > }
> >
> > 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;
> > - local_irq_disable();
> > +
> > + /* Begin critical section */
> > + preempt_disable();
> > + ide_idle(); /* avoid ide timeouts when bus master off */
> > + local_irq_save(flags);
> > +
> > + /* 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);
>
> This bit bothers me a little, as we're not saving any state
> to record whether the devices had mastering enabled.
state is saved here:
> > + cmd_state[i++] = pci_cmd;
>
> Also, from my reading of the PCI spec, if we disable mastering
> in the root bridge, every device downstream of that should
> also be transparently disabled. Can you try that ?
>
the root bridge command register is read only.
use setpci -s 0:0.0 4.w to confirm
> > + /* disabling INT2 takes care of ints 8-15 (cascaded) */
> > +
> > + tmp_mask=inb(0x21); /* works on C3. save mask. */
> > + outb(0xFE,0x21); /* TMR0 only */
> > + outb(0xFF,0x80); /* delay */
> > +
> > + local_irq_enable(); /* sti */
>
> This part looks a little magical, but the comments suffice I suppose.
>
> > + /* 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);
>
> Again, this bothers me, as we could be enabling mastering on
> a device that previously didn't have it enabled.
>
restoring previous state here:
> > + pci_cmd = cmd_state[i++];
> > longhaul->bits.EnableSoftBusRatio = 0;
> > longhaul->bits.RevisionKey = version;
> > - local_irq_disable();
> > +
> > wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
> > - local_irq_enable();
> > +
>
> Doesn't the spec say we need ints off around transitions ?
>
i didn't read it that way.
in fact an interrupt is one way to bring the PLL back up after hlt;
the timer int is the only one we can conveniently control.
the second write to the MSR doesn't do a PLL transition.
>
> Thanks for chasing this down though, it looks like you're on the
> right track.
>
> Dave
>
>
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] longhaul
2005-04-20 18:18 [PATCH] longhaul ken_staton
@ 2005-04-20 18:47 ` Dave Jones
0 siblings, 0 replies; 5+ messages in thread
From: Dave Jones @ 2005-04-20 18:47 UTC (permalink / raw)
To: ken_staton; +Cc: cpufreq
On Wed, Apr 20, 2005 at 11:18:20AM -0700, ken_staton@agilent.com wrote:
> > I wonder if the ide layer should have a way to quiesce dma that
> > we can use instead of doing this here.
> > Maybe it already does, I'm not too familiar with its internals.
> i'll look again. i didn't find a more direct way.
If it doesn't exist, it's worth bringing this up with the IDE folks
at linux-ide@vger.kernel.org to be sure theres no other evil
ide gotchas we need to know about. This still doesn't solve the
problem of DMA from SATA / SCSI though. Any ideas ?
> > This bit bothers me a little, as we're not saving any state
> > to record whether the devices had mastering enabled.
>
> state is saved here:
> > > + cmd_state[i++] = pci_cmd;
Doh, somehow I completely misread that. looks fine.
> > Also, from my reading of the PCI spec, if we disable mastering
> > in the root bridge, every device downstream of that should
> > also be transparently disabled. Can you try that ?
> the root bridge command register is read only.
> use setpci -s 0:0.0 4.w to confirm
Hmm, I was sure I read otherwise in the spec/mindshare book.
I'll have another read of that when I get home.
> > > longhaul->bits.EnableSoftBusRatio = 0;
> > > longhaul->bits.RevisionKey = version;
> > > - local_irq_disable();
> > > +
> > > wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
> > > - local_irq_enable();
> > > +
> >
> > Doesn't the spec say we need ints off around transitions ?
> i didn't read it that way.
> in fact an interrupt is one way to bring the PLL back up after hlt;
> the timer int is the only one we can conveniently control.
>
> the second write to the MSR doesn't do a PLL transition.
Ok, I'm convinced.
Dave
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH] longhaul
@ 2005-04-20 16:49 ken_staton
2005-04-20 18:03 ` Dave Jones
0 siblings, 1 reply; 5+ messages in thread
From: ken_staton @ 2005-04-20 16:49 UTC (permalink / raw)
To: cpufreq
here's the patch for longhaul on a nehemiah c3-2.
the patch is against 2.6.11.7
i've undone dprintk because it was more convenient to test on both 2.4 and 2.6 kernels.
refer to the text sent to this list on 11apr2005.
note that 8237 dma might still cause problems.
get_dma_residue() on all channels until they are all zero if you need to.
8237 transfer sizes are small enough that they should complete
before the frequency change once pci bus mastering is shut down.
--- longhaul.c 2005-04-20 09:15:55.000000000 -0700
+++ longhaul-rc2.c 2005-04-20 09:15:13.000000000 -0700
@@ -30,6 +30,9 @@
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/ide.h>
+#include <linux/delay.h>
+
#include <asm/msr.h>
#include <asm/timex.h>
#include <asm/io.h>
@@ -58,13 +61,26 @@
/* Module parameters */
static int dont_scale_voltage;
+static int debug;
+static void dprintk(const char *fmt, ...)
+{
+ char s[256];
+ va_list args;
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
+ if (debug == 0)
+ return;
+
+ va_start(args, fmt);
+ vsprintf(s, fmt, args);
+ printk(s);
+ va_end(args);
+}
#define __hlt() __asm__ __volatile__("hlt": : :"memory")
+
/* Clock ratios multiplied by 10 */
static int clock_ratio[32];
static int eblcr_table[32];
@@ -73,9 +89,25 @@
static int longhaul_version;
static struct cpufreq_frequency_table *longhaul_table;
-#ifdef CONFIG_CPU_FREQ_DEBUG
static char speedbuffer[8];
+void ide_idle(void) {
+ int i;
+ ide_hwif_t *hwif = ide_hwifs;
+ ide_drive_t *drive;
+
+ i = 0;
+ do {
+ drive = &hwif->drives[i];
+ i++;
+ if (strncmp(drive->name,"hd",2) == 0) {
+ while (drive->waiting_for_dma) udelay(10) ;
+ } else {
+ i = 0;
+ }
+ } while (i != 0);
+}
+
static char *print_speed(int speed)
{
if (speed > 1000) {
@@ -88,7 +120,6 @@
return speedbuffer;
}
-#endif
static unsigned int calc_speed(int mult)
@@ -120,6 +151,12 @@
unsigned int clock_ratio_index)
{
int version;
+ unsigned long flags;
+ unsigned int tmp_mask;
+ struct pci_dev *dev;
+ int i;
+ u16 pci_cmd;
+ u16 cmd_state[64];
switch (cpu_model) {
case CPU_EZRA_T:
@@ -133,21 +170,77 @@
}
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;
- local_irq_disable();
+
+ /* Begin critical section */
+ preempt_disable();
+ ide_idle(); /* avoid ide timeouts when bus master off */
+ local_irq_save(flags);
+
+ /* 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);
+
+ /* disabling INT2 takes care of ints 8-15 (cascaded) */
+
+ tmp_mask=inb(0x21); /* works on C3. save mask. */
+ outb(0xFE,0x21); /* TMR0 only */
+ outb(0xFF,0x80); /* delay */
+
+ local_irq_enable(); /* sti */
+
+ __hlt(); /* make sure we've got a full tick */
+
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
- local_irq_enable();
+
__hlt();
+ local_irq_disable(); /* cli */
+
+ 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();
+
+ /* END CRITICAL SECTION */
+
+ /* disable bus ratio bit */
+
rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
+
longhaul->bits.EnableSoftBusRatio = 0;
longhaul->bits.RevisionKey = version;
- local_irq_disable();
+
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
- local_irq_enable();
+
}
/**
@@ -578,7 +671,7 @@
longhaul_setup_voltagescaling();
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
- policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+ policy->cpuinfo.transition_latency = 200000; /* nsec */
policy->cur = calc_speed(longhaul_get_cpu_mult());
ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
@@ -649,6 +742,9 @@
module_param (dont_scale_voltage, int, 0644);
MODULE_PARM_DESC(dont_scale_voltage, "Don't scale voltage of processor");
+module_param (debug, int, 0644);
+MODULE_PARM_DESC(debug, "Dump debugging information.");
+
MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");
MODULE_LICENSE ("GPL");
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] longhaul
2005-04-20 16:49 ken_staton
@ 2005-04-20 18:03 ` Dave Jones
0 siblings, 0 replies; 5+ messages in thread
From: Dave Jones @ 2005-04-20 18:03 UTC (permalink / raw)
To: ken_staton; +Cc: cpufreq
On Wed, Apr 20, 2005 at 09:49:20AM -0700, ken_staton@agilent.com wrote:
> +void ide_idle(void) {
> + int i;
> + ide_hwif_t *hwif = ide_hwifs;
> + ide_drive_t *drive;
> +
> + i = 0;
> + do {
> + drive = &hwif->drives[i];
> + i++;
> + if (strncmp(drive->name,"hd",2) == 0) {
> + while (drive->waiting_for_dma) udelay(10) ;
> + } else {
> + i = 0;
> + }
> + } while (i != 0);
> +}
I wonder if the ide layer should have a way to quiesce dma that
we can use instead of doing this here.
Maybe it already does, I'm not too familiar with its internals.
> @@ -133,21 +170,77 @@
> }
>
> 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;
> - local_irq_disable();
> +
> + /* Begin critical section */
> + preempt_disable();
> + ide_idle(); /* avoid ide timeouts when bus master off */
> + local_irq_save(flags);
> +
> + /* 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);
This bit bothers me a little, as we're not saving any state
to record whether the devices had mastering enabled.
Also, from my reading of the PCI spec, if we disable mastering
in the root bridge, every device downstream of that should
also be transparently disabled. Can you try that ?
> + /* disabling INT2 takes care of ints 8-15 (cascaded) */
> +
> + tmp_mask=inb(0x21); /* works on C3. save mask. */
> + outb(0xFE,0x21); /* TMR0 only */
> + outb(0xFF,0x80); /* delay */
> +
> + local_irq_enable(); /* sti */
This part looks a little magical, but the comments suffice I suppose.
> + /* 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);
Again, this bothers me, as we could be enabling mastering on
a device that previously didn't have it enabled.
> longhaul->bits.EnableSoftBusRatio = 0;
> longhaul->bits.RevisionKey = version;
> - local_irq_disable();
> +
> wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
> - local_irq_enable();
> +
Doesn't the spec say we need ints off around transitions ?
Thanks for chasing this down though, it looks like you're on the
right track.
Dave
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2006-05-29 13:25 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-05-29 13:25 [PATCH] Longhaul Rafał Bilski
-- strict thread matches above, loose matches on Subject: below --
2005-04-20 18:18 [PATCH] longhaul ken_staton
2005-04-20 18:47 ` Dave Jones
2005-04-20 16:49 ken_staton
2005-04-20 18:03 ` 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.