aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDave Jones <davej@redhat.com>2005-05-31 22:03:51 -0400
committerDave Jones <davej@redhat.com>2005-05-31 22:03:51 -0400
commit3be6a48f3c8df1b2fbbe57face95a03d167bda1b (patch)
tree8e3eda4b78879c0a10dec89fe0ef1c3aa4158256 /arch
parente131832ca7d3a3e5f9c7624bb310a7747dc2b57c (diff)
[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>
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.c49
1 files changed, 45 insertions, 4 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index ab0f9f5aac11..8ea545e35b3a 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -29,6 +29,7 @@
29#include <linux/cpufreq.h> 29#include <linux/cpufreq.h>
30#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/string.h> 31#include <linux/string.h>
32#include <linux/pci.h>
32 33
33#include <asm/msr.h> 34#include <asm/msr.h>
34#include <asm/timex.h> 35#include <asm/timex.h>
@@ -120,6 +121,11 @@ static void do_powersaver(union msr_longhaul *longhaul,
120 unsigned int clock_ratio_index) 121 unsigned int clock_ratio_index)
121{ 122{
122 int version; 123 int version;
124 unsigned long flags;
125 struct pci_dev *dev;
126 int i;
127 u16 pci_cmd;
128 u16 cmd_state[64];
123 129
124 switch (cpu_model) { 130 switch (cpu_model) {
125 case CPU_EZRA_T: 131 case CPU_EZRA_T:
@@ -137,17 +143,52 @@ static void do_powersaver(union msr_longhaul *longhaul,
137 longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; 143 longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
138 longhaul->bits.EnableSoftBusRatio = 1; 144 longhaul->bits.EnableSoftBusRatio = 1;
139 longhaul->bits.RevisionKey = 0; 145 longhaul->bits.RevisionKey = 0;
140 local_irq_disable(); 146
141 wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); 147 preempt_disable();
148 local_irq_save(flags);
149
150 /*
151 * get current pci bus master state for all devices
152 * and clear bus master bit
153 */
154 dev = NULL;
155 i = 0;
156 do {
157 dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
158 if (dev != NULL) {
159 pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
160 cmd_state[i++] = pci_cmd;
161 pci_cmd &= ~PCI_COMMAND_MASTER;
162 pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
163 }
164 } while (dev != NULL);
165
142 local_irq_enable(); 166 local_irq_enable();
167
168 __hlt();
169 wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
143 __hlt(); 170 __hlt();
144 171
172 local_irq_disable();
173
174 /* restore pci bus master state for all devices */
175 dev = NULL;
176 i = 0;
177 do {
178 dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
179 if (dev != NULL) {
180 pci_cmd = cmd_state[i++];
181 pci_write_config_byte(dev, PCI_COMMAND, pci_cmd);
182 }
183 } while (dev != NULL);
184 local_irq_restore(flags);
185 preempt_enable();
186
187 /* disable bus ratio bit */
145 rdmsrl(MSR_VIA_LONGHAUL, longhaul->val); 188 rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
146 longhaul->bits.EnableSoftBusRatio = 0; 189 longhaul->bits.EnableSoftBusRatio = 0;
147 longhaul->bits.RevisionKey = version; 190 longhaul->bits.RevisionKey = version;
148 local_irq_disable();
149 wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); 191 wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
150 local_irq_enable();
151} 192}
152 193
153/** 194/**