diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 39b9b58c6974..5aee1c0169ea 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -980,6 +980,56 @@ struct klist *bus_get_device_klist(struct bus_type *bus)
 }
 EXPORT_SYMBOL_GPL(bus_get_device_klist);
 
+/*
+ * Yes, this forcably breaks the klist abstraction temporarily.  It
+ * just wants to sort the klist, not change reference counts and
+ * take/drop locks rapidly in the process.  It does all this while
+ * holding the lock for the list, so objects can't otherwise be
+ * added/removed while we're swizzling.
+ */
+static void device_insertion_sort_klist(struct device *a, struct list_head *list,
+					int (*compare)(const struct device *a,
+							const struct device *b))
+{
+	struct list_head *pos;
+	struct klist_node *n;
+	struct device *b;
+
+	list_for_each(pos, list) {
+		n = container_of(pos, struct klist_node, n_node);
+		b = container_of(n, struct device, knode_bus);
+		if (compare(a, b) <= 0) {
+			list_move_tail(&a->knode_bus.n_node,
+				       &b->knode_bus.n_node);
+			return;
+		}
+	}
+	list_move_tail(&a->knode_bus.n_node, list);
+}
+
+void bus_sort_breadthfirst(struct bus_type *bus,
+			   int (*compare)(const struct device *a,
+					  const struct device *b))
+{
+	LIST_HEAD(sorted_devices);
+	struct list_head *pos, *tmp;
+	struct klist_node *n;
+	struct device *dev;
+	struct klist *device_klist;
+
+	device_klist = bus_get_device_klist(bus);
+
+	spin_lock(&device_klist->k_lock);
+	list_for_each_safe(pos, tmp, &device_klist->k_list) {
+		n = container_of(pos, struct klist_node, n_node);
+		dev = container_of(n, struct device, knode_bus);
+		device_insertion_sort_klist(dev, &sorted_devices, compare);
+	}
+	list_splice(&sorted_devices, &device_klist->k_list);
+	spin_unlock(&device_klist->k_lock);
+}
+EXPORT_SYMBOL_GPL(bus_sort_breadthfirst);
+
 int __init buses_init(void)
 {
 	bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
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);
 EXPORT_SYMBOL_GPL(pci_scan_child_bus);
 #endif
 
-static int __init pci_sort_bf_cmp(const struct pci_dev *a, const struct pci_dev *b)
+static int __init pci_sort_bf_cmp(const struct device *d_a, const struct device *d_b)
 {
+	const struct pci_dev *a = to_pci_dev(d_a);
+	const struct pci_dev *b = to_pci_dev(d_b);
+
 	if      (pci_domain_nr(a->bus) < pci_domain_nr(b->bus)) return -1;
 	else if (pci_domain_nr(a->bus) > pci_domain_nr(b->bus)) return  1;
 
@@ -1251,50 +1254,7 @@ static int __init pci_sort_bf_cmp(const struct pci_dev *a, const struct pci_dev
 	return 0;
 }
 
-/*
- * Yes, this forcably breaks the klist abstraction temporarily.  It
- * just wants to sort the klist, not change reference counts and
- * take/drop locks rapidly in the process.  It does all this while
- * holding the lock for the list, so objects can't otherwise be
- * added/removed while we're swizzling.
- */
-static void __init pci_insertion_sort_klist(struct pci_dev *a, struct list_head *list)
-{
-	struct list_head *pos;
-	struct klist_node *n;
-	struct device *dev;
-	struct pci_dev *b;
-
-	list_for_each(pos, list) {
-		n = container_of(pos, struct klist_node, n_node);
-		dev = container_of(n, struct device, knode_bus);
-		b = to_pci_dev(dev);
-		if (pci_sort_bf_cmp(a, b) <= 0) {
-			list_move_tail(&a->dev.knode_bus.n_node, &b->dev.knode_bus.n_node);
-			return;
-		}
-	}
-	list_move_tail(&a->dev.knode_bus.n_node, list);
-}
-
 void __init pci_sort_breadthfirst(void)
 {
-	LIST_HEAD(sorted_devices);
-	struct list_head *pos, *tmp;
-	struct klist_node *n;
-	struct device *dev;
-	struct pci_dev *pdev;
-	struct klist *device_klist;
-
-	device_klist = bus_get_device_klist(&pci_bus_type);
-
-	spin_lock(&device_klist->k_lock);
-	list_for_each_safe(pos, tmp, &device_klist->k_list) {
-		n = container_of(pos, struct klist_node, n_node);
-		dev = container_of(n, struct device, knode_bus);
-		pdev = to_pci_dev(dev);
-		pci_insertion_sort_klist(pdev, &sorted_devices);
-	}
-	list_splice(&sorted_devices, &device_klist->k_list);
-	spin_unlock(&device_klist->k_lock);
+	bus_sort_breadthfirst(&pci_bus_type, &pci_sort_bf_cmp);
 }
diff --git a/include/linux/device.h b/include/linux/device.h
index ec90e79f6a00..987f5912720a 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -90,6 +90,9 @@ int __must_check bus_for_each_drv(struct bus_type *bus,
 				  struct device_driver *start, void *data,
 				  int (*fn)(struct device_driver *, void *));
 
+void bus_sort_breadthfirst(struct bus_type *bus,
+			   int (*compare)(const struct device *a,
+					  const struct device *b));
 /*
  * Bus notifiers: Get notified of addition/removal of devices
  * and binding/unbinding of drivers to devices.