|
|
@@ -29,6 +29,7 @@
|
|
|
#include <linux/cpufreq.h>
|
|
|
#include <linux/slab.h>
|
|
|
#include <linux/string.h>
|
|
|
+#include <linux/pci.h>
|
|
|
|
|
|
#include <asm/msr.h>
|
|
|
#include <asm/timex.h>
|
|
|
@@ -120,6 +121,11 @@ static void do_powersaver(union msr_longhaul *longhaul,
|
|
|
unsigned int clock_ratio_index)
|
|
|
{
|
|
|
int version;
|
|
|
+ unsigned long flags;
|
|
|
+ struct pci_dev *dev;
|
|
|
+ int i;
|
|
|
+ u16 pci_cmd;
|
|
|
+ u16 cmd_state[64];
|
|
|
|
|
|
switch (cpu_model) {
|
|
|
case CPU_EZRA_T:
|
|
|
@@ -137,17 +143,52 @@ static void do_powersaver(union msr_longhaul *longhaul,
|
|
|
longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
|
|
|
longhaul->bits.EnableSoftBusRatio = 1;
|
|
|
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();
|
|
|
+
|
|
|
+ __hlt();
|
|
|
+ wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
|
|
|
__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);
|
|
|
longhaul->bits.EnableSoftBusRatio = 0;
|
|
|
longhaul->bits.RevisionKey = version;
|
|
|
- local_irq_disable();
|
|
|
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
|
|
|
- local_irq_enable();
|
|
|
}
|
|
|
|
|
|
/**
|