aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/setup-bus.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-05-23 18:39:34 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-05-23 18:39:34 -0400
commit5e152b4c9e0fce6149c74406346a7ae7e7a17727 (patch)
tree12503a50142797c1babfd87099c193b3e4d54f93 /drivers/pci/setup-bus.c
parenta77febbef105554c5a37241cf903f48ab7bc03c7 (diff)
parent9251bac97d47fdaea406ea0595c2d0aa50022f12 (diff)
Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (27 commits) PCI: Don't use dmi_name_in_vendors in quirk PCI: remove unused AER functions PCI/sysfs: move bus cpuaffinity to class dev_attrs PCI: add rescan to /sys/.../pci_bus/.../ PCI: update bridge resources to get more big ranges when allocating space (again) KVM: Use pci_store/load_saved_state() around VM device usage PCI: Add interfaces to store and load the device saved state PCI: Track the size of each saved capability data area PCI/e1000e: Add and use pci_disable_link_state_locked() x86/PCI: derive pcibios_last_bus from ACPI MCFG PCI: add latency tolerance reporting enable/disable support PCI: add OBFF enable/disable support PCI: add ID-based ordering enable/disable support PCI hotplug: acpiphp: assume device is in state D0 after powering on a slot. PCI: Set PCIE maxpayload for card during hotplug insertion PCI/ACPI: Report _OSC control mask returned on failure to get control x86/PCI: irq and pci_ids patch for Intel Panther Point DeviceIDs PCI: handle positive error codes PCI: check pci_vpd_pci22_wait() return PCI: Use ICH6_GPIO_EN in ich6_lpc_acpi_gpio ... Fix up trivial conflicts in include/linux/pci_ids.h: commit a6e5e2be4461 moved the intel SMBUS ID definitons to the i2c-i801.c driver.
Diffstat (limited to 'drivers/pci/setup-bus.c')
-rw-r--r--drivers/pci/setup-bus.c125
1 files changed, 117 insertions, 8 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index a806cb321d2..1e9e5a5b8c8 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -991,30 +991,139 @@ static void pci_bus_dump_resources(struct pci_bus *bus)
991 } 991 }
992} 992}
993 993
994static int __init pci_bus_get_depth(struct pci_bus *bus)
995{
996 int depth = 0;
997 struct pci_dev *dev;
998
999 list_for_each_entry(dev, &bus->devices, bus_list) {
1000 int ret;
1001 struct pci_bus *b = dev->subordinate;
1002 if (!b)
1003 continue;
1004
1005 ret = pci_bus_get_depth(b);
1006 if (ret + 1 > depth)
1007 depth = ret + 1;
1008 }
1009
1010 return depth;
1011}
1012static int __init pci_get_max_depth(void)
1013{
1014 int depth = 0;
1015 struct pci_bus *bus;
1016
1017 list_for_each_entry(bus, &pci_root_buses, node) {
1018 int ret;
1019
1020 ret = pci_bus_get_depth(bus);
1021 if (ret > depth)
1022 depth = ret;
1023 }
1024
1025 return depth;
1026}
1027
1028/*
1029 * first try will not touch pci bridge res
1030 * second and later try will clear small leaf bridge res
1031 * will stop till to the max deepth if can not find good one
1032 */
994void __init 1033void __init
995pci_assign_unassigned_resources(void) 1034pci_assign_unassigned_resources(void)
996{ 1035{
997 struct pci_bus *bus; 1036 struct pci_bus *bus;
998 struct resource_list_x add_list; /* list of resources that 1037 struct resource_list_x add_list; /* list of resources that
999 want additional resources */ 1038 want additional resources */
1039 int tried_times = 0;
1040 enum release_type rel_type = leaf_only;
1041 struct resource_list_x head, *list;
1042 unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
1043 IORESOURCE_PREFETCH;
1044 unsigned long failed_type;
1045 int max_depth = pci_get_max_depth();
1046 int pci_try_num;
1047
1048
1049 head.next = NULL;
1000 add_list.next = NULL; 1050 add_list.next = NULL;
1051
1052 pci_try_num = max_depth + 1;
1053 printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n",
1054 max_depth, pci_try_num);
1055
1056again:
1001 /* Depth first, calculate sizes and alignments of all 1057 /* Depth first, calculate sizes and alignments of all
1002 subordinate buses. */ 1058 subordinate buses. */
1003 list_for_each_entry(bus, &pci_root_buses, node) { 1059 list_for_each_entry(bus, &pci_root_buses, node)
1004 __pci_bus_size_bridges(bus, &add_list); 1060 __pci_bus_size_bridges(bus, &add_list);
1005 }
1006 1061
1007 /* Depth last, allocate resources and update the hardware. */ 1062 /* Depth last, allocate resources and update the hardware. */
1008 list_for_each_entry(bus, &pci_root_buses, node) { 1063 list_for_each_entry(bus, &pci_root_buses, node)
1009 __pci_bus_assign_resources(bus, &add_list, NULL); 1064 __pci_bus_assign_resources(bus, &add_list, &head);
1010 pci_enable_bridges(bus);
1011 }
1012 BUG_ON(add_list.next); 1065 BUG_ON(add_list.next);
1066 tried_times++;
1067
1068 /* any device complain? */
1069 if (!head.next)
1070 goto enable_and_dump;
1071 failed_type = 0;
1072 for (list = head.next; list;) {
1073 failed_type |= list->flags;
1074 list = list->next;
1075 }
1076 /*
1077 * io port are tight, don't try extra
1078 * or if reach the limit, don't want to try more
1079 */
1080 failed_type &= type_mask;
1081 if ((failed_type == IORESOURCE_IO) || (tried_times >= pci_try_num)) {
1082 free_list(resource_list_x, &head);
1083 goto enable_and_dump;
1084 }
1085
1086 printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n",
1087 tried_times + 1);
1088
1089 /* third times and later will not check if it is leaf */
1090 if ((tried_times + 1) > 2)
1091 rel_type = whole_subtree;
1092
1093 /*
1094 * Try to release leaf bridge's resources that doesn't fit resource of
1095 * child device under that bridge
1096 */
1097 for (list = head.next; list;) {
1098 bus = list->dev->bus;
1099 pci_bus_release_bridge_resources(bus, list->flags & type_mask,
1100 rel_type);
1101 list = list->next;
1102 }
1103 /* restore size and flags */
1104 for (list = head.next; list;) {
1105 struct resource *res = list->res;
1106
1107 res->start = list->start;
1108 res->end = list->end;
1109 res->flags = list->flags;
1110 if (list->dev->subordinate)
1111 res->flags = 0;
1112
1113 list = list->next;
1114 }
1115 free_list(resource_list_x, &head);
1116
1117 goto again;
1118
1119enable_and_dump:
1120 /* Depth last, update the hardware. */
1121 list_for_each_entry(bus, &pci_root_buses, node)
1122 pci_enable_bridges(bus);
1013 1123
1014 /* dump the resource on buses */ 1124 /* dump the resource on buses */
1015 list_for_each_entry(bus, &pci_root_buses, node) { 1125 list_for_each_entry(bus, &pci_root_buses, node)
1016 pci_bus_dump_resources(bus); 1126 pci_bus_dump_resources(bus);
1017 }
1018} 1127}
1019 1128
1020void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) 1129void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)