aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/setup-bus.c
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2010-01-22 04:02:27 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-02-22 19:17:25 -0500
commit32180e402f9ff1f3389c99edf3f393425e706080 (patch)
tree8bdc06675bdaf8dc79916e96e4ca666343bb1b23 /drivers/pci/setup-bus.c
parent9789ac979b6b6ae6cc09f7b29c88e95ecb14ec39 (diff)
PCI: pciehp: second try to get big range for pcie devices
Handle the case where the slot bridge that doesn't get a pre-allocated resource big enough to handle its child resources.. For example pcie devices need 256M, but the bridge only gets 2M preallocated. Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/setup-bus.c')
-rw-r--r--drivers/pci/setup-bus.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index b19a56b8b17a..ed545f669459 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -964,12 +964,61 @@ enable_and_dump:
964void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) 964void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
965{ 965{
966 struct pci_bus *parent = bridge->subordinate; 966 struct pci_bus *parent = bridge->subordinate;
967 int tried_times = 0;
968 struct resource_list_x head, *list;
967 int retval; 969 int retval;
970 unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
971 IORESOURCE_PREFETCH;
972
973 head.next = NULL;
968 974
975again:
969 pci_bus_size_bridges(parent); 976 pci_bus_size_bridges(parent);
970 __pci_bridge_assign_resources(bridge, NULL); 977 __pci_bridge_assign_resources(bridge, &head);
971 retval = pci_reenable_device(bridge); 978 retval = pci_reenable_device(bridge);
972 pci_set_master(bridge); 979 pci_set_master(bridge);
973 pci_enable_bridges(parent); 980 pci_enable_bridges(parent);
981
982 tried_times++;
983
984 if (!head.next)
985 return;
986
987 if (tried_times >= 2) {
988 /* still fail, don't need to try more */
989 free_failed_list(&head);
990 return;
991 }
992
993 printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n",
994 tried_times + 1);
995
996 /*
997 * Try to release leaf bridge's resources that doesn't fit resource of
998 * child device under that bridge
999 */
1000 for (list = head.next; list;) {
1001 struct pci_bus *bus = list->dev->bus;
1002 unsigned long flags = list->flags;
1003
1004 pci_bus_release_bridge_resources(bus, flags & type_mask,
1005 whole_subtree);
1006 list = list->next;
1007 }
1008 /* restore size and flags */
1009 for (list = head.next; list;) {
1010 struct resource *res = list->res;
1011
1012 res->start = list->start;
1013 res->end = list->end;
1014 res->flags = list->flags;
1015 if (list->dev->subordinate)
1016 res->flags = 0;
1017
1018 list = list->next;
1019 }
1020 free_failed_list(&head);
1021
1022 goto again;
974} 1023}
975EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources); 1024EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);