diff options
author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2010-02-23 12:24:36 -0500 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2010-02-23 12:43:37 -0500 |
commit | 2fe2abf896c1e7a0ee65faaf3ef0ce654848abbd (patch) | |
tree | f066d5c94bbed5ca3556b4d2f0c4b3a9795b6eff /include/linux | |
parent | 89a74ecccd1f78e51faf6287e5c0e93a92ac096e (diff) |
PCI: augment bus resource table with a list
Previously we used a table of size PCI_BUS_NUM_RESOURCES (16) for resources
forwarded to a bus by its upstream bridge. We've increased this size
several times when the table overflowed.
But there's no good limit on the number of resources because host bridges
and subtractive decode bridges can forward any number of ranges to their
secondary buses.
This patch reduces the table to only PCI_BRIDGE_RESOURCE_NUM (4) entries,
which corresponds to the number of windows a PCI-to-PCI (3) or CardBus (4)
bridge can positively decode. Any additional resources, e.g., PCI host
bridge windows or subtractively-decoded regions, are kept in a list.
I'd prefer a single list rather than this split table/list approach, but
that requires simultaneous changes to every architecture. This approach
only requires immediate changes where we set up (a) host bridges with more
than four windows and (b) subtractive-decode P2P bridges, and we can
incrementally change other architectures to use the list.
Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/pci.h | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/include/linux/pci.h b/include/linux/pci.h index 2ff9d26a078f..e19a69613d8f 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -364,9 +364,26 @@ static inline void pci_add_saved_cap(struct pci_dev *pci_dev, | |||
364 | hlist_add_head(&new_cap->next, &pci_dev->saved_cap_space); | 364 | hlist_add_head(&new_cap->next, &pci_dev->saved_cap_space); |
365 | } | 365 | } |
366 | 366 | ||
367 | #ifndef PCI_BUS_NUM_RESOURCES | 367 | /* |
368 | #define PCI_BUS_NUM_RESOURCES 16 | 368 | * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond |
369 | #endif | 369 | * to P2P or CardBus bridge windows) go in a table. Additional ones (for |
370 | * buses below host bridges or subtractive decode bridges) go in the list. | ||
371 | * Use pci_bus_for_each_resource() to iterate through all the resources. | ||
372 | */ | ||
373 | |||
374 | /* | ||
375 | * PCI_SUBTRACTIVE_DECODE means the bridge forwards the window implicitly | ||
376 | * and there's no way to program the bridge with the details of the window. | ||
377 | * This does not apply to ACPI _CRS windows, even with the _DEC subtractive- | ||
378 | * decode bit set, because they are explicit and can be programmed with _SRS. | ||
379 | */ | ||
380 | #define PCI_SUBTRACTIVE_DECODE 0x1 | ||
381 | |||
382 | struct pci_bus_resource { | ||
383 | struct list_head list; | ||
384 | struct resource *res; | ||
385 | unsigned int flags; | ||
386 | }; | ||
370 | 387 | ||
371 | #define PCI_REGION_FLAG_MASK 0x0fU /* These bits of resource flags tell us the PCI region flags */ | 388 | #define PCI_REGION_FLAG_MASK 0x0fU /* These bits of resource flags tell us the PCI region flags */ |
372 | 389 | ||
@@ -377,8 +394,8 @@ struct pci_bus { | |||
377 | struct list_head devices; /* list of devices on this bus */ | 394 | struct list_head devices; /* list of devices on this bus */ |
378 | struct pci_dev *self; /* bridge device as seen by parent */ | 395 | struct pci_dev *self; /* bridge device as seen by parent */ |
379 | struct list_head slots; /* list of slots on this bus */ | 396 | struct list_head slots; /* list of slots on this bus */ |
380 | struct resource *resource[PCI_BUS_NUM_RESOURCES]; | 397 | struct resource *resource[PCI_BRIDGE_RESOURCE_NUM]; |
381 | /* address space routed to this bus */ | 398 | struct list_head resources; /* address space routed to this bus */ |
382 | 399 | ||
383 | struct pci_ops *ops; /* configuration access functions */ | 400 | struct pci_ops *ops; /* configuration access functions */ |
384 | void *sysdata; /* hook for sys-specific extension */ | 401 | void *sysdata; /* hook for sys-specific extension */ |
@@ -829,8 +846,14 @@ int pci_request_selected_regions_exclusive(struct pci_dev *, int, const char *); | |||
829 | void pci_release_selected_regions(struct pci_dev *, int); | 846 | void pci_release_selected_regions(struct pci_dev *, int); |
830 | 847 | ||
831 | /* drivers/pci/bus.c */ | 848 | /* drivers/pci/bus.c */ |
849 | void pci_bus_add_resource(struct pci_bus *bus, struct resource *res, unsigned int flags); | ||
850 | struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n); | ||
851 | void pci_bus_remove_resources(struct pci_bus *bus); | ||
852 | |||
832 | #define pci_bus_for_each_resource(bus, res, i) \ | 853 | #define pci_bus_for_each_resource(bus, res, i) \ |
833 | for (i = 0; res = bus->resource[i], i < PCI_BUS_NUM_RESOURCES; i++) | 854 | for (i = 0; \ |
855 | (res = pci_bus_resource_n(bus, i)) || i < PCI_BRIDGE_RESOURCE_NUM; \ | ||
856 | i++) | ||
834 | 857 | ||
835 | int __must_check pci_bus_alloc_resource(struct pci_bus *bus, | 858 | int __must_check pci_bus_alloc_resource(struct pci_bus *bus, |
836 | struct resource *res, resource_size_t size, | 859 | struct resource *res, resource_size_t size, |