aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/pci/common.c
diff options
context:
space:
mode:
authorMike Habeck <habeck@sgi.com>2010-05-12 14:14:32 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-07-30 12:29:12 -0400
commit7bd1c365fd124624191d49dcc1eb9759d6017ec3 (patch)
tree3e193b2061e02f4e04c51d14ce7a066c6e850bb2 /arch/x86/pci/common.c
parent549e15611b4ac1de51ef0e0a79c2704f50a638a2 (diff)
x86/PCI: Add option to not assign BAR's if not already assigned
The Linux kernel assigns BARs that a BIOS did not assign, most likely to handle broken BIOSes that didn't enumerate the devices correctly. On UV the BIOS purposely doesn't assign I/O BARs for certain devices/ drivers we know don't use them (examples, LSI SAS, Qlogic FC, ...). We purposely don't assign these I/O BARs because I/O Space is a very limited resource. There is only 64k of I/O Space, and in a PCIe topology that space gets divided up into 4k chucks (this is due to the fact that a pci-to-pci bridge's I/O decoder is aligned at 4k)... Thus a system can have at most 16 cards with I/O BARs: (64k / 4k = 16) SGI needs to scale to >16 devices with I/O BARs. So by not assigning I/O BARs on devices we know don't use them, we can do that (iff the kernel doesn't go and assign these BARs that the BIOS purposely didn't assign). This patch will not assign a resource to a device BAR if that BAR was not assigned by the BIOS, and the kernel cmdline option 'pci=nobar' was specified. This patch is closely modeled after the 'pci=norom' option that currently exists in the tree. Signed-off-by: Mike Habeck <habeck@sgi.com> Signed-off-by: Mike Travis <travis@sgi.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'arch/x86/pci/common.c')
-rw-r--r--arch/x86/pci/common.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 215a27ae050d..a0772af64efb 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -125,6 +125,23 @@ void __init dmi_check_skip_isa_align(void)
125static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) 125static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
126{ 126{
127 struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE]; 127 struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE];
128 struct resource *bar_r;
129 int bar;
130
131 if (pci_probe & PCI_NOASSIGN_BARS) {
132 /*
133 * If the BIOS did not assign the BAR, zero out the
134 * resource so the kernel doesn't attmept to assign
135 * it later on in pci_assign_unassigned_resources
136 */
137 for (bar = 0; bar <= PCI_STD_RESOURCE_END; bar++) {
138 bar_r = &dev->resource[bar];
139 if (bar_r->start == 0 && bar_r->end != 0) {
140 bar_r->flags = 0;
141 bar_r->end = 0;
142 }
143 }
144 }
128 145
129 if (pci_probe & PCI_NOASSIGN_ROMS) { 146 if (pci_probe & PCI_NOASSIGN_ROMS) {
130 if (rom_r->parent) 147 if (rom_r->parent)
@@ -509,6 +526,9 @@ char * __devinit pcibios_setup(char *str)
509 } else if (!strcmp(str, "norom")) { 526 } else if (!strcmp(str, "norom")) {
510 pci_probe |= PCI_NOASSIGN_ROMS; 527 pci_probe |= PCI_NOASSIGN_ROMS;
511 return NULL; 528 return NULL;
529 } else if (!strcmp(str, "nobar")) {
530 pci_probe |= PCI_NOASSIGN_BARS;
531 return NULL;
512 } else if (!strcmp(str, "assign-busses")) { 532 } else if (!strcmp(str, "assign-busses")) {
513 pci_probe |= PCI_ASSIGN_ALL_BUSSES; 533 pci_probe |= PCI_ASSIGN_ALL_BUSSES;
514 return NULL; 534 return NULL;