aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2008-08-26 12:00:57 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-10-16 12:24:52 -0400
commit99178b036c97293a65004ff5ec5cff9f833aaecd (patch)
treec83ac6855710038ad9846f79b952b7fdcca528f8 /drivers/pci
parent26853ab6f9a4c482be4b638477335704724d4854 (diff)
Driver core: add bus_sort_breadthfirst() function
The PCI core wants to reorder the devices in the bus list. So move this functionality out of the pci core and into the driver core so that anyone else can also do this if needed. This also lets us change how struct device is attached to drivers in the future without messing with the PCI core. Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/probe.c50
1 files changed, 5 insertions, 45 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 36698e57b97f..dd9161a054e1 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1237,8 +1237,11 @@ EXPORT_SYMBOL(pci_scan_bridge);
1237EXPORT_SYMBOL_GPL(pci_scan_child_bus); 1237EXPORT_SYMBOL_GPL(pci_scan_child_bus);
1238#endif 1238#endif
1239 1239
1240static int __init pci_sort_bf_cmp(const struct pci_dev *a, const struct pci_dev *b) 1240static int __init pci_sort_bf_cmp(const struct device *d_a, const struct device *d_b)
1241{ 1241{
1242 const struct pci_dev *a = to_pci_dev(d_a);
1243 const struct pci_dev *b = to_pci_dev(d_b);
1244
1242 if (pci_domain_nr(a->bus) < pci_domain_nr(b->bus)) return -1; 1245 if (pci_domain_nr(a->bus) < pci_domain_nr(b->bus)) return -1;
1243 else if (pci_domain_nr(a->bus) > pci_domain_nr(b->bus)) return 1; 1246 else if (pci_domain_nr(a->bus) > pci_domain_nr(b->bus)) return 1;
1244 1247
@@ -1251,50 +1254,7 @@ static int __init pci_sort_bf_cmp(const struct pci_dev *a, const struct pci_dev
1251 return 0; 1254 return 0;
1252} 1255}
1253 1256
1254/*
1255 * Yes, this forcably breaks the klist abstraction temporarily. It
1256 * just wants to sort the klist, not change reference counts and
1257 * take/drop locks rapidly in the process. It does all this while
1258 * holding the lock for the list, so objects can't otherwise be
1259 * added/removed while we're swizzling.
1260 */
1261static void __init pci_insertion_sort_klist(struct pci_dev *a, struct list_head *list)
1262{
1263 struct list_head *pos;
1264 struct klist_node *n;
1265 struct device *dev;
1266 struct pci_dev *b;
1267
1268 list_for_each(pos, list) {
1269 n = container_of(pos, struct klist_node, n_node);
1270 dev = container_of(n, struct device, knode_bus);
1271 b = to_pci_dev(dev);
1272 if (pci_sort_bf_cmp(a, b) <= 0) {
1273 list_move_tail(&a->dev.knode_bus.n_node, &b->dev.knode_bus.n_node);
1274 return;
1275 }
1276 }
1277 list_move_tail(&a->dev.knode_bus.n_node, list);
1278}
1279
1280void __init pci_sort_breadthfirst(void) 1257void __init pci_sort_breadthfirst(void)
1281{ 1258{
1282 LIST_HEAD(sorted_devices); 1259 bus_sort_breadthfirst(&pci_bus_type, &pci_sort_bf_cmp);
1283 struct list_head *pos, *tmp;
1284 struct klist_node *n;
1285 struct device *dev;
1286 struct pci_dev *pdev;
1287 struct klist *device_klist;
1288
1289 device_klist = bus_get_device_klist(&pci_bus_type);
1290
1291 spin_lock(&device_klist->k_lock);
1292 list_for_each_safe(pos, tmp, &device_klist->k_list) {
1293 n = container_of(pos, struct klist_node, n_node);
1294 dev = container_of(n, struct device, knode_bus);
1295 pdev = to_pci_dev(dev);
1296 pci_insertion_sort_klist(pdev, &sorted_devices);
1297 }
1298 list_splice(&sorted_devices, &device_klist->k_list);
1299 spin_unlock(&device_klist->k_lock);
1300} 1260}