[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: Dave Jones <davej@redhat.com>

+45 -4
+45 -4
arch/i386/kernel/cpu/cpufreq/longhaul.c
··· 29 29 #include <linux/cpufreq.h> 30 30 #include <linux/slab.h> 31 31 #include <linux/string.h> 32 + #include <linux/pci.h> 32 33 33 34 #include <asm/msr.h> 34 35 #include <asm/timex.h> ··· 121 120 unsigned int clock_ratio_index) 122 121 { 123 122 int version; 123 + unsigned long flags; 124 + struct pci_dev *dev; 125 + int i; 126 + u16 pci_cmd; 127 + u16 cmd_state[64]; 124 128 125 129 switch (cpu_model) { 126 130 case CPU_EZRA_T: ··· 143 137 longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; 144 138 longhaul->bits.EnableSoftBusRatio = 1; 145 139 longhaul->bits.RevisionKey = 0; 146 - local_irq_disable(); 147 - wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); 140 + 141 + preempt_disable(); 142 + local_irq_save(flags); 143 + 144 + /* 145 + * get current pci bus master state for all devices 146 + * and clear bus master bit 147 + */ 148 + dev = NULL; 149 + i = 0; 150 + do { 151 + dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); 152 + if (dev != NULL) { 153 + pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); 154 + cmd_state[i++] = pci_cmd; 155 + pci_cmd &= ~PCI_COMMAND_MASTER; 156 + pci_write_config_word(dev, PCI_COMMAND, pci_cmd); 157 + } 158 + } while (dev != NULL); 159 + 148 160 local_irq_enable(); 161 + 162 + __hlt(); 163 + wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); 149 164 __hlt(); 150 165 166 + local_irq_disable(); 167 + 168 + /* restore pci bus master state for all devices */ 169 + dev = NULL; 170 + i = 0; 171 + do { 172 + dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); 173 + if (dev != NULL) { 174 + pci_cmd = cmd_state[i++]; 175 + pci_write_config_byte(dev, PCI_COMMAND, pci_cmd); 176 + } 177 + } while (dev != NULL); 178 + local_irq_restore(flags); 179 + preempt_enable(); 180 + 181 + /* disable bus ratio bit */ 151 182 rdmsrl(MSR_VIA_LONGHAUL, longhaul->val); 152 183 longhaul->bits.EnableSoftBusRatio = 0; 153 184 longhaul->bits.RevisionKey = version; 154 - local_irq_disable(); 155 185 wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); 156 - local_irq_enable(); 157 186 } 158 187 159 188 /**