Commit 3be6a48f authored by Dave Jones's avatar Dave Jones

[CPUFREQ] longhaul - disable PCI mastering around transition.

The spec states that we have to do this, which is *horrid*.

Based on code from: Ken Staton <ken_staton@agilent.com>
Signed-off-by: default avatarDave Jones <davej@redhat.com>
parent e131832c
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/pci.h>
#include <asm/msr.h> #include <asm/msr.h>
#include <asm/timex.h> #include <asm/timex.h>
...@@ -120,6 +121,11 @@ static void do_powersaver(union msr_longhaul *longhaul, ...@@ -120,6 +121,11 @@ static void do_powersaver(union msr_longhaul *longhaul,
unsigned int clock_ratio_index) unsigned int clock_ratio_index)
{ {
int version; int version;
unsigned long flags;
struct pci_dev *dev;
int i;
u16 pci_cmd;
u16 cmd_state[64];
switch (cpu_model) { switch (cpu_model) {
case CPU_EZRA_T: case CPU_EZRA_T:
...@@ -137,17 +143,52 @@ static void do_powersaver(union msr_longhaul *longhaul, ...@@ -137,17 +143,52 @@ static void do_powersaver(union msr_longhaul *longhaul,
longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
longhaul->bits.EnableSoftBusRatio = 1; longhaul->bits.EnableSoftBusRatio = 1;
longhaul->bits.RevisionKey = 0; longhaul->bits.RevisionKey = 0;
local_irq_disable();
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); preempt_disable();
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);
local_irq_enable(); local_irq_enable();
__hlt();
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
__hlt(); __hlt();
local_irq_disable();
/* 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); rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
longhaul->bits.EnableSoftBusRatio = 0; longhaul->bits.EnableSoftBusRatio = 0;
longhaul->bits.RevisionKey = version; longhaul->bits.RevisionKey = version;
local_irq_disable();
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
local_irq_enable();
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment