#include <linux/cpufreq.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/pci.h>
#include <asm/msr.h>
#include <asm/timex.h>
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:
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();
}
/**