aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/setup-bus.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@aristanetworks.com>2009-09-09 17:09:24 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-09-09 17:10:24 -0400
commit28760489a3f1e136c5ae8581c0fa8f63511f2f4c (patch)
treea3c890e9c8d9e98385691d56f5c007d280514fe5 /drivers/pci/setup-bus.c
parent0ba379ec0fb182a87b8891c5754abbcd9c035b4f (diff)
PCI: pcie: Ensure hotplug ports have a minimum number of resources
In general a BIOS may goof or we may hotplug in a hotplug controller. In either case the kernel needs to reserve resources for plugging in more devices in the future instead of creating a minimal resource assignment. We already do this for cardbus bridges I am just adding a variant for pcie bridges. v2: Make testing for pcie hotplug bridges based on a flag. So far we only set the flag for pcie but a header_quirk could easily be added for the non-standard pci hotplug bridges. Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/setup-bus.c')
-rw-r--r--drivers/pci/setup-bus.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 7c443b4583ab..cb1a027eb552 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -309,7 +309,7 @@ static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned lon
309 since these windows have 4K granularity and the IO ranges 309 since these windows have 4K granularity and the IO ranges
310 of non-bridge PCI devices are limited to 256 bytes. 310 of non-bridge PCI devices are limited to 256 bytes.
311 We must be careful with the ISA aliasing though. */ 311 We must be careful with the ISA aliasing though. */
312static void pbus_size_io(struct pci_bus *bus) 312static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size)
313{ 313{
314 struct pci_dev *dev; 314 struct pci_dev *dev;
315 struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); 315 struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
@@ -336,6 +336,8 @@ static void pbus_size_io(struct pci_bus *bus)
336 size1 += r_size; 336 size1 += r_size;
337 } 337 }
338 } 338 }
339 if (size < min_size)
340 size = min_size;
339/* To be fixed in 2.5: we should have sort of HAVE_ISA 341/* To be fixed in 2.5: we should have sort of HAVE_ISA
340 flag in the struct pci_bus. */ 342 flag in the struct pci_bus. */
341#if defined(CONFIG_ISA) || defined(CONFIG_EISA) 343#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
@@ -354,7 +356,8 @@ static void pbus_size_io(struct pci_bus *bus)
354 356
355/* Calculate the size of the bus and minimal alignment which 357/* Calculate the size of the bus and minimal alignment which
356 guarantees that all child resources fit in this size. */ 358 guarantees that all child resources fit in this size. */
357static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type) 359static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
360 unsigned long type, resource_size_t min_size)
358{ 361{
359 struct pci_dev *dev; 362 struct pci_dev *dev;
360 resource_size_t min_align, align, size; 363 resource_size_t min_align, align, size;
@@ -404,6 +407,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
404 mem64_mask &= r->flags & IORESOURCE_MEM_64; 407 mem64_mask &= r->flags & IORESOURCE_MEM_64;
405 } 408 }
406 } 409 }
410 if (size < min_size)
411 size = min_size;
407 412
408 align = 0; 413 align = 0;
409 min_align = 0; 414 min_align = 0;
@@ -483,6 +488,7 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
483{ 488{
484 struct pci_dev *dev; 489 struct pci_dev *dev;
485 unsigned long mask, prefmask; 490 unsigned long mask, prefmask;
491 resource_size_t min_mem_size = 0, min_io_size = 0;
486 492
487 list_for_each_entry(dev, &bus->devices, bus_list) { 493 list_for_each_entry(dev, &bus->devices, bus_list) {
488 struct pci_bus *b = dev->subordinate; 494 struct pci_bus *b = dev->subordinate;
@@ -512,8 +518,12 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
512 518
513 case PCI_CLASS_BRIDGE_PCI: 519 case PCI_CLASS_BRIDGE_PCI:
514 pci_bridge_check_ranges(bus); 520 pci_bridge_check_ranges(bus);
521 if (bus->self->is_hotplug_bridge) {
522 min_io_size = pci_hotplug_io_size;
523 min_mem_size = pci_hotplug_mem_size;
524 }
515 default: 525 default:
516 pbus_size_io(bus); 526 pbus_size_io(bus, min_io_size);
517 /* If the bridge supports prefetchable range, size it 527 /* If the bridge supports prefetchable range, size it
518 separately. If it doesn't, or its prefetchable window 528 separately. If it doesn't, or its prefetchable window
519 has already been allocated by arch code, try 529 has already been allocated by arch code, try
@@ -521,9 +531,11 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
521 resources. */ 531 resources. */
522 mask = IORESOURCE_MEM; 532 mask = IORESOURCE_MEM;
523 prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH; 533 prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH;
524 if (pbus_size_mem(bus, prefmask, prefmask)) 534 if (pbus_size_mem(bus, prefmask, prefmask, min_mem_size))
525 mask = prefmask; /* Success, size non-prefetch only. */ 535 mask = prefmask; /* Success, size non-prefetch only. */
526 pbus_size_mem(bus, mask, IORESOURCE_MEM); 536 else
537 min_mem_size += min_mem_size;
538 pbus_size_mem(bus, mask, IORESOURCE_MEM, min_mem_size);
527 break; 539 break;
528 } 540 }
529} 541}