Commit 7bd1c365fd124624191d49dcc1eb9759d6017ec3

Authored by Mike Habeck
Committed by Jesse Barnes
1 parent 549e15611b

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>

Showing 3 changed files with 23 additions and 0 deletions Side-by-side Diff

Documentation/kernel-parameters.txt
... ... @@ -1970,6 +1970,8 @@
1970 1970 norom [X86] Do not assign address space to
1971 1971 expansion ROMs that do not already have
1972 1972 BIOS assigned address ranges.
  1973 + nobar [X86] Do not assign address space to the
  1974 + BARs that weren't assigned by the BIOS.
1973 1975 irqmask=0xMMMM [X86] Set a bit mask of IRQs allowed to be
1974 1976 assigned automatically to PCI devices. You can
1975 1977 make the kernel exclude IRQs of your ISA cards
arch/x86/include/asm/pci_x86.h
... ... @@ -30,6 +30,7 @@
30 30 #define PCI_HAS_IO_ECS 0x40000
31 31 #define PCI_NOASSIGN_ROMS 0x80000
32 32 #define PCI_ROOT_NO_CRS 0x100000
  33 +#define PCI_NOASSIGN_BARS 0x200000
33 34  
34 35 extern unsigned int pci_probe;
35 36 extern unsigned long pirq_table_addr;
arch/x86/pci/common.c
... ... @@ -125,7 +125,24 @@
125 125 static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
126 126 {
127 127 struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE];
  128 + struct resource *bar_r;
  129 + int bar;
128 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 + }
  145 +
129 146 if (pci_probe & PCI_NOASSIGN_ROMS) {
130 147 if (rom_r->parent)
131 148 return;
... ... @@ -508,6 +525,9 @@
508 525 return NULL;
509 526 } else if (!strcmp(str, "norom")) {
510 527 pci_probe |= PCI_NOASSIGN_ROMS;
  528 + return NULL;
  529 + } else if (!strcmp(str, "nobar")) {
  530 + pci_probe |= PCI_NOASSIGN_BARS;
511 531 return NULL;
512 532 } else if (!strcmp(str, "assign-busses")) {
513 533 pci_probe |= PCI_ASSIGN_ALL_BUSSES;