aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeliang Tang <geliangtang@163.com>2015-12-07 09:24:24 -0500
committerBjorn Helgaas <bhelgaas@google.com>2015-12-10 20:38:07 -0500
commit96ae6469ba16ae502d2b2db4b5c9b7c846262999 (patch)
tree2b293b96b1a753e9070eccbafc012777c58fc4d4
parent8e5a395a040a7c72ec283f844eca679b924f5f01 (diff)
x86/PCI: Simplify pci_bios_{read,write}
There is some repetitive code in the switch/case statements in pci_bios_read() and pci_bios_write(). Factor out the BIOS function IDs and the result widths to simplify the code. Signed-off-by: Geliang Tang <geliangtang@163.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--arch/x86/pci/pcbios.c108
1 files changed, 38 insertions, 70 deletions
diff --git a/arch/x86/pci/pcbios.c b/arch/x86/pci/pcbios.c
index 9b83b9051ae7..9770e55e768f 100644
--- a/arch/x86/pci/pcbios.c
+++ b/arch/x86/pci/pcbios.c
@@ -180,6 +180,7 @@ static int pci_bios_read(unsigned int seg, unsigned int bus,
180 unsigned long result = 0; 180 unsigned long result = 0;
181 unsigned long flags; 181 unsigned long flags;
182 unsigned long bx = (bus << 8) | devfn; 182 unsigned long bx = (bus << 8) | devfn;
183 u16 number = 0, mask = 0;
183 184
184 WARN_ON(seg); 185 WARN_ON(seg);
185 if (!value || (bus > 255) || (devfn > 255) || (reg > 255)) 186 if (!value || (bus > 255) || (devfn > 255) || (reg > 255))
@@ -189,53 +190,35 @@ static int pci_bios_read(unsigned int seg, unsigned int bus,
189 190
190 switch (len) { 191 switch (len) {
191 case 1: 192 case 1:
192 __asm__("lcall *(%%esi); cld\n\t" 193 number = PCIBIOS_READ_CONFIG_BYTE;
193 "jc 1f\n\t" 194 mask = 0xff;
194 "xor %%ah, %%ah\n"
195 "1:"
196 : "=c" (*value),
197 "=a" (result)
198 : "1" (PCIBIOS_READ_CONFIG_BYTE),
199 "b" (bx),
200 "D" ((long)reg),
201 "S" (&pci_indirect));
202 /*
203 * Zero-extend the result beyond 8 bits, do not trust the
204 * BIOS having done it:
205 */
206 *value &= 0xff;
207 break; 195 break;
208 case 2: 196 case 2:
209 __asm__("lcall *(%%esi); cld\n\t" 197 number = PCIBIOS_READ_CONFIG_WORD;
210 "jc 1f\n\t" 198 mask = 0xffff;
211 "xor %%ah, %%ah\n"
212 "1:"
213 : "=c" (*value),
214 "=a" (result)
215 : "1" (PCIBIOS_READ_CONFIG_WORD),
216 "b" (bx),
217 "D" ((long)reg),
218 "S" (&pci_indirect));
219 /*
220 * Zero-extend the result beyond 16 bits, do not trust the
221 * BIOS having done it:
222 */
223 *value &= 0xffff;
224 break; 199 break;
225 case 4: 200 case 4:
226 __asm__("lcall *(%%esi); cld\n\t" 201 number = PCIBIOS_READ_CONFIG_DWORD;
227 "jc 1f\n\t"
228 "xor %%ah, %%ah\n"
229 "1:"
230 : "=c" (*value),
231 "=a" (result)
232 : "1" (PCIBIOS_READ_CONFIG_DWORD),
233 "b" (bx),
234 "D" ((long)reg),
235 "S" (&pci_indirect));
236 break; 202 break;
237 } 203 }
238 204
205 __asm__("lcall *(%%esi); cld\n\t"
206 "jc 1f\n\t"
207 "xor %%ah, %%ah\n"
208 "1:"
209 : "=c" (*value),
210 "=a" (result)
211 : "1" (number),
212 "b" (bx),
213 "D" ((long)reg),
214 "S" (&pci_indirect));
215 /*
216 * Zero-extend the result beyond 8 or 16 bits, do not trust the
217 * BIOS having done it:
218 */
219 if (mask)
220 *value &= mask;
221
239 raw_spin_unlock_irqrestore(&pci_config_lock, flags); 222 raw_spin_unlock_irqrestore(&pci_config_lock, flags);
240 223
241 return (int)((result & 0xff00) >> 8); 224 return (int)((result & 0xff00) >> 8);
@@ -247,6 +230,7 @@ static int pci_bios_write(unsigned int seg, unsigned int bus,
247 unsigned long result = 0; 230 unsigned long result = 0;
248 unsigned long flags; 231 unsigned long flags;
249 unsigned long bx = (bus << 8) | devfn; 232 unsigned long bx = (bus << 8) | devfn;
233 u16 number = 0;
250 234
251 WARN_ON(seg); 235 WARN_ON(seg);
252 if ((bus > 255) || (devfn > 255) || (reg > 255)) 236 if ((bus > 255) || (devfn > 255) || (reg > 255))
@@ -256,43 +240,27 @@ static int pci_bios_write(unsigned int seg, unsigned int bus,
256 240
257 switch (len) { 241 switch (len) {
258 case 1: 242 case 1:
259 __asm__("lcall *(%%esi); cld\n\t" 243 number = PCIBIOS_WRITE_CONFIG_BYTE;
260 "jc 1f\n\t"
261 "xor %%ah, %%ah\n"
262 "1:"
263 : "=a" (result)
264 : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
265 "c" (value),
266 "b" (bx),
267 "D" ((long)reg),
268 "S" (&pci_indirect));
269 break; 244 break;
270 case 2: 245 case 2:
271 __asm__("lcall *(%%esi); cld\n\t" 246 number = PCIBIOS_WRITE_CONFIG_WORD;
272 "jc 1f\n\t"
273 "xor %%ah, %%ah\n"
274 "1:"
275 : "=a" (result)
276 : "0" (PCIBIOS_WRITE_CONFIG_WORD),
277 "c" (value),
278 "b" (bx),
279 "D" ((long)reg),
280 "S" (&pci_indirect));
281 break; 247 break;
282 case 4: 248 case 4:
283 __asm__("lcall *(%%esi); cld\n\t" 249 number = PCIBIOS_WRITE_CONFIG_DWORD;
284 "jc 1f\n\t"
285 "xor %%ah, %%ah\n"
286 "1:"
287 : "=a" (result)
288 : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
289 "c" (value),
290 "b" (bx),
291 "D" ((long)reg),
292 "S" (&pci_indirect));
293 break; 250 break;
294 } 251 }
295 252
253 __asm__("lcall *(%%esi); cld\n\t"
254 "jc 1f\n\t"
255 "xor %%ah, %%ah\n"
256 "1:"
257 : "=a" (result)
258 : "0" (number),
259 "c" (value),
260 "b" (bx),
261 "D" ((long)reg),
262 "S" (&pci_indirect));
263
296 raw_spin_unlock_irqrestore(&pci_config_lock, flags); 264 raw_spin_unlock_irqrestore(&pci_config_lock, flags);
297 265
298 return (int)((result & 0xff00) >> 8); 266 return (int)((result & 0xff00) >> 8);