diff options
author | Dave Jones <davej@redhat.com> | 2005-05-31 22:03:51 -0400 |
---|---|---|
committer | Dave Jones <davej@redhat.com> | 2005-05-31 22:03:51 -0400 |
commit | 3be6a48f3c8df1b2fbbe57face95a03d167bda1b (patch) | |
tree | 8e3eda4b78879c0a10dec89fe0ef1c3aa4158256 /arch | |
parent | e131832ca7d3a3e5f9c7624bb310a7747dc2b57c (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.c | 49 |
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 | /** |