Skip to content

Commit

Permalink
x86/PCI: Simplify pci_bios_{read,write}
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Geliang Tang authored and Bjorn Helgaas committed Dec 11, 2015
1 parent 8e5a395 commit 96ae646
Showing 1 changed file with 38 additions and 70 deletions.
108 changes: 38 additions & 70 deletions arch/x86/pci/pcbios.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ static int pci_bios_read(unsigned int seg, unsigned int bus,
unsigned long result = 0;
unsigned long flags;
unsigned long bx = (bus << 8) | devfn;
u16 number = 0, mask = 0;

WARN_ON(seg);
if (!value || (bus > 255) || (devfn > 255) || (reg > 255))
Expand All @@ -189,53 +190,35 @@ static int pci_bios_read(unsigned int seg, unsigned int bus,

switch (len) {
case 1:
__asm__("lcall *(%%esi); cld\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
: "=c" (*value),
"=a" (result)
: "1" (PCIBIOS_READ_CONFIG_BYTE),
"b" (bx),
"D" ((long)reg),
"S" (&pci_indirect));
/*
* Zero-extend the result beyond 8 bits, do not trust the
* BIOS having done it:
*/
*value &= 0xff;
number = PCIBIOS_READ_CONFIG_BYTE;
mask = 0xff;
break;
case 2:
__asm__("lcall *(%%esi); cld\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
: "=c" (*value),
"=a" (result)
: "1" (PCIBIOS_READ_CONFIG_WORD),
"b" (bx),
"D" ((long)reg),
"S" (&pci_indirect));
/*
* Zero-extend the result beyond 16 bits, do not trust the
* BIOS having done it:
*/
*value &= 0xffff;
number = PCIBIOS_READ_CONFIG_WORD;
mask = 0xffff;
break;
case 4:
__asm__("lcall *(%%esi); cld\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
: "=c" (*value),
"=a" (result)
: "1" (PCIBIOS_READ_CONFIG_DWORD),
"b" (bx),
"D" ((long)reg),
"S" (&pci_indirect));
number = PCIBIOS_READ_CONFIG_DWORD;
break;
}

__asm__("lcall *(%%esi); cld\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
: "=c" (*value),
"=a" (result)
: "1" (number),
"b" (bx),
"D" ((long)reg),
"S" (&pci_indirect));
/*
* Zero-extend the result beyond 8 or 16 bits, do not trust the
* BIOS having done it:
*/
if (mask)
*value &= mask;

raw_spin_unlock_irqrestore(&pci_config_lock, flags);

return (int)((result & 0xff00) >> 8);
Expand All @@ -247,6 +230,7 @@ static int pci_bios_write(unsigned int seg, unsigned int bus,
unsigned long result = 0;
unsigned long flags;
unsigned long bx = (bus << 8) | devfn;
u16 number = 0;

WARN_ON(seg);
if ((bus > 255) || (devfn > 255) || (reg > 255))
Expand All @@ -256,43 +240,27 @@ static int pci_bios_write(unsigned int seg, unsigned int bus,

switch (len) {
case 1:
__asm__("lcall *(%%esi); cld\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
: "=a" (result)
: "0" (PCIBIOS_WRITE_CONFIG_BYTE),
"c" (value),
"b" (bx),
"D" ((long)reg),
"S" (&pci_indirect));
number = PCIBIOS_WRITE_CONFIG_BYTE;
break;
case 2:
__asm__("lcall *(%%esi); cld\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
: "=a" (result)
: "0" (PCIBIOS_WRITE_CONFIG_WORD),
"c" (value),
"b" (bx),
"D" ((long)reg),
"S" (&pci_indirect));
number = PCIBIOS_WRITE_CONFIG_WORD;
break;
case 4:
__asm__("lcall *(%%esi); cld\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
: "=a" (result)
: "0" (PCIBIOS_WRITE_CONFIG_DWORD),
"c" (value),
"b" (bx),
"D" ((long)reg),
"S" (&pci_indirect));
number = PCIBIOS_WRITE_CONFIG_DWORD;
break;
}

__asm__("lcall *(%%esi); cld\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
: "=a" (result)
: "0" (number),
"c" (value),
"b" (bx),
"D" ((long)reg),
"S" (&pci_indirect));

raw_spin_unlock_irqrestore(&pci_config_lock, flags);

return (int)((result & 0xff00) >> 8);
Expand Down

0 comments on commit 96ae646

Please sign in to comment.