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>
This commit is contained in:

committed by
Jesse Barnes

parent
0ba379ec0f
commit
28760489a3
@@ -309,7 +309,7 @@ static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned lon
|
||||
since these windows have 4K granularity and the IO ranges
|
||||
of non-bridge PCI devices are limited to 256 bytes.
|
||||
We must be careful with the ISA aliasing though. */
|
||||
static void pbus_size_io(struct pci_bus *bus)
|
||||
static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
|
||||
@@ -336,6 +336,8 @@ static void pbus_size_io(struct pci_bus *bus)
|
||||
size1 += r_size;
|
||||
}
|
||||
}
|
||||
if (size < min_size)
|
||||
size = min_size;
|
||||
/* To be fixed in 2.5: we should have sort of HAVE_ISA
|
||||
flag in the struct pci_bus. */
|
||||
#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
|
||||
@@ -354,7 +356,8 @@ static void pbus_size_io(struct pci_bus *bus)
|
||||
|
||||
/* Calculate the size of the bus and minimal alignment which
|
||||
guarantees that all child resources fit in this size. */
|
||||
static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type)
|
||||
static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
||||
unsigned long type, resource_size_t min_size)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
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
|
||||
mem64_mask &= r->flags & IORESOURCE_MEM_64;
|
||||
}
|
||||
}
|
||||
if (size < min_size)
|
||||
size = min_size;
|
||||
|
||||
align = 0;
|
||||
min_align = 0;
|
||||
@@ -483,6 +488,7 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
unsigned long mask, prefmask;
|
||||
resource_size_t min_mem_size = 0, min_io_size = 0;
|
||||
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
struct pci_bus *b = dev->subordinate;
|
||||
@@ -512,8 +518,12 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
|
||||
|
||||
case PCI_CLASS_BRIDGE_PCI:
|
||||
pci_bridge_check_ranges(bus);
|
||||
if (bus->self->is_hotplug_bridge) {
|
||||
min_io_size = pci_hotplug_io_size;
|
||||
min_mem_size = pci_hotplug_mem_size;
|
||||
}
|
||||
default:
|
||||
pbus_size_io(bus);
|
||||
pbus_size_io(bus, min_io_size);
|
||||
/* If the bridge supports prefetchable range, size it
|
||||
separately. If it doesn't, or its prefetchable window
|
||||
has already been allocated by arch code, try
|
||||
@@ -521,9 +531,11 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
|
||||
resources. */
|
||||
mask = IORESOURCE_MEM;
|
||||
prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH;
|
||||
if (pbus_size_mem(bus, prefmask, prefmask))
|
||||
if (pbus_size_mem(bus, prefmask, prefmask, min_mem_size))
|
||||
mask = prefmask; /* Success, size non-prefetch only. */
|
||||
pbus_size_mem(bus, mask, IORESOURCE_MEM);
|
||||
else
|
||||
min_mem_size += min_mem_size;
|
||||
pbus_size_mem(bus, mask, IORESOURCE_MEM, min_mem_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user