linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators
@ 2013-05-26 15:52 Jiang Liu
  2013-05-26 15:52 ` [PATCH v3, part2 01/20] PCI: introduce " Jiang Liu
                   ` (19 more replies)
  0 siblings, 20 replies; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:52 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel

This is the second part of PCI bus lock patch series, it's based on
https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git

And the first part of the PCI bus lock patch series could be found at:
http://marc.info/?l=linux-pci&m=136948986401098&w=2

You can access the git tree at:

Introduce hotplug-safe PCI bus iterators as below, which hold a
reference on the returned PCI bus object.
bool pci_bus_exists(int domain, int busnr);
struct pci_bus *pci_get_bus(int domain, int busnr);
struct pci_bus *pci_get_next_bus(struct pci_bus *from);
struct pci_bus *pci_get_next_root_bus(struct pci_bus *from);
#define for_each_pci_bus(b) for (b = NULL; (b = pci_get_next_bus(b)); )
#define for_each_pci_root_bus(b)  \
		for (b = NULL; (b = pci_get_next_root_bus(b)); )

The long-term goal is to remove hotplug-unsafe pci_find_bus(),
pci_find_next_bus() and the global pci_root_buses list.

These new interfaces may be a little slower than existing interfaces,
but it should be acceptable because they are not used on hot paths.

V1->V2:
1) address review comments for V1

Jiang Liu (20):
  PCI: introduce hotplug-safe PCI bus iterators
  PCI, core: use hotplug-safe iterators to walk PCI buses
  PCI, hotplug: use hotplug-safe iterators to walk PCI buses
  PCI, IOV: hold a reference to PCI bus when creating virtual PCI
    devices
  PCI, Alpha: use hotplug-safe iterators to walk PCI buses
  PCI, FRV: use hotplug-safe iterators to walk PCI buses
  PCI, IA64: use hotplug-safe iterators to walk PCI buses
  PCI, Microblaze: use hotplug-safe iterators to walk PCI buses
  PCI, mn10300: use hotplug-safe iterators to walk PCI buses
  PCI, PPC: use hotplug-safe iterators to walk PCI buses
  PCI, SPARC: use hotplug-safe iterators to walk PCI buses
  PCI, x86: use hotplug-safe iterators to walk PCI buses
  PCI, ACPI: use hotplug-safe iterators to walk PCI buses
  PCI, DRM: use hotplug-safe iterators to walk PCI buses
  PCI, EDAC: use hotplug-safe PCI bus iterators to walk PCI buses
  PCI, via-camera: use hotplug-safe iterators to walk PCI buses
  PCI, iommu: use hotplug-safe iterators to walk PCI buses
  PCI, eeepc-laptop: use hotplug-safe iterators to walk PCI buses
  PCI, asus-wmi: use hotplug-safe iterators to walk PCI buses
  PCI, ARM: use hotplug-safe PCI bus iterators to walk PCI buses

 arch/alpha/kernel/pci.c                 |   2 +-
 arch/arm/kernel/bios32.c                |  13 +--
 arch/arm/mach-footbridge/dc21285.c      |  12 ++-
 arch/frv/mb93090-mb00/pci-frv.c         |   5 +-
 arch/frv/mb93090-mb00/pci-vdk.c         |   2 +-
 arch/ia64/hp/common/sba_iommu.c         |   2 +-
 arch/ia64/sn/kernel/io_common.c         |   2 +-
 arch/ia64/sn/pci/tioca_provider.c       |   3 +-
 arch/microblaze/pci/pci-common.c        |   4 +-
 arch/mn10300/unit-asb2305/pci-asb2305.c |   5 +-
 arch/powerpc/kernel/pci-common.c        |   4 +-
 arch/powerpc/kernel/pci_64.c            |  22 ++---
 arch/sparc/kernel/pci.c                 |   4 +-
 arch/x86/pci/acpi.c                     |   3 +-
 arch/x86/pci/common.c                   |   3 +-
 arch/x86/pci/i386.c                     |   9 +-
 arch/x86/pci/irq.c                      |   2 +-
 arch/x86/pci/legacy.c                   |   2 +-
 drivers/acpi/reboot.c                   |   3 +-
 drivers/edac/i7core_edac.c              |   2 +-
 drivers/gpu/drm/drm_fops.c              |   6 +-
 drivers/iommu/amd_iommu.c               |   4 +-
 drivers/iommu/dmar.c                    |   6 +-
 drivers/media/platform/via-camera.c     |  12 ++-
 drivers/pci/hotplug-pci.c               |   2 +-
 drivers/pci/hotplug/ibmphp_core.c       |   8 +-
 drivers/pci/hotplug/ibmphp_ebda.c       |   8 +-
 drivers/pci/hotplug/sgi_hotplug.c       |   3 +-
 drivers/pci/hotplug/shpchp_sysfs.c      |   2 +-
 drivers/pci/iov.c                       |  14 +--
 drivers/pci/pci-sysfs.c                 |   2 +-
 drivers/pci/pci.h                       |   1 +
 drivers/pci/pcie/pme.c                  |   5 +-
 drivers/pci/probe.c                     |  17 ++--
 drivers/pci/search.c                    | 159 ++++++++++++++++++++++++++------
 drivers/pci/setup-bus.c                 |  14 ++-
 drivers/pci/xen-pcifront.c              |   3 +-
 drivers/platform/x86/asus-wmi.c         |   9 +-
 drivers/platform/x86/eeepc-laptop.c     |   5 +-
 include/linux/pci.h                     |  23 ++++-
 40 files changed, 278 insertions(+), 129 deletions(-)

-- 
1.8.1.2


^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 01/20] PCI: introduce hotplug-safe PCI bus iterators
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
@ 2013-05-26 15:52 ` Jiang Liu
  2013-05-28  4:22   ` Yinghai Lu
  2013-06-17 20:06   ` Bjorn Helgaas
  2013-05-26 15:52 ` [PATCH v3, part2 02/20] PCI, core: use hotplug-safe iterators to walk PCI buses Jiang Liu
                   ` (18 subsequent siblings)
  19 siblings, 2 replies; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:52 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel

Introduce hotplug-safe PCI bus iterators as below, which hold a
reference on the returned PCI bus object.
bool pci_bus_exists(int domain, int busnr);
struct pci_bus *pci_get_bus(int domain, int busnr);
struct pci_bus *pci_get_next_bus(struct pci_bus *from);
struct pci_bus *pci_get_next_root_bus(struct pci_bus *from);
#define for_each_pci_bus(b) for (b = NULL; (b = pci_get_next_bus(b)); )
#define for_each_pci_root_bus(b)  \
		for (b = NULL; (b = pci_get_next_root_bus(b)); )

The long-term goal is to remove hotplug-unsafe pci_find_bus(),
pci_find_next_bus() and the global pci_root_buses list.

These new interfaces may be a littler slower than existing interfaces,
but it should be acceptable because they are not used on hot paths.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
Cc: linux-pci@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/pci/pci.h    |   1 +
 drivers/pci/probe.c  |   2 +-
 drivers/pci/search.c | 159 +++++++++++++++++++++++++++++++++++++++++----------
 include/linux/pci.h  |  23 +++++++-
 4 files changed, 153 insertions(+), 32 deletions(-)

diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 68678ed..8fe15f6 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -126,6 +126,7 @@ static inline void pci_remove_legacy_files(struct pci_bus *bus) { return; }
 
 /* Lock for read/write access to pci device and bus lists */
 extern struct rw_semaphore pci_bus_sem;
+extern struct class pcibus_class;
 
 extern raw_spinlock_t pci_lock;
 
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 2830070..1004a05 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -93,7 +93,7 @@ static void release_pcibus_dev(struct device *dev)
 	kfree(pci_bus);
 }
 
-static struct class pcibus_class = {
+struct class pcibus_class = {
 	.name		= "pci_bus",
 	.dev_release	= &release_pcibus_dev,
 	.dev_attrs	= pcibus_dev_attrs,
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index d0627fa..16ccaf8 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -52,20 +52,27 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev)
 	return tmp;
 }
 
-static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
+struct pci_bus_match_arg {
+	int domain;
+	int bus;
+};
+
+static int pci_match_bus(struct device *dev, const void *data)
 {
-	struct pci_bus* child;
-	struct list_head *tmp;
+	struct pci_bus *bus = to_pci_bus(dev);
+	const struct pci_bus_match_arg *arg = data;
 
-	if(bus->number == busnr)
-		return bus;
+	return (pci_domain_nr(bus) == arg->domain && bus->number == arg->bus);
+}
 
-	list_for_each(tmp, &bus->children) {
-		child = pci_do_find_bus(pci_bus_b(tmp), busnr);
-		if(child)
-			return child;
-	}
-	return NULL;
+static int pci_match_next_bus(struct device *dev, const void *data)
+{
+	return 1;
+}
+
+static int pci_match_next_root_bus(struct device *dev, const void *data)
+{
+	return pci_is_root_bus(to_pci_bus(dev));
 }
 
 /**
@@ -76,20 +83,19 @@ static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
  * Given a PCI bus number and domain number, the desired PCI bus is located
  * in the global list of PCI buses.  If the bus is found, a pointer to its
  * data structure is returned.  If no bus is found, %NULL is returned.
+ *
+ * Note: it's not hotplug safe, the returned bus may be destroyed at any time.
+ * Please use pci_get_bus() instead which holds a reference on the returned
+ * PCI bus.
  */
-struct pci_bus * pci_find_bus(int domain, int busnr)
+struct pci_bus *pci_find_bus(int domain, int busnr)
 {
-	struct pci_bus *bus = NULL;
-	struct pci_bus *tmp_bus;
+	struct pci_bus *bus;
 
-	while ((bus = pci_find_next_bus(bus)) != NULL)  {
-		if (pci_domain_nr(bus) != domain)
-			continue;
-		tmp_bus = pci_do_find_bus(bus, busnr);
-		if (tmp_bus)
-			return tmp_bus;
-	}
-	return NULL;
+	bus = pci_get_bus(domain, busnr);
+	pci_bus_put(bus);
+
+	return bus;
 }
 
 /**
@@ -100,21 +106,114 @@ struct pci_bus * pci_find_bus(int domain, int busnr)
  * initiated by passing %NULL as the @from argument.  Otherwise if
  * @from is not %NULL, searches continue from next device on the
  * global list.
+ *
+ * Note: it's not hotplug safe, the returned bus may be destroyed at any time.
+ * Please use pci_get_next_root_bus() instead which holds a reference
+ * on the returned PCI root bus.
  */
 struct pci_bus * 
 pci_find_next_bus(const struct pci_bus *from)
 {
-	struct list_head *n;
-	struct pci_bus *b = NULL;
+	struct device *dev = from ? (struct device *)&from->dev : NULL;
+
+	dev = class_find_device(&pcibus_class, dev, NULL,
+				&pci_match_next_root_bus);
+	if (dev) {
+		put_device(dev);
+		return to_pci_bus(dev);
+	}
+
+	return NULL;
+}
+
+bool pci_bus_exists(int domain, int busnr)
+{
+	struct device *dev;
+	struct pci_bus_match_arg arg = { domain, busnr };
 
 	WARN_ON(in_interrupt());
-	down_read(&pci_bus_sem);
-	n = from ? from->node.next : pci_root_buses.next;
-	if (n != &pci_root_buses)
-		b = pci_bus_b(n);
-	up_read(&pci_bus_sem);
-	return b;
+	dev = class_find_device(&pcibus_class, NULL, &arg, &pci_match_bus);
+	if (dev)
+		put_device(dev);
+
+	return dev != NULL;
+}
+EXPORT_SYMBOL(pci_bus_exists);
+
+/**
+ * pci_get_bus - locate PCI bus from a given domain and bus number
+ * @domain: number of PCI domain to search
+ * @busnr: number of desired PCI bus
+ *
+ * Given a PCI bus number and domain number, the desired PCI bus is located.
+ * If the bus is found, a pointer to its data structure is returned.
+ * If no bus is found, %NULL is returned.
+ * Caller needs to release the returned bus by calling pci_bus_put().
+ */
+struct pci_bus *pci_get_bus(int domain, int busnr)
+{
+	struct device *dev;
+	struct pci_bus_match_arg arg = { domain, busnr };
+
+	WARN_ON(in_interrupt());
+	dev = class_find_device(&pcibus_class, NULL, &arg, &pci_match_bus);
+	if (dev)
+		return to_pci_bus(dev);
+
+	return NULL;
+}
+EXPORT_SYMBOL(pci_get_bus);
+
+/**
+ * pci_get_next_bus - begin or continue searching for a PCI bus
+ * @from: Previous PCI bus found, or %NULL for new search.
+ *
+ * Iterates through the list of known PCI busses. If a PCI bus is found,
+ * the reference count to the bus is incremented and a pointer to it is
+ * returned. Otherwise, %NULL is returned. A new search is initiated by
+ * passing %NULL as the @from argument. Otherwise if @from is not %NULL,
+ * searches continue from next bus on the global list. The reference count
+ * for @from is always decremented if it is not %NULL.
+ */
+struct pci_bus *pci_get_next_bus(struct pci_bus *from)
+{
+	struct device *dev = from ? &from->dev : NULL;
+
+	WARN_ON(in_interrupt());
+	dev = class_find_device(&pcibus_class, dev, NULL, &pci_match_next_bus);
+	pci_bus_put(from);
+	if (dev)
+		return to_pci_bus(dev);
+
+	return NULL;
+}
+EXPORT_SYMBOL(pci_get_next_bus);
+
+/**
+ * pci_find_next_root_bus - begin or continue searching for a PCI root bus
+ * @from: Previous PCI bus found, or %NULL for new search.
+ *
+ * Iterates through the list of known PCI root busses. If a PCI bus is found,
+ * the reference count to the root bus is incremented and a pointer to it is
+ * returned. Otherwise, %NULL is returned. A new search is initiated by
+ * passing %NULL as the @from argument. Otherwise if @from is not %NULL,
+ * searches continue from next root bus on the global list. The reference
+ * count for @from is always decremented if it is not %NULL.
+ */
+struct pci_bus *pci_get_next_root_bus(struct pci_bus *from)
+{
+	struct device *dev = from ? &from->dev : NULL;
+
+	WARN_ON(in_interrupt());
+	dev = class_find_device(&pcibus_class, dev, NULL,
+				&pci_match_next_root_bus);
+	pci_bus_put(from);
+	if (dev)
+		return to_pci_bus(dev);
+
+	return NULL;
 }
+EXPORT_SYMBOL(pci_get_next_root_bus);
 
 /**
  * pci_get_slot - locate PCI device for a given PCI slot
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 7b23fa0..1e43423 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -454,6 +454,9 @@ struct pci_bus {
 
 #define pci_bus_b(n)	list_entry(n, struct pci_bus, node)
 #define to_pci_bus(n)	container_of(n, struct pci_bus, dev)
+#define for_each_pci_bus(b)	for (b = NULL; (b = pci_get_next_bus(b)); )
+#define for_each_pci_root_bus(b) \
+			for (b = NULL; (b = pci_get_next_root_bus(b)); )
 
 /*
  * Returns true if the pci bus is root (behind host-pci bridge),
@@ -718,7 +721,6 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
 void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
 			     struct pci_bus_region *region);
 void pcibios_scan_specific_bus(int busn);
-struct pci_bus *pci_find_bus(int domain, int busnr);
 void pci_bus_add_devices(const struct pci_bus *bus);
 struct pci_bus * __deprecated pci_scan_bus_parented(struct device *parent,
 			int bus, struct pci_ops *ops, void *sysdata);
@@ -778,8 +780,15 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap);
 int pci_find_next_ext_capability(struct pci_dev *dev, int pos, int cap);
 int pci_find_ht_capability(struct pci_dev *dev, int ht_cap);
 int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
+
+struct pci_bus *pci_find_bus(int domain, int busnr);
 struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
 
+bool pci_bus_exists(int domain, int busnr);
+struct pci_bus *pci_get_bus(int domain, int busnr);
+struct pci_bus *pci_get_next_bus(struct pci_bus *from);
+struct pci_bus *pci_get_next_root_bus(struct pci_bus *from);
+
 struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
 				struct pci_dev *from);
 struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
@@ -1430,6 +1439,18 @@ static inline void pci_unblock_cfg_access(struct pci_dev *dev)
 static inline struct pci_bus *pci_find_next_bus(const struct pci_bus *from)
 { return NULL; }
 
+static inline bool pci_bus_exists(int domain, int busnr)
+{ return false; }
+
+static inline struct pci_bus *pci_get_bus(int domain, int busnr)
+{ return NULL; }
+
+static inline struct pci_bus *pci_get_next_bus(struct pci_bus *from)
+{ return NULL; }
+
+static inline struct pci_bus *pci_get_next_root_bus(struct pci_bus *from)
+{ return NULL; }
+
 static inline struct pci_dev *pci_get_slot(struct pci_bus *bus,
 						unsigned int devfn)
 { return NULL; }
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 02/20] PCI, core: use hotplug-safe iterators to walk PCI buses
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
  2013-05-26 15:52 ` [PATCH v3, part2 01/20] PCI: introduce " Jiang Liu
@ 2013-05-26 15:52 ` Jiang Liu
  2013-05-26 15:53 ` [PATCH v3, part2 03/20] PCI, hotplug: " Jiang Liu
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:52 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel, Konrad Rzeszutek Wilk, Jeremy Fitzhardinge,
	Rafael J. Wysocki, xen-devel, virtualization

Enhance PCI core to use hotplug-safe iterators to walk PCI buses.

In other words, replace pci_find_bus(), pci_find_next_bus() and
pci_root_buses with pci_bus_exists(), pci_get_bus(), pci_get_next_bus()
and pci_get_next_root_bus() etc.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
Cc: linux-pci@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: xen-devel@lists.xensource.com
Cc: virtualization@lists.linux-foundation.org
---
 drivers/pci/pci-sysfs.c    |  2 +-
 drivers/pci/pcie/pme.c     |  5 +++--
 drivers/pci/probe.c        | 15 +++++++++------
 drivers/pci/setup-bus.c    | 14 ++++++--------
 drivers/pci/xen-pcifront.c |  3 ++-
 5 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 403da60..e2da5f3 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -296,7 +296,7 @@ static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf,
 
 	if (val) {
 		mutex_lock(&pci_remove_rescan_mutex);
-		while ((b = pci_find_next_bus(b)) != NULL)
+		for_each_pci_root_bus(b)
 			pci_rescan_bus(b);
 		mutex_unlock(&pci_remove_rescan_mutex);
 	}
diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c
index 795db1f..1ed38a3 100644
--- a/drivers/pci/pcie/pme.c
+++ b/drivers/pci/pcie/pme.c
@@ -132,7 +132,7 @@ static bool pcie_pme_from_pci_bridge(struct pci_bus *bus, u8 devfn)
 static void pcie_pme_handle_request(struct pci_dev *port, u16 req_id)
 {
 	u8 busnr = req_id >> 8, devfn = req_id & 0xff;
-	struct pci_bus *bus;
+	struct pci_bus *bus = NULL;
 	struct pci_dev *dev;
 	bool found = false;
 
@@ -161,7 +161,7 @@ static void pcie_pme_handle_request(struct pci_dev *port, u16 req_id)
 	}
 
 	/* Second, find the bus the source device is on. */
-	bus = pci_find_bus(pci_domain_nr(port->bus), busnr);
+	bus = pci_get_bus(pci_domain_nr(port->bus), busnr);
 	if (!bus)
 		goto out;
 
@@ -206,6 +206,7 @@ static void pcie_pme_handle_request(struct pci_dev *port, u16 req_id)
 	}
 
  out:
+	pci_bus_put(bus);
 	if (!found)
 		dev_dbg(&port->dev, "Spurious native PME interrupt!\n");
 }
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 1004a05..7c34362 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -752,7 +752,7 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
  */
 int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
 {
-	struct pci_bus *child;
+	struct pci_bus *child = NULL;
 	int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
 	u32 buses, i, j = 0;
 	u16 bctl;
@@ -804,7 +804,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
 		 * However, we continue to descend down the hierarchy and
 		 * scan remaining child buses.
 		 */
-		child = pci_find_bus(pci_domain_nr(bus), secondary);
+		child = pci_get_bus(pci_domain_nr(bus), secondary);
 		if (!child) {
 			child = pci_add_new_bus(bus, dev, secondary);
 			if (!child)
@@ -812,6 +812,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
 			child->primary = primary;
 			pci_bus_insert_busn_res(child, secondary, subordinate);
 			child->bridge_ctl = bctl;
+			pci_bus_get(child);
 		}
 
 		cmax = pci_scan_child_bus(child);
@@ -843,12 +844,13 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
 		/* Prevent assigning a bus number that already exists.
 		 * This can happen when a bridge is hot-plugged, so in
 		 * this case we only re-scan this bus. */
-		child = pci_find_bus(pci_domain_nr(bus), max+1);
+		child = pci_get_bus(pci_domain_nr(bus), max+1);
 		if (!child) {
 			child = pci_add_new_bus(bus, dev, ++max);
 			if (!child)
 				goto out;
 			pci_bus_insert_busn_res(child, max, 0xff);
+			pci_bus_get(child);
 		}
 		buses = (buses & 0xff000000)
 		      | ((unsigned int)(child->primary)     <<  0)
@@ -893,8 +895,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
 			 */
 			for (i=0; i<CARDBUS_RESERVE_BUSNR; i++) {
 				struct pci_bus *parent = bus;
-				if (pci_find_bus(pci_domain_nr(bus),
-							max+i+1))
+				if (pci_bus_exists(pci_domain_nr(bus), max+i+1))
 					break;
 				while (parent->parent) {
 					if ((!pcibios_assign_all_busses()) &&
@@ -949,6 +950,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
 
 out:
 	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl);
+	pci_bus_put(child);
 
 	return max;
 }
@@ -1710,10 +1712,11 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 	if (!b)
 		return NULL;
 
-	b2 = pci_find_bus(pci_domain_nr(b), bus);
+	b2 = pci_get_bus(pci_domain_nr(b), bus);
 	if (b2) {
 		/* If we already got to this bus through a different bridge, ignore it */
 		dev_dbg(&b2->dev, "bus already known\n");
+		pci_bus_put(b2);
 		goto err_out;
 	}
 
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 16abaaa..9a3e3f7 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1317,12 +1317,10 @@ static int __init pci_bus_get_depth(struct pci_bus *bus)
 }
 static int __init pci_get_max_depth(void)
 {
-	int depth = 0;
+	int ret, depth = 0;
 	struct pci_bus *bus;
 
-	list_for_each_entry(bus, &pci_root_buses, node) {
-		int ret;
-
+	for_each_pci_root_bus(bus) {
 		ret = pci_bus_get_depth(bus);
 		if (ret > depth)
 			depth = ret;
@@ -1423,11 +1421,11 @@ again:
 		add_list = &realloc_head;
 	/* Depth first, calculate sizes and alignments of all
 	   subordinate buses. */
-	list_for_each_entry(bus, &pci_root_buses, node)
+	for_each_pci_root_bus(bus)
 		__pci_bus_size_bridges(bus, add_list);
 
 	/* Depth last, allocate resources and update the hardware. */
-	list_for_each_entry(bus, &pci_root_buses, node)
+	for_each_pci_root_bus(bus)
 		__pci_bus_assign_resources(bus, add_list, &fail_head);
 	if (add_list)
 		BUG_ON(!list_empty(add_list));
@@ -1480,11 +1478,11 @@ again:
 
 enable_and_dump:
 	/* Depth last, update the hardware. */
-	list_for_each_entry(bus, &pci_root_buses, node)
+	for_each_pci_root_bus(bus)
 		pci_enable_bridges(bus);
 
 	/* dump the resource on buses */
-	list_for_each_entry(bus, &pci_root_buses, node)
+	for_each_pci_root_bus(bus)
 		pci_bus_dump_resources(bus);
 }
 
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index 966abc6..816cf94 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -522,7 +522,7 @@ static int pcifront_rescan_root(struct pcifront_device *pdev,
 	dev_info(&pdev->xdev->dev, "Rescanning PCI Frontend Bus %04x:%02x\n",
 		 domain, bus);
 
-	b = pci_find_bus(domain, bus);
+	b = pci_get_bus(domain, bus);
 	if (!b)
 		/* If the bus is unknown, create it. */
 		return pcifront_scan_root(pdev, domain, bus);
@@ -534,6 +534,7 @@ static int pcifront_rescan_root(struct pcifront_device *pdev,
 
 	/* Create SysFS and notify udev of the devices. Aka: "going live" */
 	pci_bus_add_devices(b);
+	pci_bus_put(b);
 
 	return err;
 }
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 03/20] PCI, hotplug: use hotplug-safe iterators to walk PCI buses
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
  2013-05-26 15:52 ` [PATCH v3, part2 01/20] PCI: introduce " Jiang Liu
  2013-05-26 15:52 ` [PATCH v3, part2 02/20] PCI, core: use hotplug-safe iterators to walk PCI buses Jiang Liu
@ 2013-05-26 15:53 ` Jiang Liu
  2013-05-26 15:53 ` [PATCH v3, part2 04/20] PCI, IOV: hold a reference to PCI bus when creating virtual PCI devices Jiang Liu
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:53 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel, Jiri Kosina, Masanari Iida, Rafael J. Wysocki

Enhance PCI hotplug drivers to use hotplug-safe iterators to walk
PCI buses.

In other words, replace pci_find_bus(), pci_find_next_bus() and
pci_root_buses with pci_bus_exists(), pci_get_bus(), pci_get_next_bus()
and pci_get_next_root_bus() etc.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Masanari Iida <standby24x7@gmail.com>
Cc: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
Cc: Toshi Kani <toshi.kani@hp.com>
Cc: linux-pci@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/pci/hotplug-pci.c          | 2 +-
 drivers/pci/hotplug/ibmphp_core.c  | 8 +++++---
 drivers/pci/hotplug/ibmphp_ebda.c  | 8 ++++++--
 drivers/pci/hotplug/sgi_hotplug.c  | 3 ++-
 drivers/pci/hotplug/shpchp_sysfs.c | 2 +-
 5 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/hotplug-pci.c b/drivers/pci/hotplug-pci.c
index 6258dc2..18533ed 100644
--- a/drivers/pci/hotplug-pci.c
+++ b/drivers/pci/hotplug-pci.c
@@ -11,7 +11,7 @@ int __ref pci_hp_add_bridge(struct pci_dev *dev)
 	int end = parent->busn_res.end;
 
 	for (busnr = start; busnr <= end; busnr++) {
-		if (!pci_find_bus(pci_domain_nr(parent), busnr))
+		if (!pci_bus_exists(pci_domain_nr(parent), busnr))
 			break;
 	}
 	if (busnr-- > end) {
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index cbd72d8..fb47695 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -739,7 +739,7 @@ static u8 bus_structure_fixup(u8 busno)
 	struct pci_dev *dev;
 	u16 l;
 
-	if (pci_find_bus(0, busno) || !(ibmphp_find_same_bus_num(busno)))
+	if (pci_bus_exists(0, busno) || !(ibmphp_find_same_bus_num(busno)))
 		return 1;
 
 	bus = kmalloc(sizeof(*bus), GFP_KERNEL);
@@ -787,7 +787,7 @@ static int ibm_configure_device(struct pci_func *func)
 				PCI_DEVFN(func->device, func->function));
 
 	if (func->dev == NULL) {
-		struct pci_bus *bus = pci_find_bus(0, func->busno);
+		struct pci_bus *bus = pci_get_bus(0, func->busno);
 		if (!bus)
 			return 0;
 
@@ -795,6 +795,7 @@ static int ibm_configure_device(struct pci_func *func)
 				PCI_DEVFN(func->device, func->function));
 		if (num)
 			pci_bus_add_devices(bus);
+		pci_bus_put(bus);
 
 		func->dev = pci_get_bus_and_slot(func->busno,
 				PCI_DEVFN(func->device, func->function));
@@ -1315,13 +1316,14 @@ static int __init ibmphp_init(void)
 		goto exit;
 	}
 
-	bus = pci_find_bus(0, 0);
+	bus = pci_get_bus(0, 0);
 	if (!bus) {
 		err("Can't find the root pci bus, can not continue\n");
 		rc = -ENODEV;
 		goto error;
 	}
 	memcpy(ibmphp_pci_bus, bus, sizeof(*ibmphp_pci_bus));
+	pci_bus_put(bus);
 
 	ibmphp_debug = debug;
 
diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c
index 9df78bc..e17f271 100644
--- a/drivers/pci/hotplug/ibmphp_ebda.c
+++ b/drivers/pci/hotplug/ibmphp_ebda.c
@@ -978,9 +978,13 @@ static int __init ebda_rsrc_controller (void)
 	}			/* each hpc  */
 
 	list_for_each_entry(tmp_slot, &ibmphp_slot_head, ibm_slot_list) {
+		struct pci_bus *bus = pci_get_bus(0, tmp_slot->bus);
+
+		BUG_ON(!bus);
 		snprintf(name, SLOT_NAME_SIZE, "%s", create_file_name(tmp_slot));
-		pci_hp_register(tmp_slot->hotplug_slot,
-			pci_find_bus(0, tmp_slot->bus), tmp_slot->device, name);
+		pci_hp_register(tmp_slot->hotplug_slot, bus, tmp_slot->device,
+				name);
+		pci_bus_put(bus);
 	}
 
 	print_ebda_hpc ();
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
index b2781df..5c69bda 100644
--- a/drivers/pci/hotplug/sgi_hotplug.c
+++ b/drivers/pci/hotplug/sgi_hotplug.c
@@ -684,7 +684,7 @@ static int __init sn_pci_hotplug_init(void)
 
 	INIT_LIST_HEAD(&sn_hp_list);
 
-	while ((pci_bus = pci_find_next_bus(pci_bus))) {
+	for_each_pci_root_bus(pci_bus) {
 		if (!pci_bus->sysdata)
 			continue;
 
@@ -703,6 +703,7 @@ static int __init sn_pci_hotplug_init(void)
 			break;
 		}
 	}
+	pci_bus_put(pci_bus);
 
 	return registered == 1 ? 0 : -ENODEV;
 }
diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c
index e8c31fe..e7a5dd2 100644
--- a/drivers/pci/hotplug/shpchp_sysfs.c
+++ b/drivers/pci/hotplug/shpchp_sysfs.c
@@ -74,7 +74,7 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha
 	}
 	out += sprintf(out, "Free resources: bus numbers\n");
 	for (busnr = bus->busn_res.start; busnr <= bus->busn_res.end; busnr++) {
-		if (!pci_find_bus(pci_domain_nr(bus), busnr))
+		if (!pci_bus_exists(pci_domain_nr(bus), busnr))
 			break;
 	}
 	if (busnr < bus->busn_res.end)
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 04/20] PCI, IOV: hold a reference to PCI bus when creating virtual PCI devices
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
                   ` (2 preceding siblings ...)
  2013-05-26 15:53 ` [PATCH v3, part2 03/20] PCI, hotplug: " Jiang Liu
@ 2013-05-26 15:53 ` Jiang Liu
  2013-05-26 15:53 ` [PATCH v3, part2 05/20] PCI, Alpha: use hotplug-safe iterators to walk PCI buses Jiang Liu
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:53 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel

Also use new iterator to walk PCI devices of a PCI bus.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
---
 drivers/pci/iov.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 5eb8165..4b796d6 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -36,19 +36,17 @@ static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr)
 	struct pci_bus *child;
 
 	if (bus->number == busnr)
-		return bus;
+		return pci_bus_get(bus);
 
-	child = pci_find_bus(pci_domain_nr(bus), busnr);
+	child = pci_get_bus(pci_domain_nr(bus), busnr);
 	if (child)
 		return child;
 
 	child = pci_add_new_bus(bus, NULL, busnr);
-	if (!child)
-		return NULL;
-
-	pci_bus_insert_busn_res(child, busnr, busnr);
+	if (child)
+		pci_bus_insert_busn_res(child, busnr, busnr);
 
-	return child;
+	return pci_bus_get(child);
 }
 
 static void virtfn_remove_bus(struct pci_bus *physbus, struct pci_bus *virtbus)
@@ -113,6 +111,7 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
 		goto failed2;
 
 	kobject_uevent(&virtfn->dev.kobj, KOBJ_CHANGE);
+	pci_bus_put(bus);
 
 	return 0;
 
@@ -125,6 +124,7 @@ failed1:
 	virtfn_remove_bus(dev->bus, bus);
 failed0:
 	mutex_unlock(&iov->dev->sriov->lock);
+	pci_bus_put(bus);
 
 	return rc;
 }
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 05/20] PCI, Alpha: use hotplug-safe iterators to walk PCI buses
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
                   ` (3 preceding siblings ...)
  2013-05-26 15:53 ` [PATCH v3, part2 04/20] PCI, IOV: hold a reference to PCI bus when creating virtual PCI devices Jiang Liu
@ 2013-05-26 15:53 ` Jiang Liu
  2013-05-26 15:53 ` [PATCH v3, part2 06/20] PCI, FRV: " Jiang Liu
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:53 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel, Richard Henderson, Ivan Kokshaysky, Matt Turner,
	Thierry Reding, linux-alpha

Enhance Alpha architecture specific code to use hotplug-safe iterators
to walk PCI buses.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Thierry Reding <thierry.reding@avionic-design.de>
Cc: linux-alpha@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 arch/alpha/kernel/pci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index edb4e00..094cd58 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -305,7 +305,7 @@ pcibios_claim_console_setup(void)
 {
 	struct pci_bus *b;
 
-	list_for_each_entry(b, &pci_root_buses, node)
+	for_each_pci_root_bus(b)
 		pcibios_claim_one_bus(b);
 }
 
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 06/20] PCI, FRV: use hotplug-safe iterators to walk PCI buses
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
                   ` (4 preceding siblings ...)
  2013-05-26 15:53 ` [PATCH v3, part2 05/20] PCI, Alpha: use hotplug-safe iterators to walk PCI buses Jiang Liu
@ 2013-05-26 15:53 ` Jiang Liu
  2013-05-26 15:53 ` [PATCH v3, part2 07/20] PCI, IA64: " Jiang Liu
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:53 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel, David Howells, Sebastian Andrzej Siewior

Enhance FRV architecture specific code to use hotplug-safe iterators
to walk PCI buses.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Cc: David Howells <dhowells@redhat.com>
Cc: Jiang Liu <jiang.liu@huawei.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: linux-kernel@vger.kernel.org
---
 arch/frv/mb93090-mb00/pci-frv.c | 5 ++++-
 arch/frv/mb93090-mb00/pci-vdk.c | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/frv/mb93090-mb00/pci-frv.c b/arch/frv/mb93090-mb00/pci-frv.c
index c281217..48ee89a 100644
--- a/arch/frv/mb93090-mb00/pci-frv.c
+++ b/arch/frv/mb93090-mb00/pci-frv.c
@@ -188,8 +188,11 @@ static void __init pcibios_assign_resources(void)
 
 void __init pcibios_resource_survey(void)
 {
+	struct pci_bus *bus;
+
 	DBG("PCI: Allocating resources\n");
-	pcibios_allocate_bus_resources(&pci_root_buses);
+	for_each_pci_root_bus(bus)
+		pcibios_allocate_bus_resources(&bus->children);
 	pcibios_allocate_resources(0);
 	pcibios_allocate_resources(1);
 	pcibios_assign_resources();
diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c
index 0aa35f0..f1d6c16 100644
--- a/arch/frv/mb93090-mb00/pci-vdk.c
+++ b/arch/frv/mb93090-mb00/pci-vdk.c
@@ -234,7 +234,7 @@ static void __init pcibios_fixup_peer_bridges(void)
 		return;
 	printk("PCI: Peer bridge fixup\n");
 	for (n=0; n <= pcibios_last_bus; n++) {
-		if (pci_find_bus(0, n))
+		if (pci_bus_exists(0, n))
 			continue;
 		bus.number = n;
 		bus.ops = pci_root_ops;
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 07/20] PCI, IA64: use hotplug-safe iterators to walk PCI buses
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
                   ` (5 preceding siblings ...)
  2013-05-26 15:53 ` [PATCH v3, part2 06/20] PCI, FRV: " Jiang Liu
@ 2013-05-26 15:53 ` Jiang Liu
  2013-05-26 15:53 ` [PATCH v3, part2 08/20] PCI, Microblaze: " Jiang Liu
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:53 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel, Tony Luck, Fenghua Yu, linux-ia64

Enhance IA64 architecture specific code to use hotplug-safe iterators
to walk PCI buses.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-ia64@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 arch/ia64/hp/common/sba_iommu.c   | 2 +-
 arch/ia64/sn/kernel/io_common.c   | 2 +-
 arch/ia64/sn/pci/tioca_provider.c | 3 ++-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index bcda5b2..6faf241 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -2156,7 +2156,7 @@ sba_init(void)
 #ifdef CONFIG_PCI
 	{
 		struct pci_bus *b = NULL;
-		while ((b = pci_find_next_bus(b)) != NULL)
+		for_each_pci_root_bus(b)
 			sba_connect_bus(b);
 	}
 #endif
diff --git a/arch/ia64/sn/kernel/io_common.c b/arch/ia64/sn/kernel/io_common.c
index 11f2275..87d8d8f 100644
--- a/arch/ia64/sn/kernel/io_common.c
+++ b/arch/ia64/sn/kernel/io_common.c
@@ -530,7 +530,7 @@ sn_io_late_init(void)
 	 * info from the PROM).
 	 */
 	bus = NULL;
-	while ((bus = pci_find_next_bus(bus)) != NULL) {
+	for_each_pci_root_bus(bus) {
 		bussoft = SN_PCIBUS_BUSSOFT(bus);
 		nasid = NASID_GET(bussoft->bs_base);
 		cnode = nasid_to_cnodeid(nasid);
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
index a70b11f..cd8c0fb 100644
--- a/arch/ia64/sn/pci/tioca_provider.c
+++ b/arch/ia64/sn/pci/tioca_provider.c
@@ -624,7 +624,7 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
 	    nasid_to_cnodeid(tioca_common->ca_closest_nasid);
 	tioca_common->ca_kernel_private = (u64) tioca_kern;
 
-	bus = pci_find_bus(tioca_common->ca_common.bs_persist_segment,
+	bus = pci_get_bus(tioca_common->ca_common.bs_persist_segment,
 		tioca_common->ca_common.bs_persist_busnum);
 	BUG_ON(!bus);
 	tioca_kern->ca_devices = &bus->devices;
@@ -632,6 +632,7 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
 	/* init GART */
 
 	if (tioca_gart_init(tioca_kern) < 0) {
+		pci_bus_put(bus);
 		kfree(tioca_kern);
 		kfree(tioca_common);
 		return NULL;
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 08/20] PCI, Microblaze: use hotplug-safe iterators to walk PCI buses
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
                   ` (6 preceding siblings ...)
  2013-05-26 15:53 ` [PATCH v3, part2 07/20] PCI, IA64: " Jiang Liu
@ 2013-05-26 15:53 ` Jiang Liu
  2013-05-26 15:53 ` [PATCH v3, part2 09/20] PCI, mn10300: " Jiang Liu
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:53 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel, Michal Simek, Grant Likely, Hiroo MATSUMOTO,
	microblaze-uclinux

Enhance Microblaze architecture specific code to use hotplug-safe
iterators to walk PCI buses.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Cc: Michal Simek <monstr@monstr.eu>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Hiroo MATSUMOTO <matsumoto.hiroo@jp.fujitsu.com>
Cc: microblaze-uclinux@itee.uq.edu.au
Cc: linux-kernel@vger.kernel.org
---
 arch/microblaze/pci/pci-common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index bdb8ea1..a35caa3 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -1317,7 +1317,7 @@ void __init pcibios_resource_survey(void)
 	/* Allocate and assign resources. If we re-assign everything, then
 	 * we skip the allocate phase
 	 */
-	list_for_each_entry(b, &pci_root_buses, node)
+	for_each_pci_root_bus(b)
 		pcibios_allocate_bus_resources(b);
 
 	pcibios_allocate_resources(0);
@@ -1327,7 +1327,7 @@ void __init pcibios_resource_survey(void)
 	 * the low IO area and the VGA memory area if they intersect the
 	 * bus available resources to avoid allocating things on top of them
 	 */
-	list_for_each_entry(b, &pci_root_buses, node)
+	for_each_pci_root_bus(b)
 		pcibios_reserve_legacy_regions(b);
 
 	/* Now proceed to assigning things that were left unassigned */
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 09/20] PCI, mn10300: use hotplug-safe iterators to walk PCI buses
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
                   ` (7 preceding siblings ...)
  2013-05-26 15:53 ` [PATCH v3, part2 08/20] PCI, Microblaze: " Jiang Liu
@ 2013-05-26 15:53 ` Jiang Liu
  2013-05-26 15:53 ` [PATCH v3, part2 10/20] PCI, PPC: " Jiang Liu
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:53 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel, David Howells, Koichi Yasutake

Enhance mn10300 architecture specific code to use hotplug-safe
iterators to walk PCI buses.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Cc: David Howells <dhowells@redhat.com>
Cc: Koichi Yasutake <yasutake.koichi@jp.panasonic.com>
Cc: linux-kernel@vger.kernel.org
---
 arch/mn10300/unit-asb2305/pci-asb2305.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.c b/arch/mn10300/unit-asb2305/pci-asb2305.c
index c4e2e79..88c0c52 100644
--- a/arch/mn10300/unit-asb2305/pci-asb2305.c
+++ b/arch/mn10300/unit-asb2305/pci-asb2305.c
@@ -207,8 +207,11 @@ fs_initcall(pcibios_assign_resources);
 
 void __init pcibios_resource_survey(void)
 {
+	struct pci_bus *bus;
+
 	DBG("PCI: Allocating resources\n");
-	pcibios_allocate_bus_resources(&pci_root_buses);
+	for_each_pci_root_bus(bus)
+		pcibios_allocate_bus_resources(&bus->children);
 	pcibios_allocate_resources(0);
 	pcibios_allocate_resources(1);
 }
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 10/20] PCI, PPC: use hotplug-safe iterators to walk PCI buses
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
                   ` (8 preceding siblings ...)
  2013-05-26 15:53 ` [PATCH v3, part2 09/20] PCI, mn10300: " Jiang Liu
@ 2013-05-26 15:53 ` Jiang Liu
  2013-05-26 15:53 ` [PATCH v3, part2 11/20] PCI, SPARC: " Jiang Liu
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:53 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel, Benjamin Herrenschmidt, Paul Mackerras, Gavin Shan,
	Grant Likely, Bill Pemberton, linuxppc-dev

Enhance PPC architecture specific code to use hotplug-safe iterators
to walk PCI buses.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Gavin Shan <shangw@linux.vnet.ibm.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Bill Pemberton <wfp5p@virginia.edu>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-kernel@vger.kernel.org
---
 arch/powerpc/kernel/pci-common.c |  4 ++--
 arch/powerpc/kernel/pci_64.c     | 22 ++++++++--------------
 2 files changed, 10 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index f5c5c90..56ad3a4 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1386,7 +1386,7 @@ void __init pcibios_resource_survey(void)
 	struct pci_bus *b;
 
 	/* Allocate and assign resources */
-	list_for_each_entry(b, &pci_root_buses, node)
+	for_each_pci_root_bus(b)
 		pcibios_allocate_bus_resources(b);
 	pcibios_allocate_resources(0);
 	pcibios_allocate_resources(1);
@@ -1396,7 +1396,7 @@ void __init pcibios_resource_survey(void)
 	 * bus available resources to avoid allocating things on top of them
 	 */
 	if (!pci_has_flag(PCI_PROBE_ONLY)) {
-		list_for_each_entry(b, &pci_root_buses, node)
+		for_each_pci_root_bus(b)
 			pcibios_reserve_legacy_regions(b);
 	}
 
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 873050d..d71249b 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -207,10 +207,8 @@ void pcibios_setup_phb_io_space(struct pci_controller *hose)
 long sys_pciconfig_iobase(long which, unsigned long in_bus,
 			  unsigned long in_devfn)
 {
-	struct pci_controller* hose;
-	struct list_head *ln;
-	struct pci_bus *bus = NULL;
-	struct device_node *hose_node;
+	struct pci_controller* hose = NULL;
+	struct pci_bus *bus;
 
 	/* Argh ! Please forgive me for that hack, but that's the
 	 * simplest way to get existing XFree to not lockup on some
@@ -229,19 +227,15 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
 	/* That syscall isn't quite compatible with PCI domains, but it's
 	 * used on pre-domains setup. We return the first match
 	 */
-
-	for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
-		bus = pci_bus_b(ln);
-		if (in_bus >= bus->number && in_bus <= bus->busn_res.end)
+	for_each_pci_root_bus(bus)
+		if (in_bus >= bus->number && in_bus <= bus->busn_res.end) {
+			hose = pci_bus_to_host(bus);
+			pci_bus_put(bus);
 			break;
-		bus = NULL;
-	}
-	if (bus == NULL || bus->dev.of_node == NULL)
+		}
+	if (hose == NULL)
 		return -ENODEV;
 
-	hose_node = bus->dev.of_node;
-	hose = PCI_DN(hose_node)->phb;
-
 	switch (which) {
 	case IOBASE_BRIDGE_NUMBER:
 		return (long)hose->first_busno;
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 11/20] PCI, SPARC: use hotplug-safe iterators to walk PCI buses
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
                   ` (9 preceding siblings ...)
  2013-05-26 15:53 ` [PATCH v3, part2 10/20] PCI, PPC: " Jiang Liu
@ 2013-05-26 15:53 ` Jiang Liu
  2013-05-26 17:11   ` David Miller
  2013-05-26 15:53 ` [PATCH v3, part2 12/20] PCI, x86: " Jiang Liu
                   ` (8 subsequent siblings)
  19 siblings, 1 reply; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:53 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel, David S. Miller, Andrew Morton, sparclinux

Enhance SPARC architecture specific code to use hotplug-safe iterators
to walk PCI buses.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Jiang Liu <jiang.liu@huawei.com>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: sparclinux@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 arch/sparc/kernel/pci.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index b16f624..ed84a97 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -995,9 +995,9 @@ static void pci_bus_slot_names(struct device_node *node, struct pci_bus *bus)
 
 static int __init of_pci_slot_init(void)
 {
-	struct pci_bus *pbus = NULL;
+	struct pci_bus *pbus;
 
-	while ((pbus = pci_find_next_bus(pbus)) != NULL) {
+	for_each_pci_root_bus(pbus) {
 		struct device_node *node;
 
 		if (pbus->self) {
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 12/20] PCI, x86: use hotplug-safe iterators to walk PCI buses
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
                   ` (10 preceding siblings ...)
  2013-05-26 15:53 ` [PATCH v3, part2 11/20] PCI, SPARC: " Jiang Liu
@ 2013-05-26 15:53 ` Jiang Liu
  2013-05-26 15:53 ` [PATCH v3, part2 13/20] PCI, ACPI: " Jiang Liu
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:53 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel, Thomas Gleixner, Ingo Molnar, H. Peter Anvin, x86,
	Matthew Garrett

Enhance x86 architecture specific code to use hotplug-safe iterators
to walk PCI buses.

In other words, replace pci_find_bus(), pci_find_next_bus() and
pci_root_buses with pci_bus_exists(), pci_get_bus(), pci_get_next_bus()
and pci_get_next_root_bus() etc.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Cc: Myron Stowe <myron.stowe@redhat.com>
Cc: Yijing Wang <wangyijing@huawei.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Matthew Garrett <mjg@redhat.com>
Cc: linux-kernel@vger.kernel.org
---
 arch/x86/pci/acpi.c   | 3 ++-
 arch/x86/pci/common.c | 3 ++-
 arch/x86/pci/i386.c   | 9 ++++-----
 arch/x86/pci/irq.c    | 2 +-
 arch/x86/pci/legacy.c | 2 +-
 5 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 3e72425..b972f04 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -526,7 +526,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 	 * Maybe the desired pci bus has been already scanned. In such case
 	 * it is unnecessary to scan the pci bus with the given domain,busnum.
 	 */
-	bus = pci_find_bus(domain, busnum);
+	bus = pci_get_bus(domain, busnum);
 	if (bus) {
 		/*
 		 * If the desired bus exits, the content of bus->sysdata will
@@ -534,6 +534,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 		 */
 		memcpy(bus->sysdata, sd, sizeof(*sd));
 		kfree(info);
+		pci_bus_put(bus);
 	} else {
 		probe_pci_root_info(info, device, busnum, domain);
 
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 305c68b..51cc1be 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -460,8 +460,9 @@ struct pci_bus *pcibios_scan_root(int busnum)
 {
 	struct pci_bus *bus = NULL;
 
-	while ((bus = pci_find_next_bus(bus)) != NULL) {
+	for_each_pci_root_bus(bus) {
 		if (bus->number == busnum) {
+			pci_bus_put(bus);
 			/* Already scanned */
 			return bus;
 		}
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 94919e3..6481d25 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -343,7 +343,7 @@ static int __init pcibios_assign_resources(void)
 	struct pci_bus *bus;
 
 	if (!(pci_probe & PCI_ASSIGN_ROMS))
-		list_for_each_entry(bus, &pci_root_buses, node)
+		for_each_pci_root_bus(bus)
 			pcibios_allocate_rom_resources(bus);
 
 	pci_assign_unassigned_resources();
@@ -371,12 +371,11 @@ void __init pcibios_resource_survey(void)
 
 	DBG("PCI: Allocating resources\n");
 
-	list_for_each_entry(bus, &pci_root_buses, node)
+	for_each_pci_root_bus(bus)
 		pcibios_allocate_bus_resources(bus);
-
-	list_for_each_entry(bus, &pci_root_buses, node)
+	for_each_pci_root_bus(bus)
 		pcibios_allocate_resources(bus, 0);
-	list_for_each_entry(bus, &pci_root_buses, node)
+	for_each_pci_root_bus(bus)
 		pcibios_allocate_resources(bus, 1);
 
 	e820_reserve_resources_late();
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
index 372e9b8..65898f6 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -137,7 +137,7 @@ static void __init pirq_peer_trick(void)
 	}
 	for (i = 1; i < 256; i++) {
 		int node;
-		if (!busmap[i] || pci_find_bus(0, i))
+		if (!busmap[i] || pci_bus_exists(0, i))
 			continue;
 		node = get_mp_bus_to_node(i);
 		if (pci_scan_bus_on_node(i, &pci_root_ops, node))
diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c
index 4db96fb..1fb7922 100644
--- a/arch/x86/pci/legacy.c
+++ b/arch/x86/pci/legacy.c
@@ -40,7 +40,7 @@ void pcibios_scan_specific_bus(int busn)
 	long node;
 	u32 l;
 
-	if (pci_find_bus(0, busn))
+	if (pci_bus_exists(0, busn))
 		return;
 
 	node = get_mp_bus_to_node(busn);
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 13/20] PCI, ACPI: use hotplug-safe iterators to walk PCI buses
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
                   ` (11 preceding siblings ...)
  2013-05-26 15:53 ` [PATCH v3, part2 12/20] PCI, x86: " Jiang Liu
@ 2013-05-26 15:53 ` Jiang Liu
  2013-05-26 15:53 ` [PATCH v3, part2 14/20] PCI, DRM: " Jiang Liu
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:53 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel, Len Brown, linux-acpi

Enhance ACPI reset drvier to use hotplug-safe iterators to walk PCI buses.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Len Brown <lenb@kernel.org>
Cc: linux-acpi@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/acpi/reboot.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c
index a6c77e8b..532dd6d 100644
--- a/drivers/acpi/reboot.c
+++ b/drivers/acpi/reboot.c
@@ -33,7 +33,7 @@ void acpi_reboot(void)
 	switch (rr->space_id) {
 	case ACPI_ADR_SPACE_PCI_CONFIG:
 		/* The reset register can only live on bus 0. */
-		bus0 = pci_find_bus(0, 0);
+		bus0 = pci_get_bus(0, 0);
 		if (!bus0)
 			return;
 		/* Form PCI device/function pair. */
@@ -43,6 +43,7 @@ void acpi_reboot(void)
 		/* Write the value that resets us. */
 		pci_bus_write_config_byte(bus0, devfn,
 				(rr->address & 0xffff), reset_value);
+		pci_bus_put(bus0);
 		break;
 
 	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 14/20] PCI, DRM: use hotplug-safe iterators to walk PCI buses
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
                   ` (12 preceding siblings ...)
  2013-05-26 15:53 ` [PATCH v3, part2 13/20] PCI, ACPI: " Jiang Liu
@ 2013-05-26 15:53 ` Jiang Liu
  2013-06-17 18:08   ` Bjorn Helgaas
  2013-05-26 15:53 ` [PATCH v3, part2 15/20] PCI, EDAC: use hotplug-safe PCI bus " Jiang Liu
                   ` (5 subsequent siblings)
  19 siblings, 1 reply; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:53 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel, David Airlie, dri-devel

Enhance DRM drvier to use hotplug-safe iterators to walk PCI buses.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Cc: David Airlie <airlied@linux.ie>
Cc: dri-devel@lists.freedesktop.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/gpu/drm/drm_fops.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 429e07d..dc8c40b 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -359,9 +359,11 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 			pci_dev_put(pci_dev);
 		}
 		if (!dev->hose) {
-			struct pci_bus *b = pci_bus_b(pci_root_buses.next);
-			if (b)
+			struct pci_bus *b = pci_get_next_root_bus(NULL);
+			if (b) {
 				dev->hose = b->sysdata;
+				pci_bus_put(b);
+			}
 		}
 	}
 #endif
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 15/20] PCI, EDAC: use hotplug-safe PCI bus iterators to walk PCI buses
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
                   ` (13 preceding siblings ...)
  2013-05-26 15:53 ` [PATCH v3, part2 14/20] PCI, DRM: " Jiang Liu
@ 2013-05-26 15:53 ` Jiang Liu
  2013-06-17 20:18   ` Bjorn Helgaas
  2013-05-26 15:53 ` [PATCH v3, part2 16/20] PCI, via-camera: use hotplug-safe " Jiang Liu
                   ` (4 subsequent siblings)
  19 siblings, 1 reply; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:53 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel, Mauro Carvalho Chehab, Doug Thompson, linux-edac

Enhance EDAC drviers to use hotplug-safe iterators to walk PCI buses.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
Cc: Doug Thompson <dougthompson@xmission.com>
Cc: linux-edac@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/edac/i7core_edac.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index 0ec3e95..7146e10 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -1296,7 +1296,7 @@ static unsigned i7core_pci_lastbus(void)
 	int last_bus = 0, bus;
 	struct pci_bus *b = NULL;
 
-	while ((b = pci_find_next_bus(b)) != NULL) {
+	for_each_pci_root_bus(b) {
 		bus = b->number;
 		edac_dbg(0, "Found bus %d\n", bus);
 		if (bus > last_bus)
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 16/20] PCI, via-camera: use hotplug-safe iterators to walk PCI buses
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
                   ` (14 preceding siblings ...)
  2013-05-26 15:53 ` [PATCH v3, part2 15/20] PCI, EDAC: use hotplug-safe PCI bus " Jiang Liu
@ 2013-05-26 15:53 ` Jiang Liu
  2013-05-26 15:53 ` [PATCH v3, part2 17/20] PCI, iommu: " Jiang Liu
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:53 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel, Mauro Carvalho Chehab, Daniel Drake,
	Jonathan Corbet, Javier Martin, linux-media

Enhance via-camera drviers to use hotplug-safe iterators to walk
PCI buses.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
Cc: Daniel Drake <dsd@laptop.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Javier Martin <javier.martin@vista-silicon.com>
Cc: linux-media@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/media/platform/via-camera.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/via-camera.c b/drivers/media/platform/via-camera.c
index a794cd6..3ea3fac 100644
--- a/drivers/media/platform/via-camera.c
+++ b/drivers/media/platform/via-camera.c
@@ -1284,7 +1284,8 @@ static struct video_device viacam_v4l_template = {
 
 static bool viacam_serial_is_enabled(void)
 {
-	struct pci_bus *pbus = pci_find_bus(0, 0);
+	struct pci_bus *pbus = pci_get_bus(0, 0);
+	bool ret = false;
 	u8 cbyte;
 
 	if (!pbus)
@@ -1292,18 +1293,21 @@ static bool viacam_serial_is_enabled(void)
 	pci_bus_read_config_byte(pbus, VIACAM_SERIAL_DEVFN,
 			VIACAM_SERIAL_CREG, &cbyte);
 	if ((cbyte & VIACAM_SERIAL_BIT) == 0)
-		return false; /* Not enabled */
+		goto out; /* Not enabled */
 	if (override_serial == 0) {
 		printk(KERN_NOTICE "Via camera: serial port is enabled, " \
 				"refusing to load.\n");
 		printk(KERN_NOTICE "Specify override_serial=1 to force " \
 				"module loading.\n");
-		return true;
+		ret = true;
+		goto out;
 	}
 	printk(KERN_NOTICE "Via camera: overriding serial port\n");
 	pci_bus_write_config_byte(pbus, VIACAM_SERIAL_DEVFN,
 			VIACAM_SERIAL_CREG, cbyte & ~VIACAM_SERIAL_BIT);
-	return false;
+out:
+	pci_bus_put(pbus);
+	return ret;
 }
 
 static struct ov7670_config sensor_cfg = {
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 17/20] PCI, iommu: use hotplug-safe iterators to walk PCI buses
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
                   ` (15 preceding siblings ...)
  2013-05-26 15:53 ` [PATCH v3, part2 16/20] PCI, via-camera: use hotplug-safe " Jiang Liu
@ 2013-05-26 15:53 ` Jiang Liu
  2013-06-17 20:20   ` Bjorn Helgaas
  2013-05-26 15:53 ` [PATCH v3, part2 18/20] PCI, eeepc-laptop: " Jiang Liu
                   ` (2 subsequent siblings)
  19 siblings, 1 reply; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:53 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel, Joerg Roedel, Ingo Molnar, Donald Dutile,
	Hannes Reinecke, Li, Zhen-Hua, iommu

Enhance iommu drviers to use hotplug-safe iterators to walk
PCI buses.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Donald Dutile <ddutile@redhat.com>
Cc: Hannes Reinecke <hare@suse.de>
Cc: "Li, Zhen-Hua" <zhen-hual@hp.com>
Cc: iommu@lists.linux-foundation.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/iommu/amd_iommu.c | 4 +++-
 drivers/iommu/dmar.c      | 6 ++++--
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 21d02b0..eef7a7e 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -352,6 +352,7 @@ static int init_iommu_group(struct device *dev)
 	struct iommu_dev_data *dev_data;
 	struct iommu_group *group;
 	struct pci_dev *dma_pdev;
+	struct pci_bus *b = NULL;
 	int ret;
 
 	group = iommu_group_get(dev);
@@ -388,7 +389,7 @@ static int init_iommu_group(struct device *dev)
 		 * the alias.  Be careful to also test the parent device if
 		 * we think the alias is the root of the group.
 		 */
-		bus = pci_find_bus(0, alias >> 8);
+		b = bus = pci_get_bus(0, alias >> 8);
 		if (!bus)
 			goto use_group;
 
@@ -408,6 +409,7 @@ static int init_iommu_group(struct device *dev)
 	dma_pdev = get_isolation_root(pci_dev_get(to_pci_dev(dev)));
 use_pdev:
 	ret = use_pdev_iommu_group(dma_pdev, dev);
+	pci_bus_put(b);
 	pci_dev_put(dma_pdev);
 	return ret;
 use_group:
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index a7967ce..7162787 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -67,12 +67,12 @@ static void __init dmar_register_drhd_unit(struct dmar_drhd_unit *drhd)
 static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
 					   struct pci_dev **dev, u16 segment)
 {
-	struct pci_bus *bus;
+	struct pci_bus *b, *bus;
 	struct pci_dev *pdev = NULL;
 	struct acpi_dmar_pci_path *path;
 	int count;
 
-	bus = pci_find_bus(segment, scope->bus);
+	b = bus = pci_get_bus(segment, scope->bus);
 	path = (struct acpi_dmar_pci_path *)(scope + 1);
 	count = (scope->length - sizeof(struct acpi_dmar_device_scope))
 		/ sizeof(struct acpi_dmar_pci_path);
@@ -97,6 +97,8 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
 		count --;
 		bus = pdev->subordinate;
 	}
+	pci_bus_put(b);
+
 	if (!pdev) {
 		pr_warn("Device scope device [%04x:%02x:%02x.%02x] not found\n",
 			segment, scope->bus, path->dev, path->fn);
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 18/20] PCI, eeepc-laptop: use hotplug-safe iterators to walk PCI buses
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
                   ` (16 preceding siblings ...)
  2013-05-26 15:53 ` [PATCH v3, part2 17/20] PCI, iommu: " Jiang Liu
@ 2013-05-26 15:53 ` Jiang Liu
  2013-05-26 15:53 ` [PATCH v3, part2 19/20] PCI, asus-wmi: " Jiang Liu
  2013-05-26 15:53 ` [PATCH v3, part2 20/20] PCI, ARM: use hotplug-safe PCI bus " Jiang Liu
  19 siblings, 0 replies; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:53 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel, Corentin Chary, Matthew Garrett, acpi4asus-user,
	platform-driver-x86

Enhance eeepc-laptop drvier to use hotplug-safe iterators to walk
PCI buses.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Cc: Corentin Chary <corentin.chary@gmail.com>
Cc: Matthew Garrett <matthew.garrett@nebula.com>
Cc: acpi4asus-user@lists.sourceforge.net
Cc: platform-driver-x86@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/platform/x86/eeepc-laptop.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 5d26e70..6291b4f 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -759,7 +759,7 @@ static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
 static int eeepc_setup_pci_hotplug(struct eeepc_laptop *eeepc)
 {
 	int ret = -ENOMEM;
-	struct pci_bus *bus = pci_find_bus(0, 1);
+	struct pci_bus *bus = pci_get_bus(0, 1);
 
 	if (!bus) {
 		pr_err("Unable to find wifi PCI bus\n");
@@ -787,6 +787,8 @@ static int eeepc_setup_pci_hotplug(struct eeepc_laptop *eeepc)
 		goto error_register;
 	}
 
+	pci_bus_put(bus);
+
 	return 0;
 
 error_register:
@@ -795,6 +797,7 @@ error_info:
 	kfree(eeepc->hotplug_slot);
 	eeepc->hotplug_slot = NULL;
 error_slot:
+	pci_bus_put(bus);
 	return ret;
 }
 
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 19/20] PCI, asus-wmi: use hotplug-safe iterators to walk PCI buses
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
                   ` (17 preceding siblings ...)
  2013-05-26 15:53 ` [PATCH v3, part2 18/20] PCI, eeepc-laptop: " Jiang Liu
@ 2013-05-26 15:53 ` Jiang Liu
  2013-05-26 15:53 ` [PATCH v3, part2 20/20] PCI, ARM: use hotplug-safe PCI bus " Jiang Liu
  19 siblings, 0 replies; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:53 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel, Corentin Chary, Matthew Garrett, acpi4asus-user,
	platform-driver-x86

Enhance asus-wmi drvier to use hotplug-safe iterators to walk PCI buses.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Cc: Corentin Chary <corentin.chary@gmail.com>
Cc: Matthew Garrett <matthew.garrett@nebula.com>
Cc: acpi4asus-user@lists.sourceforge.net
Cc: platform-driver-x86@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/platform/x86/asus-wmi.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index c11b242..f92db4c 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -596,7 +596,7 @@ static bool asus_wlan_rfkill_blocked(struct asus_wmi *asus)
 static void asus_rfkill_hotplug(struct asus_wmi *asus)
 {
 	struct pci_dev *dev;
-	struct pci_bus *bus;
+	struct pci_bus *bus = NULL;
 	bool blocked;
 	bool absent;
 	u32 l;
@@ -611,7 +611,7 @@ static void asus_rfkill_hotplug(struct asus_wmi *asus)
 		rfkill_set_sw_state(asus->wlan.rfkill, blocked);
 
 	if (asus->hotplug_slot) {
-		bus = pci_find_bus(0, 1);
+		bus = pci_get_bus(0, 1);
 		if (!bus) {
 			pr_warn("Unable to find PCI bus 1?\n");
 			goto out_unlock;
@@ -657,6 +657,7 @@ static void asus_rfkill_hotplug(struct asus_wmi *asus)
 
 out_unlock:
 	mutex_unlock(&asus->hotplug_lock);
+	pci_bus_put(bus);
 }
 
 static void asus_rfkill_notify(acpi_handle handle, u32 event, void *data)
@@ -748,7 +749,7 @@ static void asus_hotplug_work(struct work_struct *work)
 static int asus_setup_pci_hotplug(struct asus_wmi *asus)
 {
 	int ret = -ENOMEM;
-	struct pci_bus *bus = pci_find_bus(0, 1);
+	struct pci_bus *bus = pci_get_bus(0, 1);
 
 	if (!bus) {
 		pr_err("Unable to find wifi PCI bus\n");
@@ -782,6 +783,7 @@ static int asus_setup_pci_hotplug(struct asus_wmi *asus)
 		pr_err("Unable to register hotplug slot - %d\n", ret);
 		goto error_register;
 	}
+	pci_bus_put(bus);
 
 	return 0;
 
@@ -793,6 +795,7 @@ error_info:
 error_slot:
 	destroy_workqueue(asus->hotplug_workqueue);
 error_workqueue:
+	pci_bus_put(bus);
 	return ret;
 }
 
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3, part2 20/20] PCI, ARM: use hotplug-safe PCI bus iterators to walk PCI buses
  2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
                   ` (18 preceding siblings ...)
  2013-05-26 15:53 ` [PATCH v3, part2 19/20] PCI, asus-wmi: " Jiang Liu
@ 2013-05-26 15:53 ` Jiang Liu
  2013-06-17 18:24   ` Bjorn Helgaas
  19 siblings, 1 reply; 36+ messages in thread
From: Jiang Liu @ 2013-05-26 15:53 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu, linux-pci,
	linux-kernel, Russell King, Thierry Reding, Rob Herring,
	linux-arm-kernel

Enhance ARM architecture specific code to use new hotplug-safe PCI
bus iterators to walk PCI buses.

Change pcibios_report_status implementation so that it doesn't access
pci_root_buses global list. The pci_root_buses list will be scheduled
to be removed.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Thierry Reding <thierry.reding@avionic-design.de>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
---
 arch/arm/kernel/bios32.c           | 13 +------------
 arch/arm/mach-footbridge/dc21285.c | 12 +++++++++++-
 2 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index b2ed73c..50ebbe8 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -22,7 +22,7 @@ static int debug_pci;
  * We can't use pci_find_device() here since we are
  * called from interrupt context.
  */
-static void pcibios_bus_report_status(struct pci_bus *bus, u_int status_mask, int warn)
+void pcibios_bus_report_status(struct pci_bus *bus, u_int status_mask, int warn)
 {
 	struct pci_dev *dev;
 
@@ -55,17 +55,6 @@ static void pcibios_bus_report_status(struct pci_bus *bus, u_int status_mask, in
 			pcibios_bus_report_status(dev->subordinate, status_mask, warn);
 }
 
-void pcibios_report_status(u_int status_mask, int warn)
-{
-	struct list_head *l;
-
-	list_for_each(l, &pci_root_buses) {
-		struct pci_bus *bus = pci_bus_b(l);
-
-		pcibios_bus_report_status(bus, status_mask, warn);
-	}
-}
-
 /*
  * We don't use this to fix the device, but initialisation of it.
  * It's not the correct use for this, but it works.
diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c
index a7cd2cf..a0f1d01 100644
--- a/arch/arm/mach-footbridge/dc21285.c
+++ b/arch/arm/mach-footbridge/dc21285.c
@@ -35,7 +35,16 @@
 				  PCI_STATUS_PARITY) << 16)
 
 extern int setup_arm_irq(int, struct irqaction *);
-extern void pcibios_report_status(u_int status_mask, int warn);
+extern void pcibios_report_bus_status(struct pci_bus *bus, u_int status_mask,
+				      int warn);
+
+static struct pci_bus *dc21285_root_bus;
+
+static void pcibios_report_status(u_int status_mask, int warn)
+{
+	if (dc21285_root_bus)
+		pcibios_report_bus_status(dc21285_root_bus, status_mask, warn);
+}
 
 static unsigned long
 dc21285_base_address(struct pci_bus *bus, unsigned int devfn)
@@ -376,5 +385,6 @@ void __init dc21285_preinit(void)
 
 void __init dc21285_postinit(void)
 {
+	dc21285_root_bus = pci_get_next_root_bus(NULL);
 	register_isa_ports(DC21285_PCI_MEM, DC21285_PCI_IO, 0);
 }
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCH v3, part2 11/20] PCI, SPARC: use hotplug-safe iterators to walk PCI buses
  2013-05-26 15:53 ` [PATCH v3, part2 11/20] PCI, SPARC: " Jiang Liu
@ 2013-05-26 17:11   ` David Miller
  0 siblings, 0 replies; 36+ messages in thread
From: David Miller @ 2013-05-26 17:11 UTC (permalink / raw)
  To: liuj97
  Cc: bhelgaas, yinghai, jiang.liu, rjw, gregkh, guz.fnst, toshi.kani,
	myron.stowe, wangyijing, linux-pci, linux-kernel, akpm,
	sparclinux

From: Jiang Liu <liuj97@gmail.com>
Date: Sun, 26 May 2013 23:53:08 +0800

> Enhance SPARC architecture specific code to use hotplug-safe iterators
> to walk PCI buses.
> 
> Signed-off-by: Jiang Liu <jiang.liu@huawei.com>

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3, part2 01/20] PCI: introduce hotplug-safe PCI bus iterators
  2013-05-26 15:52 ` [PATCH v3, part2 01/20] PCI: introduce " Jiang Liu
@ 2013-05-28  4:22   ` Yinghai Lu
  2013-05-28 15:06     ` Liu Jiang
  2013-06-17 20:06   ` Bjorn Helgaas
  1 sibling, 1 reply; 36+ messages in thread
From: Yinghai Lu @ 2013-05-28  4:22 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Bjorn Helgaas, Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman,
	Gu Zheng, Toshi Kani, Myron Stowe, Yijing Wang, linux-pci,
	Linux Kernel Mailing List

On Sun, May 26, 2013 at 8:52 AM, Jiang Liu <liuj97@gmail.com> wrote:
> Introduce hotplug-safe PCI bus iterators as below, which hold a
> reference on the returned PCI bus object.
> bool pci_bus_exists(int domain, int busnr);
> struct pci_bus *pci_get_bus(int domain, int busnr);
> struct pci_bus *pci_get_next_bus(struct pci_bus *from);
> struct pci_bus *pci_get_next_root_bus(struct pci_bus *from);
> #define for_each_pci_bus(b) for (b = NULL; (b = pci_get_next_bus(b)); )
> #define for_each_pci_root_bus(b)  \
>                 for (b = NULL; (b = pci_get_next_root_bus(b)); )
>
> The long-term goal is to remove hotplug-unsafe pci_find_bus(),
> pci_find_next_bus() and the global pci_root_buses list.
>
> These new interfaces may be a littler slower than existing interfaces,
> but it should be acceptable because they are not used on hot paths.

looks like go over all buses to find out several root buses is not good.


>
> Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
> Acked-by: Yinghai Lu <yinghai@kernel.org>

I take that back.

> Cc: linux-pci@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> ---
>  drivers/pci/pci.h    |   1 +
>  drivers/pci/probe.c  |   2 +-
>  drivers/pci/search.c | 159 +++++++++++++++++++++++++++++++++++++++++----------
>  include/linux/pci.h  |  23 +++++++-
>  4 files changed, 153 insertions(+), 32 deletions(-)
>
> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
> index 68678ed..8fe15f6 100644
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -126,6 +126,7 @@ static inline void pci_remove_legacy_files(struct pci_bus *bus) { return; }
>
>  /* Lock for read/write access to pci device and bus lists */
>  extern struct rw_semaphore pci_bus_sem;
> +extern struct class pcibus_class;
>
>  extern raw_spinlock_t pci_lock;
>
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index 2830070..1004a05 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -93,7 +93,7 @@ static void release_pcibus_dev(struct device *dev)
>         kfree(pci_bus);
>  }
>
> -static struct class pcibus_class = {
> +struct class pcibus_class = {
>         .name           = "pci_bus",
>         .dev_release    = &release_pcibus_dev,
>         .dev_attrs      = pcibus_dev_attrs,
...
> +static int pci_match_next_root_bus(struct device *dev, const void *data)
> +{
> +       return pci_is_root_bus(to_pci_bus(dev));
>  }
...
> +
> +/**
> + * pci_find_next_root_bus - begin or continue searching for a PCI root bus
> + * @from: Previous PCI bus found, or %NULL for new search.
> + *
> + * Iterates through the list of known PCI root busses. If a PCI bus is found,
> + * the reference count to the root bus is incremented and a pointer to it is
> + * returned. Otherwise, %NULL is returned. A new search is initiated by
> + * passing %NULL as the @from argument. Otherwise if @from is not %NULL,
> + * searches continue from next root bus on the global list. The reference
> + * count for @from is always decremented if it is not %NULL.
> + */
> +struct pci_bus *pci_get_next_root_bus(struct pci_bus *from)
> +{
> +       struct device *dev = from ? &from->dev : NULL;
> +
> +       WARN_ON(in_interrupt());
> +       dev = class_find_device(&pcibus_class, dev, NULL,
> +                               &pci_match_next_root_bus);
> +       pci_bus_put(from);
> +       if (dev)
> +               return to_pci_bus(dev);
> +
> +       return NULL;
>  }
> +EXPORT_SYMBOL(pci_get_next_root_bus);

this patchset is most doing same thing like my for_each_host_bridge patchset.
that patchset add bus_type for host_bridge and loop with each_...bus
to find host_bridge
and to its bus.

looks like for each host bridge should be right direction.

also late we could add per host bridge lock instead of whole pci bus sem etc.

Thanks

Yinghai

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3, part2 01/20] PCI: introduce hotplug-safe PCI bus iterators
  2013-05-28  4:22   ` Yinghai Lu
@ 2013-05-28 15:06     ` Liu Jiang
  0 siblings, 0 replies; 36+ messages in thread
From: Liu Jiang @ 2013-05-28 15:06 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Bjorn Helgaas, Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman,
	Gu Zheng, Toshi Kani, Myron Stowe, Yijing Wang, linux-pci,
	Linux Kernel Mailing List

On Tue 28 May 2013 12:22:29 PM CST, Yinghai Lu wrote:
> On Sun, May 26, 2013 at 8:52 AM, Jiang Liu <liuj97@gmail.com> wrote:
>> Introduce hotplug-safe PCI bus iterators as below, which hold a
>> reference on the returned PCI bus object.
>> bool pci_bus_exists(int domain, int busnr);
>> struct pci_bus *pci_get_bus(int domain, int busnr);
>> struct pci_bus *pci_get_next_bus(struct pci_bus *from);
>> struct pci_bus *pci_get_next_root_bus(struct pci_bus *from);
>> #define for_each_pci_bus(b) for (b = NULL; (b = pci_get_next_bus(b)); )
>> #define for_each_pci_root_bus(b)  \
>>                 for (b = NULL; (b = pci_get_next_root_bus(b)); )
>>
>> The long-term goal is to remove hotplug-unsafe pci_find_bus(),
>> pci_find_next_bus() and the global pci_root_buses list.
>>
>> These new interfaces may be a littler slower than existing interfaces,
>> but it should be acceptable because they are not used on hot paths.
>
> looks like go over all buses to find out several root buses is not good.
>
>
>>
>> Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
>> Acked-by: Yinghai Lu <yinghai@kernel.org>
>
> I take that back.
>
>> Cc: linux-pci@vger.kernel.org
>> Cc: linux-kernel@vger.kernel.org
>> ---
>>  drivers/pci/pci.h    |   1 +
>>  drivers/pci/probe.c  |   2 +-
>>  drivers/pci/search.c | 159 +++++++++++++++++++++++++++++++++++++++++----------
>>  include/linux/pci.h  |  23 +++++++-
>>  4 files changed, 153 insertions(+), 32 deletions(-)
>>
>> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
>> index 68678ed..8fe15f6 100644
>> --- a/drivers/pci/pci.h
>> +++ b/drivers/pci/pci.h
>> @@ -126,6 +126,7 @@ static inline void pci_remove_legacy_files(struct pci_bus *bus) { return; }
>>
>>  /* Lock for read/write access to pci device and bus lists */
>>  extern struct rw_semaphore pci_bus_sem;
>> +extern struct class pcibus_class;
>>
>>  extern raw_spinlock_t pci_lock;
>>
>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>> index 2830070..1004a05 100644
>> --- a/drivers/pci/probe.c
>> +++ b/drivers/pci/probe.c
>> @@ -93,7 +93,7 @@ static void release_pcibus_dev(struct device *dev)
>>         kfree(pci_bus);
>>  }
>>
>> -static struct class pcibus_class = {
>> +struct class pcibus_class = {
>>         .name           = "pci_bus",
>>         .dev_release    = &release_pcibus_dev,
>>         .dev_attrs      = pcibus_dev_attrs,
> ...
>> +static int pci_match_next_root_bus(struct device *dev, const void *data)
>> +{
>> +       return pci_is_root_bus(to_pci_bus(dev));
>>  }
> ...
>> +
>> +/**
>> + * pci_find_next_root_bus - begin or continue searching for a PCI root bus
>> + * @from: Previous PCI bus found, or %NULL for new search.
>> + *
>> + * Iterates through the list of known PCI root busses. If a PCI bus is found,
>> + * the reference count to the root bus is incremented and a pointer to it is
>> + * returned. Otherwise, %NULL is returned. A new search is initiated by
>> + * passing %NULL as the @from argument. Otherwise if @from is not %NULL,
>> + * searches continue from next root bus on the global list. The reference
>> + * count for @from is always decremented if it is not %NULL.
>> + */
>> +struct pci_bus *pci_get_next_root_bus(struct pci_bus *from)
>> +{
>> +       struct device *dev = from ? &from->dev : NULL;
>> +
>> +       WARN_ON(in_interrupt());
>> +       dev = class_find_device(&pcibus_class, dev, NULL,
>> +                               &pci_match_next_root_bus);
>> +       pci_bus_put(from);
>> +       if (dev)
>> +               return to_pci_bus(dev);
>> +
>> +       return NULL;
>>  }
>> +EXPORT_SYMBOL(pci_get_next_root_bus);
>
> this patchset is most doing same thing like my for_each_host_bridge patchset.
> that patchset add bus_type for host_bridge and loop with each_...bus
> to find host_bridge
> and to its bus.
>
> looks like for each host bridge should be right direction.
>
> also late we could add per host bridge lock instead of whole pci bus sem etc.
>
> Thanks
>
> Yinghai
Hi Yinghai,
          Thanks for review! Actually this patchset is inspired by your 
for_each_host_bridge()
patchset but trying to close some race windows.
          Currently pci_root_bus holds a reference to pci_host_bridge, 
so it's always safe to
reference pci_root_bus->bridge. And pci_host_bridge doesn't hold 
reference to pci_root_bus,
so we can't safely reference pci_host_bridge->bus. And it's hard to 
make pci_host_bridge
to hold a reference to pci_root_bus because that will cause loop.
           So we try to achieve the same goal with this patchset, but 
with some level of inefficiency
to search all PCI buses for root buses.
          The third patchset of this series is to introduce a PCI bus 
lock mechanism to solve
many risk conditions in PCI host bridge/device hotplug we are facing 
recently. We have
done basic tests against the new lock mechanism and seems it has solved 
all those
risk conditions found by us and Gu Zheng. But we are still working on 
improving the
third patchset.
          To all, seems we are trying to achieve the same goal with 
different approaches.
Regards!
Gerry


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3, part2 14/20] PCI, DRM: use hotplug-safe iterators to walk PCI buses
  2013-05-26 15:53 ` [PATCH v3, part2 14/20] PCI, DRM: " Jiang Liu
@ 2013-06-17 18:08   ` Bjorn Helgaas
  0 siblings, 0 replies; 36+ messages in thread
From: Bjorn Helgaas @ 2013-06-17 18:08 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Yinghai Lu, Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman,
	Gu Zheng, Toshi Kani, Myron Stowe, Yijing Wang, linux-pci,
	linux-kernel, David Airlie, dri-devel

On Sun, May 26, 2013 at 11:53:11PM +0800, Jiang Liu wrote:
> Enhance DRM drvier to use hotplug-safe iterators to walk PCI buses.
> 
> Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
> Cc: David Airlie <airlied@linux.ie>
> Cc: dri-devel@lists.freedesktop.org
> Cc: linux-kernel@vger.kernel.org
> ---
>  drivers/gpu/drm/drm_fops.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
> index 429e07d..dc8c40b 100644
> --- a/drivers/gpu/drm/drm_fops.c
> +++ b/drivers/gpu/drm/drm_fops.c
> @@ -359,9 +359,11 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
>  			pci_dev_put(pci_dev);
>  		}
>  		if (!dev->hose) {
> -			struct pci_bus *b = pci_bus_b(pci_root_buses.next);
> -			if (b)
> +			struct pci_bus *b = pci_get_next_root_bus(NULL);
> +			if (b) {
>  				dev->hose = b->sysdata;
> +				pci_bus_put(b);
> +			}

This is a gross hack to begin with, and it would be far better to get
rid of the whole "#ifdef __alpha__" block that contains this code.
I can't believe alpha is so special that it needs to do something
that no other arch needs.

>  		}
>  	}
>  #endif
> -- 
> 1.8.1.2
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3, part2 20/20] PCI, ARM: use hotplug-safe PCI bus iterators to walk PCI buses
  2013-05-26 15:53 ` [PATCH v3, part2 20/20] PCI, ARM: use hotplug-safe PCI bus " Jiang Liu
@ 2013-06-17 18:24   ` Bjorn Helgaas
  0 siblings, 0 replies; 36+ messages in thread
From: Bjorn Helgaas @ 2013-06-17 18:24 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Yinghai Lu, Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman,
	Gu Zheng, Toshi Kani, Myron Stowe, Yijing Wang, linux-pci,
	linux-kernel, Russell King, Thierry Reding, Rob Herring,
	linux-arm-kernel

On Sun, May 26, 2013 at 11:53:17PM +0800, Jiang Liu wrote:
> Enhance ARM architecture specific code to use new hotplug-safe PCI
> bus iterators to walk PCI buses.
> 
> Change pcibios_report_status implementation so that it doesn't access
> pci_root_buses global list. The pci_root_buses list will be scheduled
> to be removed.
> 
> Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Thierry Reding <thierry.reding@avionic-design.de>
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Rob Herring <rob.herring@calxeda.com>
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linux-kernel@vger.kernel.org
> ---
>  arch/arm/kernel/bios32.c           | 13 +------------
>  arch/arm/mach-footbridge/dc21285.c | 12 +++++++++++-
>  2 files changed, 12 insertions(+), 13 deletions(-)
> 
> diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
> index b2ed73c..50ebbe8 100644
> --- a/arch/arm/kernel/bios32.c
> +++ b/arch/arm/kernel/bios32.c
> @@ -22,7 +22,7 @@ static int debug_pci;
>   * We can't use pci_find_device() here since we are
>   * called from interrupt context.
>   */
> -static void pcibios_bus_report_status(struct pci_bus *bus, u_int status_mask, int warn)
> +void pcibios_bus_report_status(struct pci_bus *bus, u_int status_mask, int warn)
>  {
>  	struct pci_dev *dev;
>  
> @@ -55,17 +55,6 @@ static void pcibios_bus_report_status(struct pci_bus *bus, u_int status_mask, in
>  			pcibios_bus_report_status(dev->subordinate, status_mask, warn);
>  }
>  
> -void pcibios_report_status(u_int status_mask, int warn)
> -{
> -	struct list_head *l;
> -
> -	list_for_each(l, &pci_root_buses) {
> -		struct pci_bus *bus = pci_bus_b(l);
> -
> -		pcibios_bus_report_status(bus, status_mask, warn);
> -	}
> -}
> -
>  /*
>   * We don't use this to fix the device, but initialisation of it.
>   * It's not the correct use for this, but it works.
> diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c
> index a7cd2cf..a0f1d01 100644
> --- a/arch/arm/mach-footbridge/dc21285.c
> +++ b/arch/arm/mach-footbridge/dc21285.c
> @@ -35,7 +35,16 @@
>  				  PCI_STATUS_PARITY) << 16)
>  
>  extern int setup_arm_irq(int, struct irqaction *);
> -extern void pcibios_report_status(u_int status_mask, int warn);
> +extern void pcibios_report_bus_status(struct pci_bus *bus, u_int status_mask,
> +				      int warn);
> +
> +static struct pci_bus *dc21285_root_bus;
> +
> +static void pcibios_report_status(u_int status_mask, int warn)
> +{
> +	if (dc21285_root_bus)
> +		pcibios_report_bus_status(dc21285_root_bus, status_mask, warn);
> +}
>  
>  static unsigned long
>  dc21285_base_address(struct pci_bus *bus, unsigned int devfn)
> @@ -376,5 +385,6 @@ void __init dc21285_preinit(void)
>  
>  void __init dc21285_postinit(void)
>  {
> +	dc21285_root_bus = pci_get_next_root_bus(NULL);

It seems sort of ugly to scan the bus in pcibios_init_hw(), which
*returns* the struct pci_bus, then search for it here.  Why can't
we just remember the bus we scanned?

It's also a little dubious that we only do pcibios_report_status()
for footbridge.  That makes it look like it's debug code that might
not be necessary at all.

>  	register_isa_ports(DC21285_PCI_MEM, DC21285_PCI_IO, 0);
>  }
> -- 
> 1.8.1.2
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3, part2 01/20] PCI: introduce hotplug-safe PCI bus iterators
  2013-05-26 15:52 ` [PATCH v3, part2 01/20] PCI: introduce " Jiang Liu
  2013-05-28  4:22   ` Yinghai Lu
@ 2013-06-17 20:06   ` Bjorn Helgaas
  2013-06-18 16:23     ` Jiang Liu
  2013-06-20 16:18     ` Jiang Liu
  1 sibling, 2 replies; 36+ messages in thread
From: Bjorn Helgaas @ 2013-06-17 20:06 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Yinghai Lu, Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman,
	Gu Zheng, Toshi Kani, Myron Stowe, Yijing Wang, linux-pci,
	linux-kernel

On Sun, May 26, 2013 at 11:52:58PM +0800, Jiang Liu wrote:
> Introduce hotplug-safe PCI bus iterators as below, which hold a
> reference on the returned PCI bus object.
> bool pci_bus_exists(int domain, int busnr);
> struct pci_bus *pci_get_bus(int domain, int busnr);
> struct pci_bus *pci_get_next_bus(struct pci_bus *from);
> struct pci_bus *pci_get_next_root_bus(struct pci_bus *from);
> #define for_each_pci_bus(b) for (b = NULL; (b = pci_get_next_bus(b)); )
> #define for_each_pci_root_bus(b)  \
> 		for (b = NULL; (b = pci_get_next_root_bus(b)); )
> 
> The long-term goal is to remove hotplug-unsafe pci_find_bus(),
> pci_find_next_bus() and the global pci_root_buses list.

I think you should mark the unsafe interfaces as __deprecated so
users will get compile-time warnings.

I don't think pci_bus_exists() is a safe interface, because the value
it returns may be incorrect before the caller can look at it.  The
only safe thing would be to make it so we try to create the bus
and return failure if it already exists.  Then the mutex can be in
the code that creates the bus.

I don't see any uses of for_each_pci_bus(), so please remove that.

It sounds like we don't have a consensus on how to iterate over
PCI root buses.  If you separate that from the pci_get_bus()
changes, maybe we can at least move forward on the pci_get_bus()
stuff.

Bjorn

> These new interfaces may be a littler slower than existing interfaces,
> but it should be acceptable because they are not used on hot paths.
> 
> Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
> Acked-by: Yinghai Lu <yinghai@kernel.org>
> Cc: linux-pci@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> ---
>  drivers/pci/pci.h    |   1 +
>  drivers/pci/probe.c  |   2 +-
>  drivers/pci/search.c | 159 +++++++++++++++++++++++++++++++++++++++++----------
>  include/linux/pci.h  |  23 +++++++-
>  4 files changed, 153 insertions(+), 32 deletions(-)
> 
> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
> index 68678ed..8fe15f6 100644
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -126,6 +126,7 @@ static inline void pci_remove_legacy_files(struct pci_bus *bus) { return; }
>  
>  /* Lock for read/write access to pci device and bus lists */
>  extern struct rw_semaphore pci_bus_sem;
> +extern struct class pcibus_class;
>  
>  extern raw_spinlock_t pci_lock;
>  
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index 2830070..1004a05 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -93,7 +93,7 @@ static void release_pcibus_dev(struct device *dev)
>  	kfree(pci_bus);
>  }
>  
> -static struct class pcibus_class = {
> +struct class pcibus_class = {
>  	.name		= "pci_bus",
>  	.dev_release	= &release_pcibus_dev,
>  	.dev_attrs	= pcibus_dev_attrs,
> diff --git a/drivers/pci/search.c b/drivers/pci/search.c
> index d0627fa..16ccaf8 100644
> --- a/drivers/pci/search.c
> +++ b/drivers/pci/search.c
> @@ -52,20 +52,27 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev)
>  	return tmp;
>  }
>  
> -static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
> +struct pci_bus_match_arg {
> +	int domain;
> +	int bus;
> +};
> +
> +static int pci_match_bus(struct device *dev, const void *data)
>  {
> -	struct pci_bus* child;
> -	struct list_head *tmp;
> +	struct pci_bus *bus = to_pci_bus(dev);
> +	const struct pci_bus_match_arg *arg = data;
>  
> -	if(bus->number == busnr)
> -		return bus;
> +	return (pci_domain_nr(bus) == arg->domain && bus->number == arg->bus);
> +}
>  
> -	list_for_each(tmp, &bus->children) {
> -		child = pci_do_find_bus(pci_bus_b(tmp), busnr);
> -		if(child)
> -			return child;
> -	}
> -	return NULL;
> +static int pci_match_next_bus(struct device *dev, const void *data)
> +{
> +	return 1;
> +}
> +
> +static int pci_match_next_root_bus(struct device *dev, const void *data)
> +{
> +	return pci_is_root_bus(to_pci_bus(dev));
>  }
>  
>  /**
> @@ -76,20 +83,19 @@ static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
>   * Given a PCI bus number and domain number, the desired PCI bus is located
>   * in the global list of PCI buses.  If the bus is found, a pointer to its
>   * data structure is returned.  If no bus is found, %NULL is returned.
> + *
> + * Note: it's not hotplug safe, the returned bus may be destroyed at any time.
> + * Please use pci_get_bus() instead which holds a reference on the returned
> + * PCI bus.
>   */
> -struct pci_bus * pci_find_bus(int domain, int busnr)
> +struct pci_bus *pci_find_bus(int domain, int busnr)
>  {
> -	struct pci_bus *bus = NULL;
> -	struct pci_bus *tmp_bus;
> +	struct pci_bus *bus;
>  
> -	while ((bus = pci_find_next_bus(bus)) != NULL)  {
> -		if (pci_domain_nr(bus) != domain)
> -			continue;
> -		tmp_bus = pci_do_find_bus(bus, busnr);
> -		if (tmp_bus)
> -			return tmp_bus;
> -	}
> -	return NULL;
> +	bus = pci_get_bus(domain, busnr);
> +	pci_bus_put(bus);
> +
> +	return bus;
>  }
>  
>  /**
> @@ -100,21 +106,114 @@ struct pci_bus * pci_find_bus(int domain, int busnr)
>   * initiated by passing %NULL as the @from argument.  Otherwise if
>   * @from is not %NULL, searches continue from next device on the
>   * global list.
> + *
> + * Note: it's not hotplug safe, the returned bus may be destroyed at any time.
> + * Please use pci_get_next_root_bus() instead which holds a reference
> + * on the returned PCI root bus.
>   */
>  struct pci_bus * 
>  pci_find_next_bus(const struct pci_bus *from)
>  {
> -	struct list_head *n;
> -	struct pci_bus *b = NULL;
> +	struct device *dev = from ? (struct device *)&from->dev : NULL;
> +
> +	dev = class_find_device(&pcibus_class, dev, NULL,
> +				&pci_match_next_root_bus);
> +	if (dev) {
> +		put_device(dev);
> +		return to_pci_bus(dev);
> +	}
> +
> +	return NULL;
> +}
> +
> +bool pci_bus_exists(int domain, int busnr)
> +{
> +	struct device *dev;
> +	struct pci_bus_match_arg arg = { domain, busnr };
>  
>  	WARN_ON(in_interrupt());
> -	down_read(&pci_bus_sem);
> -	n = from ? from->node.next : pci_root_buses.next;
> -	if (n != &pci_root_buses)
> -		b = pci_bus_b(n);
> -	up_read(&pci_bus_sem);
> -	return b;
> +	dev = class_find_device(&pcibus_class, NULL, &arg, &pci_match_bus);
> +	if (dev)
> +		put_device(dev);
> +
> +	return dev != NULL;
> +}
> +EXPORT_SYMBOL(pci_bus_exists);
> +
> +/**
> + * pci_get_bus - locate PCI bus from a given domain and bus number
> + * @domain: number of PCI domain to search
> + * @busnr: number of desired PCI bus
> + *
> + * Given a PCI bus number and domain number, the desired PCI bus is located.
> + * If the bus is found, a pointer to its data structure is returned.
> + * If no bus is found, %NULL is returned.
> + * Caller needs to release the returned bus by calling pci_bus_put().
> + */
> +struct pci_bus *pci_get_bus(int domain, int busnr)
> +{
> +	struct device *dev;
> +	struct pci_bus_match_arg arg = { domain, busnr };
> +
> +	WARN_ON(in_interrupt());
> +	dev = class_find_device(&pcibus_class, NULL, &arg, &pci_match_bus);
> +	if (dev)
> +		return to_pci_bus(dev);
> +
> +	return NULL;
> +}
> +EXPORT_SYMBOL(pci_get_bus);
> +
> +/**
> + * pci_get_next_bus - begin or continue searching for a PCI bus
> + * @from: Previous PCI bus found, or %NULL for new search.
> + *
> + * Iterates through the list of known PCI busses. If a PCI bus is found,
> + * the reference count to the bus is incremented and a pointer to it is
> + * returned. Otherwise, %NULL is returned. A new search is initiated by
> + * passing %NULL as the @from argument. Otherwise if @from is not %NULL,
> + * searches continue from next bus on the global list. The reference count
> + * for @from is always decremented if it is not %NULL.
> + */
> +struct pci_bus *pci_get_next_bus(struct pci_bus *from)
> +{
> +	struct device *dev = from ? &from->dev : NULL;
> +
> +	WARN_ON(in_interrupt());
> +	dev = class_find_device(&pcibus_class, dev, NULL, &pci_match_next_bus);
> +	pci_bus_put(from);
> +	if (dev)
> +		return to_pci_bus(dev);
> +
> +	return NULL;
> +}
> +EXPORT_SYMBOL(pci_get_next_bus);
> +
> +/**
> + * pci_find_next_root_bus - begin or continue searching for a PCI root bus
> + * @from: Previous PCI bus found, or %NULL for new search.
> + *
> + * Iterates through the list of known PCI root busses. If a PCI bus is found,
> + * the reference count to the root bus is incremented and a pointer to it is
> + * returned. Otherwise, %NULL is returned. A new search is initiated by
> + * passing %NULL as the @from argument. Otherwise if @from is not %NULL,
> + * searches continue from next root bus on the global list. The reference
> + * count for @from is always decremented if it is not %NULL.
> + */
> +struct pci_bus *pci_get_next_root_bus(struct pci_bus *from)
> +{
> +	struct device *dev = from ? &from->dev : NULL;
> +
> +	WARN_ON(in_interrupt());
> +	dev = class_find_device(&pcibus_class, dev, NULL,
> +				&pci_match_next_root_bus);
> +	pci_bus_put(from);
> +	if (dev)
> +		return to_pci_bus(dev);
> +
> +	return NULL;
>  }
> +EXPORT_SYMBOL(pci_get_next_root_bus);
>  
>  /**
>   * pci_get_slot - locate PCI device for a given PCI slot
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 7b23fa0..1e43423 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -454,6 +454,9 @@ struct pci_bus {
>  
>  #define pci_bus_b(n)	list_entry(n, struct pci_bus, node)
>  #define to_pci_bus(n)	container_of(n, struct pci_bus, dev)
> +#define for_each_pci_bus(b)	for (b = NULL; (b = pci_get_next_bus(b)); )
> +#define for_each_pci_root_bus(b) \
> +			for (b = NULL; (b = pci_get_next_root_bus(b)); )
>  
>  /*
>   * Returns true if the pci bus is root (behind host-pci bridge),
> @@ -718,7 +721,6 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
>  void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
>  			     struct pci_bus_region *region);
>  void pcibios_scan_specific_bus(int busn);
> -struct pci_bus *pci_find_bus(int domain, int busnr);
>  void pci_bus_add_devices(const struct pci_bus *bus);
>  struct pci_bus * __deprecated pci_scan_bus_parented(struct device *parent,
>  			int bus, struct pci_ops *ops, void *sysdata);
> @@ -778,8 +780,15 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap);
>  int pci_find_next_ext_capability(struct pci_dev *dev, int pos, int cap);
>  int pci_find_ht_capability(struct pci_dev *dev, int ht_cap);
>  int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
> +
> +struct pci_bus *pci_find_bus(int domain, int busnr);
>  struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
>  
> +bool pci_bus_exists(int domain, int busnr);
> +struct pci_bus *pci_get_bus(int domain, int busnr);
> +struct pci_bus *pci_get_next_bus(struct pci_bus *from);
> +struct pci_bus *pci_get_next_root_bus(struct pci_bus *from);
> +
>  struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
>  				struct pci_dev *from);
>  struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
> @@ -1430,6 +1439,18 @@ static inline void pci_unblock_cfg_access(struct pci_dev *dev)
>  static inline struct pci_bus *pci_find_next_bus(const struct pci_bus *from)
>  { return NULL; }
>  
> +static inline bool pci_bus_exists(int domain, int busnr)
> +{ return false; }
> +
> +static inline struct pci_bus *pci_get_bus(int domain, int busnr)
> +{ return NULL; }
> +
> +static inline struct pci_bus *pci_get_next_bus(struct pci_bus *from)
> +{ return NULL; }
> +
> +static inline struct pci_bus *pci_get_next_root_bus(struct pci_bus *from)
> +{ return NULL; }
> +
>  static inline struct pci_dev *pci_get_slot(struct pci_bus *bus,
>  						unsigned int devfn)
>  { return NULL; }
> -- 
> 1.8.1.2
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3, part2 15/20] PCI, EDAC: use hotplug-safe PCI bus iterators to walk PCI buses
  2013-05-26 15:53 ` [PATCH v3, part2 15/20] PCI, EDAC: use hotplug-safe PCI bus " Jiang Liu
@ 2013-06-17 20:18   ` Bjorn Helgaas
  2013-06-18 16:33     ` Jiang Liu
  0 siblings, 1 reply; 36+ messages in thread
From: Bjorn Helgaas @ 2013-06-17 20:18 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Yinghai Lu, Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman,
	Gu Zheng, Toshi Kani, Myron Stowe, Yijing Wang, linux-pci,
	linux-kernel, Mauro Carvalho Chehab, Doug Thompson, linux-edac

On Sun, May 26, 2013 at 11:53:12PM +0800, Jiang Liu wrote:
> Enhance EDAC drviers to use hotplug-safe iterators to walk PCI buses.
> 
> Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
> Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
> Cc: Doug Thompson <dougthompson@xmission.com>
> Cc: linux-edac@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> ---
>  drivers/edac/i7core_edac.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
> index 0ec3e95..7146e10 100644
> --- a/drivers/edac/i7core_edac.c
> +++ b/drivers/edac/i7core_edac.c
> @@ -1296,7 +1296,7 @@ static unsigned i7core_pci_lastbus(void)
>  	int last_bus = 0, bus;
>  	struct pci_bus *b = NULL;
>  
> -	while ((b = pci_find_next_bus(b)) != NULL) {
> +	for_each_pci_root_bus(b) {

This doesn't look equivalent.  Previously, we iterated over all PCI
buses, so we returned the highest bus number seen anywhere.  Now we
only look at root buses, so we return the highest bus number of any
root bus.  But if that root bus has a bridge on it, obviously the
bus on the other side has a higher number.

Even with that fix, a hot-add at the same time i7core_probe() runs
could mean an incorrect result.  This is all very i7 topology-dependent,
so I don't think the PCI core can do anything more than avoid oopses
from traversing lists incorrectly.

Bjorn

>  		bus = b->number;
>  		edac_dbg(0, "Found bus %d\n", bus);
>  		if (bus > last_bus)
> -- 
> 1.8.1.2
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3, part2 17/20] PCI, iommu: use hotplug-safe iterators to walk PCI buses
  2013-05-26 15:53 ` [PATCH v3, part2 17/20] PCI, iommu: " Jiang Liu
@ 2013-06-17 20:20   ` Bjorn Helgaas
  2013-06-17 20:34     ` Don Dutile
  0 siblings, 1 reply; 36+ messages in thread
From: Bjorn Helgaas @ 2013-06-17 20:20 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Yinghai Lu, Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman,
	Gu Zheng, Toshi Kani, Myron Stowe, Yijing Wang, linux-pci,
	linux-kernel, Joerg Roedel, Ingo Molnar, Donald Dutile,
	Hannes Reinecke, Li, Zhen-Hua, iommu

On Sun, May 26, 2013 at 11:53:14PM +0800, Jiang Liu wrote:
> Enhance iommu drviers to use hotplug-safe iterators to walk
> PCI buses.
> 
> Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
> Cc: Joerg Roedel <joro@8bytes.org>
> Cc: Ingo Molnar <mingo@kernel.org>
> Cc: Donald Dutile <ddutile@redhat.com>
> Cc: Hannes Reinecke <hare@suse.de>
> Cc: "Li, Zhen-Hua" <zhen-hual@hp.com>
> Cc: iommu@lists.linux-foundation.org
> Cc: linux-kernel@vger.kernel.org
> ---
>  drivers/iommu/amd_iommu.c | 4 +++-
>  drivers/iommu/dmar.c      | 6 ++++--

The AMD and Intel IOMMU drivers are very different, and I would
split this into a patch for each.

>  2 files changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
> index 21d02b0..eef7a7e 100644
> --- a/drivers/iommu/amd_iommu.c
> +++ b/drivers/iommu/amd_iommu.c
> @@ -352,6 +352,7 @@ static int init_iommu_group(struct device *dev)
>  	struct iommu_dev_data *dev_data;
>  	struct iommu_group *group;
>  	struct pci_dev *dma_pdev;
> +	struct pci_bus *b = NULL;
>  	int ret;
>  
>  	group = iommu_group_get(dev);
> @@ -388,7 +389,7 @@ static int init_iommu_group(struct device *dev)
>  		 * the alias.  Be careful to also test the parent device if
>  		 * we think the alias is the root of the group.
>  		 */
> -		bus = pci_find_bus(0, alias >> 8);
> +		b = bus = pci_get_bus(0, alias >> 8);
>  		if (!bus)
>  			goto use_group;
>  
> @@ -408,6 +409,7 @@ static int init_iommu_group(struct device *dev)
>  	dma_pdev = get_isolation_root(pci_dev_get(to_pci_dev(dev)));
>  use_pdev:
>  	ret = use_pdev_iommu_group(dma_pdev, dev);
> +	pci_bus_put(b);
>  	pci_dev_put(dma_pdev);
>  	return ret;
>  use_group:
> diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
> index a7967ce..7162787 100644
> --- a/drivers/iommu/dmar.c
> +++ b/drivers/iommu/dmar.c
> @@ -67,12 +67,12 @@ static void __init dmar_register_drhd_unit(struct dmar_drhd_unit *drhd)
>  static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
>  					   struct pci_dev **dev, u16 segment)
>  {
> -	struct pci_bus *bus;
> +	struct pci_bus *b, *bus;
>  	struct pci_dev *pdev = NULL;
>  	struct acpi_dmar_pci_path *path;
>  	int count;
>  
> -	bus = pci_find_bus(segment, scope->bus);
> +	b = bus = pci_get_bus(segment, scope->bus);
>  	path = (struct acpi_dmar_pci_path *)(scope + 1);
>  	count = (scope->length - sizeof(struct acpi_dmar_device_scope))
>  		/ sizeof(struct acpi_dmar_pci_path);
> @@ -97,6 +97,8 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
>  		count --;
>  		bus = pdev->subordinate;
>  	}
> +	pci_bus_put(b);
> +
>  	if (!pdev) {
>  		pr_warn("Device scope device [%04x:%02x:%02x.%02x] not found\n",
>  			segment, scope->bus, path->dev, path->fn);
> -- 
> 1.8.1.2
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3, part2 17/20] PCI, iommu: use hotplug-safe iterators to walk PCI buses
  2013-06-17 20:20   ` Bjorn Helgaas
@ 2013-06-17 20:34     ` Don Dutile
  2013-06-18 16:34       ` Jiang Liu
  0 siblings, 1 reply; 36+ messages in thread
From: Don Dutile @ 2013-06-17 20:34 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Jiang Liu, Yinghai Lu, Jiang Liu, Rafael J . Wysocki,
	Greg Kroah-Hartman, Gu Zheng, Toshi Kani, Myron Stowe,
	Yijing Wang, linux-pci, linux-kernel, Joerg Roedel, Ingo Molnar,
	Hannes Reinecke, Li, Zhen-Hua, iommu

On 06/17/2013 04:20 PM, Bjorn Helgaas wrote:
> On Sun, May 26, 2013 at 11:53:14PM +0800, Jiang Liu wrote:
>> Enhance iommu drviers to use hotplug-safe iterators to walk
>> PCI buses.
>>
>> Signed-off-by: Jiang Liu<jiang.liu@huawei.com>
>> Cc: Joerg Roedel<joro@8bytes.org>
>> Cc: Ingo Molnar<mingo@kernel.org>
>> Cc: Donald Dutile<ddutile@redhat.com>
>> Cc: Hannes Reinecke<hare@suse.de>
>> Cc: "Li, Zhen-Hua"<zhen-hual@hp.com>
>> Cc: iommu@lists.linux-foundation.org
>> Cc: linux-kernel@vger.kernel.org
>> ---
>>   drivers/iommu/amd_iommu.c | 4 +++-
>>   drivers/iommu/dmar.c      | 6 ++++--
>
> The AMD and Intel IOMMU drivers are very different, and I would
> split this into a patch for each.
>
+1

>>   2 files changed, 7 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
>> index 21d02b0..eef7a7e 100644
>> --- a/drivers/iommu/amd_iommu.c
>> +++ b/drivers/iommu/amd_iommu.c
>> @@ -352,6 +352,7 @@ static int init_iommu_group(struct device *dev)
>>   	struct iommu_dev_data *dev_data;
>>   	struct iommu_group *group;
>>   	struct pci_dev *dma_pdev;
>> +	struct pci_bus *b = NULL;
>>   	int ret;
>>
>>   	group = iommu_group_get(dev);
>> @@ -388,7 +389,7 @@ static int init_iommu_group(struct device *dev)
>>   		 * the alias.  Be careful to also test the parent device if
>>   		 * we think the alias is the root of the group.
>>   		 */
>> -		bus = pci_find_bus(0, alias>>  8);
>> +		b = bus = pci_get_bus(0, alias>>  8);
>>   		if (!bus)
>>   			goto use_group;
>>
>> @@ -408,6 +409,7 @@ static int init_iommu_group(struct device *dev)
>>   	dma_pdev = get_isolation_root(pci_dev_get(to_pci_dev(dev)));
>>   use_pdev:
>>   	ret = use_pdev_iommu_group(dma_pdev, dev);
>> +	pci_bus_put(b);
>>   	pci_dev_put(dma_pdev);
>>   	return ret;
>>   use_group:
>> diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
>> index a7967ce..7162787 100644
>> --- a/drivers/iommu/dmar.c
>> +++ b/drivers/iommu/dmar.c
>> @@ -67,12 +67,12 @@ static void __init dmar_register_drhd_unit(struct dmar_drhd_unit *drhd)
>>   static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
>>   					   struct pci_dev **dev, u16 segment)
>>   {
>> -	struct pci_bus *bus;
>> +	struct pci_bus *b, *bus;
>>   	struct pci_dev *pdev = NULL;
>>   	struct acpi_dmar_pci_path *path;
>>   	int count;
>>
>> -	bus = pci_find_bus(segment, scope->bus);
>> +	b = bus = pci_get_bus(segment, scope->bus);
>>   	path = (struct acpi_dmar_pci_path *)(scope + 1);
>>   	count = (scope->length - sizeof(struct acpi_dmar_device_scope))
>>   		/ sizeof(struct acpi_dmar_pci_path);
>> @@ -97,6 +97,8 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
>>   		count --;
>>   		bus = pdev->subordinate;
>>   	}
>> +	pci_bus_put(b);
>> +
>>   	if (!pdev) {
>>   		pr_warn("Device scope device [%04x:%02x:%02x.%02x] not found\n",
>>   			segment, scope->bus, path->dev, path->fn);
>> --
>> 1.8.1.2
>>


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3, part2 01/20] PCI: introduce hotplug-safe PCI bus iterators
  2013-06-17 20:06   ` Bjorn Helgaas
@ 2013-06-18 16:23     ` Jiang Liu
  2013-06-20 16:18     ` Jiang Liu
  1 sibling, 0 replies; 36+ messages in thread
From: Jiang Liu @ 2013-06-18 16:23 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Yinghai Lu, Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman,
	Gu Zheng, Toshi Kani, Myron Stowe, Yijing Wang, linux-pci,
	linux-kernel

On 06/18/2013 04:06 AM, Bjorn Helgaas wrote:
> On Sun, May 26, 2013 at 11:52:58PM +0800, Jiang Liu wrote:
>> Introduce hotplug-safe PCI bus iterators as below, which hold a
>> reference on the returned PCI bus object.
>> bool pci_bus_exists(int domain, int busnr);
>> struct pci_bus *pci_get_bus(int domain, int busnr);
>> struct pci_bus *pci_get_next_bus(struct pci_bus *from);
>> struct pci_bus *pci_get_next_root_bus(struct pci_bus *from);
>> #define for_each_pci_bus(b) for (b = NULL; (b = pci_get_next_bus(b)); )
>> #define for_each_pci_root_bus(b)  \
>> 		for (b = NULL; (b = pci_get_next_root_bus(b)); )
>>
>> The long-term goal is to remove hotplug-unsafe pci_find_bus(),
>> pci_find_next_bus() and the global pci_root_buses list.
> 
> I think you should mark the unsafe interfaces as __deprecated so
> users will get compile-time warnings.
> 
> I don't think pci_bus_exists() is a safe interface, because the value
> it returns may be incorrect before the caller can look at it.  The
> only safe thing would be to make it so we try to create the bus
> and return failure if it already exists.  Then the mutex can be in
> the code that creates the bus.
> 
> I don't see any uses of for_each_pci_bus(), so please remove that.
> 
> It sounds like we don't have a consensus on how to iterate over
> PCI root buses.  If you separate that from the pci_get_bus()
> changes, maybe we can at least move forward on the pci_get_bus()
> stuff.
Hi Bjorn,
	Thanks for review, will send out next version according to your
suggestions. And need more investigation about pci_bus_exists() interface.
Regards!
Gerry

> 
> Bjorn
> 
>> These new interfaces may be a littler slower than existing interfaces,
>> but it should be acceptable because they are not used on hot paths.
>>
>> Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
>> Acked-by: Yinghai Lu <yinghai@kernel.org>
>> Cc: linux-pci@vger.kernel.org
>> Cc: linux-kernel@vger.kernel.org
>> ---
>>  drivers/pci/pci.h    |   1 +
>>  drivers/pci/probe.c  |   2 +-
>>  drivers/pci/search.c | 159 +++++++++++++++++++++++++++++++++++++++++----------
>>  include/linux/pci.h  |  23 +++++++-
>>  4 files changed, 153 insertions(+), 32 deletions(-)
>>
>> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
>> index 68678ed..8fe15f6 100644
>> --- a/drivers/pci/pci.h
>> +++ b/drivers/pci/pci.h
>> @@ -126,6 +126,7 @@ static inline void pci_remove_legacy_files(struct pci_bus *bus) { return; }
>>  
>>  /* Lock for read/write access to pci device and bus lists */
>>  extern struct rw_semaphore pci_bus_sem;
>> +extern struct class pcibus_class;
>>  
>>  extern raw_spinlock_t pci_lock;
>>  
>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>> index 2830070..1004a05 100644
>> --- a/drivers/pci/probe.c
>> +++ b/drivers/pci/probe.c
>> @@ -93,7 +93,7 @@ static void release_pcibus_dev(struct device *dev)
>>  	kfree(pci_bus);
>>  }
>>  
>> -static struct class pcibus_class = {
>> +struct class pcibus_class = {
>>  	.name		= "pci_bus",
>>  	.dev_release	= &release_pcibus_dev,
>>  	.dev_attrs	= pcibus_dev_attrs,
>> diff --git a/drivers/pci/search.c b/drivers/pci/search.c
>> index d0627fa..16ccaf8 100644
>> --- a/drivers/pci/search.c
>> +++ b/drivers/pci/search.c
>> @@ -52,20 +52,27 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev)
>>  	return tmp;
>>  }
>>  
>> -static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
>> +struct pci_bus_match_arg {
>> +	int domain;
>> +	int bus;
>> +};
>> +
>> +static int pci_match_bus(struct device *dev, const void *data)
>>  {
>> -	struct pci_bus* child;
>> -	struct list_head *tmp;
>> +	struct pci_bus *bus = to_pci_bus(dev);
>> +	const struct pci_bus_match_arg *arg = data;
>>  
>> -	if(bus->number == busnr)
>> -		return bus;
>> +	return (pci_domain_nr(bus) == arg->domain && bus->number == arg->bus);
>> +}
>>  
>> -	list_for_each(tmp, &bus->children) {
>> -		child = pci_do_find_bus(pci_bus_b(tmp), busnr);
>> -		if(child)
>> -			return child;
>> -	}
>> -	return NULL;
>> +static int pci_match_next_bus(struct device *dev, const void *data)
>> +{
>> +	return 1;
>> +}
>> +
>> +static int pci_match_next_root_bus(struct device *dev, const void *data)
>> +{
>> +	return pci_is_root_bus(to_pci_bus(dev));
>>  }
>>  
>>  /**
>> @@ -76,20 +83,19 @@ static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
>>   * Given a PCI bus number and domain number, the desired PCI bus is located
>>   * in the global list of PCI buses.  If the bus is found, a pointer to its
>>   * data structure is returned.  If no bus is found, %NULL is returned.
>> + *
>> + * Note: it's not hotplug safe, the returned bus may be destroyed at any time.
>> + * Please use pci_get_bus() instead which holds a reference on the returned
>> + * PCI bus.
>>   */
>> -struct pci_bus * pci_find_bus(int domain, int busnr)
>> +struct pci_bus *pci_find_bus(int domain, int busnr)
>>  {
>> -	struct pci_bus *bus = NULL;
>> -	struct pci_bus *tmp_bus;
>> +	struct pci_bus *bus;
>>  
>> -	while ((bus = pci_find_next_bus(bus)) != NULL)  {
>> -		if (pci_domain_nr(bus) != domain)
>> -			continue;
>> -		tmp_bus = pci_do_find_bus(bus, busnr);
>> -		if (tmp_bus)
>> -			return tmp_bus;
>> -	}
>> -	return NULL;
>> +	bus = pci_get_bus(domain, busnr);
>> +	pci_bus_put(bus);
>> +
>> +	return bus;
>>  }
>>  
>>  /**
>> @@ -100,21 +106,114 @@ struct pci_bus * pci_find_bus(int domain, int busnr)
>>   * initiated by passing %NULL as the @from argument.  Otherwise if
>>   * @from is not %NULL, searches continue from next device on the
>>   * global list.
>> + *
>> + * Note: it's not hotplug safe, the returned bus may be destroyed at any time.
>> + * Please use pci_get_next_root_bus() instead which holds a reference
>> + * on the returned PCI root bus.
>>   */
>>  struct pci_bus * 
>>  pci_find_next_bus(const struct pci_bus *from)
>>  {
>> -	struct list_head *n;
>> -	struct pci_bus *b = NULL;
>> +	struct device *dev = from ? (struct device *)&from->dev : NULL;
>> +
>> +	dev = class_find_device(&pcibus_class, dev, NULL,
>> +				&pci_match_next_root_bus);
>> +	if (dev) {
>> +		put_device(dev);
>> +		return to_pci_bus(dev);
>> +	}
>> +
>> +	return NULL;
>> +}
>> +
>> +bool pci_bus_exists(int domain, int busnr)
>> +{
>> +	struct device *dev;
>> +	struct pci_bus_match_arg arg = { domain, busnr };
>>  
>>  	WARN_ON(in_interrupt());
>> -	down_read(&pci_bus_sem);
>> -	n = from ? from->node.next : pci_root_buses.next;
>> -	if (n != &pci_root_buses)
>> -		b = pci_bus_b(n);
>> -	up_read(&pci_bus_sem);
>> -	return b;
>> +	dev = class_find_device(&pcibus_class, NULL, &arg, &pci_match_bus);
>> +	if (dev)
>> +		put_device(dev);
>> +
>> +	return dev != NULL;
>> +}
>> +EXPORT_SYMBOL(pci_bus_exists);
>> +
>> +/**
>> + * pci_get_bus - locate PCI bus from a given domain and bus number
>> + * @domain: number of PCI domain to search
>> + * @busnr: number of desired PCI bus
>> + *
>> + * Given a PCI bus number and domain number, the desired PCI bus is located.
>> + * If the bus is found, a pointer to its data structure is returned.
>> + * If no bus is found, %NULL is returned.
>> + * Caller needs to release the returned bus by calling pci_bus_put().
>> + */
>> +struct pci_bus *pci_get_bus(int domain, int busnr)
>> +{
>> +	struct device *dev;
>> +	struct pci_bus_match_arg arg = { domain, busnr };
>> +
>> +	WARN_ON(in_interrupt());
>> +	dev = class_find_device(&pcibus_class, NULL, &arg, &pci_match_bus);
>> +	if (dev)
>> +		return to_pci_bus(dev);
>> +
>> +	return NULL;
>> +}
>> +EXPORT_SYMBOL(pci_get_bus);
>> +
>> +/**
>> + * pci_get_next_bus - begin or continue searching for a PCI bus
>> + * @from: Previous PCI bus found, or %NULL for new search.
>> + *
>> + * Iterates through the list of known PCI busses. If a PCI bus is found,
>> + * the reference count to the bus is incremented and a pointer to it is
>> + * returned. Otherwise, %NULL is returned. A new search is initiated by
>> + * passing %NULL as the @from argument. Otherwise if @from is not %NULL,
>> + * searches continue from next bus on the global list. The reference count
>> + * for @from is always decremented if it is not %NULL.
>> + */
>> +struct pci_bus *pci_get_next_bus(struct pci_bus *from)
>> +{
>> +	struct device *dev = from ? &from->dev : NULL;
>> +
>> +	WARN_ON(in_interrupt());
>> +	dev = class_find_device(&pcibus_class, dev, NULL, &pci_match_next_bus);
>> +	pci_bus_put(from);
>> +	if (dev)
>> +		return to_pci_bus(dev);
>> +
>> +	return NULL;
>> +}
>> +EXPORT_SYMBOL(pci_get_next_bus);
>> +
>> +/**
>> + * pci_find_next_root_bus - begin or continue searching for a PCI root bus
>> + * @from: Previous PCI bus found, or %NULL for new search.
>> + *
>> + * Iterates through the list of known PCI root busses. If a PCI bus is found,
>> + * the reference count to the root bus is incremented and a pointer to it is
>> + * returned. Otherwise, %NULL is returned. A new search is initiated by
>> + * passing %NULL as the @from argument. Otherwise if @from is not %NULL,
>> + * searches continue from next root bus on the global list. The reference
>> + * count for @from is always decremented if it is not %NULL.
>> + */
>> +struct pci_bus *pci_get_next_root_bus(struct pci_bus *from)
>> +{
>> +	struct device *dev = from ? &from->dev : NULL;
>> +
>> +	WARN_ON(in_interrupt());
>> +	dev = class_find_device(&pcibus_class, dev, NULL,
>> +				&pci_match_next_root_bus);
>> +	pci_bus_put(from);
>> +	if (dev)
>> +		return to_pci_bus(dev);
>> +
>> +	return NULL;
>>  }
>> +EXPORT_SYMBOL(pci_get_next_root_bus);
>>  
>>  /**
>>   * pci_get_slot - locate PCI device for a given PCI slot
>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>> index 7b23fa0..1e43423 100644
>> --- a/include/linux/pci.h
>> +++ b/include/linux/pci.h
>> @@ -454,6 +454,9 @@ struct pci_bus {
>>  
>>  #define pci_bus_b(n)	list_entry(n, struct pci_bus, node)
>>  #define to_pci_bus(n)	container_of(n, struct pci_bus, dev)
>> +#define for_each_pci_bus(b)	for (b = NULL; (b = pci_get_next_bus(b)); )
>> +#define for_each_pci_root_bus(b) \
>> +			for (b = NULL; (b = pci_get_next_root_bus(b)); )
>>  
>>  /*
>>   * Returns true if the pci bus is root (behind host-pci bridge),
>> @@ -718,7 +721,6 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
>>  void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
>>  			     struct pci_bus_region *region);
>>  void pcibios_scan_specific_bus(int busn);
>> -struct pci_bus *pci_find_bus(int domain, int busnr);
>>  void pci_bus_add_devices(const struct pci_bus *bus);
>>  struct pci_bus * __deprecated pci_scan_bus_parented(struct device *parent,
>>  			int bus, struct pci_ops *ops, void *sysdata);
>> @@ -778,8 +780,15 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap);
>>  int pci_find_next_ext_capability(struct pci_dev *dev, int pos, int cap);
>>  int pci_find_ht_capability(struct pci_dev *dev, int ht_cap);
>>  int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
>> +
>> +struct pci_bus *pci_find_bus(int domain, int busnr);
>>  struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
>>  
>> +bool pci_bus_exists(int domain, int busnr);
>> +struct pci_bus *pci_get_bus(int domain, int busnr);
>> +struct pci_bus *pci_get_next_bus(struct pci_bus *from);
>> +struct pci_bus *pci_get_next_root_bus(struct pci_bus *from);
>> +
>>  struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
>>  				struct pci_dev *from);
>>  struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
>> @@ -1430,6 +1439,18 @@ static inline void pci_unblock_cfg_access(struct pci_dev *dev)
>>  static inline struct pci_bus *pci_find_next_bus(const struct pci_bus *from)
>>  { return NULL; }
>>  
>> +static inline bool pci_bus_exists(int domain, int busnr)
>> +{ return false; }
>> +
>> +static inline struct pci_bus *pci_get_bus(int domain, int busnr)
>> +{ return NULL; }
>> +
>> +static inline struct pci_bus *pci_get_next_bus(struct pci_bus *from)
>> +{ return NULL; }
>> +
>> +static inline struct pci_bus *pci_get_next_root_bus(struct pci_bus *from)
>> +{ return NULL; }
>> +
>>  static inline struct pci_dev *pci_get_slot(struct pci_bus *bus,
>>  						unsigned int devfn)
>>  { return NULL; }
>> -- 
>> 1.8.1.2
>>


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3, part2 15/20] PCI, EDAC: use hotplug-safe PCI bus iterators to walk PCI buses
  2013-06-17 20:18   ` Bjorn Helgaas
@ 2013-06-18 16:33     ` Jiang Liu
  2013-06-26  3:00       ` Bjorn Helgaas
  0 siblings, 1 reply; 36+ messages in thread
From: Jiang Liu @ 2013-06-18 16:33 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Yinghai Lu, Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman,
	Gu Zheng, Toshi Kani, Myron Stowe, Yijing Wang, linux-pci,
	linux-kernel, Mauro Carvalho Chehab, Doug Thompson, linux-edac

On 06/18/2013 04:18 AM, Bjorn Helgaas wrote:
> On Sun, May 26, 2013 at 11:53:12PM +0800, Jiang Liu wrote:
>> Enhance EDAC drviers to use hotplug-safe iterators to walk PCI buses.
>>
>> Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
>> Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
>> Cc: Doug Thompson <dougthompson@xmission.com> r
>> Cc: linux-edac@vger.kernel.org
>> Cc: linux-kernel@vger.kernel.org
>> ---
>>  drivers/edac/i7core_edac.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
>> index 0ec3e95..7146e10 100644
>> --- a/drivers/edac/i7core_edac.c
>> +++ b/drivers/edac/i7core_edac.c
>> @@ -1296,7 +1296,7 @@ static unsigned i7core_pci_lastbus(void)
>>  	int last_bus = 0, bus;
>>  	struct pci_bus *b = NULL;
>>  
>> -	while ((b = pci_find_next_bus(b)) != NULL) {
>> +	for_each_pci_root_bus(b) {
> 
> This doesn't look equivalent.  Previously, we iterated over all PCI
> buses, so we returned the highest bus number seen anywhere.  Now we
> only look at root buses, so we return the highest bus number of any
> root bus.  But if that root bus has a bridge on it, obviously the
> bus on the other side has a higher number.
Hi Bjorn,
	I think the name pci_find_next_bus() is misleading, it should be named
pci_find_next_root_bus() actually because it returns next root bus indeed.

> 
> Even with that fix, a hot-add at the same time i7core_probe() runs
> could mean an incorrect result.  This is all very i7 topology-dependent,
> so I don't think the PCI core can do anything more than avoid oopses
> from traversing lists incorrectly.
Yeah, it's very architecture specific. I think i7core_edac assume no PCI
root bus hotplug on i7 platforms because it's desktop or mobile processors.

> 
> Bjorn
> 
>>  		bus = b->number;
>>  		edac_dbg(0, "Found bus %d\n", bus);
>>  		if (bus > last_bus)
>> -- 
>> 1.8.1.2
>>


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3, part2 17/20] PCI, iommu: use hotplug-safe iterators to walk PCI buses
  2013-06-17 20:34     ` Don Dutile
@ 2013-06-18 16:34       ` Jiang Liu
  0 siblings, 0 replies; 36+ messages in thread
From: Jiang Liu @ 2013-06-18 16:34 UTC (permalink / raw)
  To: Don Dutile
  Cc: Bjorn Helgaas, Yinghai Lu, Jiang Liu, Rafael J . Wysocki,
	Greg Kroah-Hartman, Gu Zheng, Toshi Kani, Myron Stowe,
	Yijing Wang, linux-pci, linux-kernel, Joerg Roedel, Ingo Molnar,
	Hannes Reinecke, Li, Zhen-Hua, iommu

On 06/18/2013 04:34 AM, Don Dutile wrote:
> On 06/17/2013 04:20 PM, Bjorn Helgaas wrote:
>> On Sun, May 26, 2013 at 11:53:14PM +0800, Jiang Liu wrote:
>>> Enhance iommu drviers to use hotplug-safe iterators to walk
>>> PCI buses.
>>>
>>> Signed-off-by: Jiang Liu<jiang.liu@huawei.com>
>>> Cc: Joerg Roedel<joro@8bytes.org>
>>> Cc: Ingo Molnar<mingo@kernel.org>
>>> Cc: Donald Dutile<ddutile@redhat.com>
>>> Cc: Hannes Reinecke<hare@suse.de>
>>> Cc: "Li, Zhen-Hua"<zhen-hual@hp.com>
>>> Cc: iommu@lists.linux-foundation.org
>>> Cc: linux-kernel@vger.kernel.org
>>> ---
>>>   drivers/iommu/amd_iommu.c | 4 +++-
>>>   drivers/iommu/dmar.c      | 6 ++++--
>>
>> The AMD and Intel IOMMU drivers are very different, and I would
>> split this into a patch for each.
>>
> +1
Hi Don and Bjorn,

Thanks for review, will split it into two patches.
Regards!
Gerry
> 
>>>   2 files changed, 7 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
>>> index 21d02b0..eef7a7e 100644
>>> --- a/drivers/iommu/amd_iommu.c
>>> +++ b/drivers/iommu/amd_iommu.c
>>> @@ -352,6 +352,7 @@ static int init_iommu_group(struct device *dev)
>>>       struct iommu_dev_data *dev_data;
>>>       struct iommu_group *group;
>>>       struct pci_dev *dma_pdev;
>>> +    struct pci_bus *b = NULL;
>>>       int ret;
>>>
>>>       group = iommu_group_get(dev);
>>> @@ -388,7 +389,7 @@ static int init_iommu_group(struct device *dev)
>>>            * the alias.  Be careful to also test the parent device if
>>>            * we think the alias is the root of the group.
>>>            */
>>> -        bus = pci_find_bus(0, alias>>  8);
>>> +        b = bus = pci_get_bus(0, alias>>  8);
>>>           if (!bus)
>>>               goto use_group;
>>>
>>> @@ -408,6 +409,7 @@ static int init_iommu_group(struct device *dev)
>>>       dma_pdev = get_isolation_root(pci_dev_get(to_pci_dev(dev)));
>>>   use_pdev:
>>>       ret = use_pdev_iommu_group(dma_pdev, dev);
>>> +    pci_bus_put(b);
>>>       pci_dev_put(dma_pdev);
>>>       return ret;
>>>   use_group:
>>> diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
>>> index a7967ce..7162787 100644
>>> --- a/drivers/iommu/dmar.c
>>> +++ b/drivers/iommu/dmar.c
>>> @@ -67,12 +67,12 @@ static void __init dmar_register_drhd_unit(struct
>>> dmar_drhd_unit *drhd)
>>>   static int __init dmar_parse_one_dev_scope(struct
>>> acpi_dmar_device_scope *scope,
>>>                          struct pci_dev **dev, u16 segment)
>>>   {
>>> -    struct pci_bus *bus;
>>> +    struct pci_bus *b, *bus;
>>>       struct pci_dev *pdev = NULL;
>>>       struct acpi_dmar_pci_path *path;
>>>       int count;
>>>
>>> -    bus = pci_find_bus(segment, scope->bus);
>>> +    b = bus = pci_get_bus(segment, scope->bus);
>>>       path = (struct acpi_dmar_pci_path *)(scope + 1);
>>>       count = (scope->length - sizeof(struct acpi_dmar_device_scope))
>>>           / sizeof(struct acpi_dmar_pci_path);
>>> @@ -97,6 +97,8 @@ static int __init dmar_parse_one_dev_scope(struct
>>> acpi_dmar_device_scope *scope,
>>>           count --;
>>>           bus = pdev->subordinate;
>>>       }
>>> +    pci_bus_put(b);
>>> +
>>>       if (!pdev) {
>>>           pr_warn("Device scope device [%04x:%02x:%02x.%02x] not
>>> found\n",
>>>               segment, scope->bus, path->dev, path->fn);
>>> -- 
>>> 1.8.1.2
>>>
> 


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3, part2 01/20] PCI: introduce hotplug-safe PCI bus iterators
  2013-06-17 20:06   ` Bjorn Helgaas
  2013-06-18 16:23     ` Jiang Liu
@ 2013-06-20 16:18     ` Jiang Liu
  2013-06-26  2:58       ` Bjorn Helgaas
  1 sibling, 1 reply; 36+ messages in thread
From: Jiang Liu @ 2013-06-20 16:18 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu
  Cc: Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman, Gu Zheng,
	Toshi Kani, Myron Stowe, Yijing Wang, linux-pci, linux-kernel

On 06/18/2013 04:06 AM, Bjorn Helgaas wrote:
> On Sun, May 26, 2013 at 11:52:58PM +0800, Jiang Liu wrote:
>> Introduce hotplug-safe PCI bus iterators as below, which hold a
>> reference on the returned PCI bus object.
>> bool pci_bus_exists(int domain, int busnr);
>> struct pci_bus *pci_get_bus(int domain, int busnr);
>> struct pci_bus *pci_get_next_bus(struct pci_bus *from);
>> struct pci_bus *pci_get_next_root_bus(struct pci_bus *from);
>> #define for_each_pci_bus(b) for (b = NULL; (b = pci_get_next_bus(b)); )
>> #define for_each_pci_root_bus(b)  \
>> 		for (b = NULL; (b = pci_get_next_root_bus(b)); )
>>
>> The long-term goal is to remove hotplug-unsafe pci_find_bus(),
>> pci_find_next_bus() and the global pci_root_buses list.
> 
> I think you should mark the unsafe interfaces as __deprecated so
> users will get compile-time warnings.
> 
> I don't think pci_bus_exists() is a safe interface, because the value
> it returns may be incorrect before the caller can look at it.  The
> only safe thing would be to make it so we try to create the bus
> and return failure if it already exists.  Then the mutex can be in
> the code that creates the bus.
> 
> I don't see any uses of for_each_pci_bus(), so please remove that.
> 
> It sounds like we don't have a consensus on how to iterate over
> PCI root buses.  If you separate that from the pci_get_bus()
> changes, maybe we can at least move forward on the pci_get_bus()
> stuff.
Hi Bjorn and Yinghai,
    I have thought about the way to implement pci_for_each_root_bus()
again. And there are several possible ways here:
1) Yinghai has a patch set implementing an iterator for PCI host
bridges, but we can't safely refer the PCI root bus associated with a
host bridge device because the host bridge doesn't hold a reference to
associated PCI root bus. So we need to find a safe way to refer the PCI
root bus associated with a PCI host bridge.
2) Unexport pci_root_buses and convert it to klist, then we could walk
all root buses effectively. This solution is straight-forward, but it
may break out of tree drivers.
3) Keep current implementation, which does waste some computation cycles:(

So what's your thoughts about above solutions? Or any other suggestions?
Regards!
Gerry

> 
> Bjorn
> 
>> These new interfaces may be a littler slower than existing interfaces,
>> but it should be acceptable because they are not used on hot paths.
>>
>> Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
>> Acked-by: Yinghai Lu <yinghai@kernel.org>
>> Cc: linux-pci@vger.kernel.org
>> Cc: linux-kernel@vger.kernel.org
>> ---
>>  drivers/pci/pci.h    |   1 +
>>  drivers/pci/probe.c  |   2 +-
>>  drivers/pci/search.c | 159 +++++++++++++++++++++++++++++++++++++++++----------
>>  include/linux/pci.h  |  23 +++++++-
>>  4 files changed, 153 insertions(+), 32 deletions(-)
>>
>> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
>> index 68678ed..8fe15f6 100644
>> --- a/drivers/pci/pci.h
>> +++ b/drivers/pci/pci.h
>> @@ -126,6 +126,7 @@ static inline void pci_remove_legacy_files(struct pci_bus *bus) { return; }
>>  
>>  /* Lock for read/write access to pci device and bus lists */
>>  extern struct rw_semaphore pci_bus_sem;
>> +extern struct class pcibus_class;
>>  
>>  extern raw_spinlock_t pci_lock;
>>  
>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>> index 2830070..1004a05 100644
>> --- a/drivers/pci/probe.c
>> +++ b/drivers/pci/probe.c
>> @@ -93,7 +93,7 @@ static void release_pcibus_dev(struct device *dev)
>>  	kfree(pci_bus);
>>  }
>>  
>> -static struct class pcibus_class = {
>> +struct class pcibus_class = {
>>  	.name		= "pci_bus",
>>  	.dev_release	= &release_pcibus_dev,
>>  	.dev_attrs	= pcibus_dev_attrs,
>> diff --git a/drivers/pci/search.c b/drivers/pci/search.c
>> index d0627fa..16ccaf8 100644
>> --- a/drivers/pci/search.c
>> +++ b/drivers/pci/search.c
>> @@ -52,20 +52,27 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev)
>>  	return tmp;
>>  }
>>  
>> -static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
>> +struct pci_bus_match_arg {
>> +	int domain;
>> +	int bus;
>> +};
>> +
>> +static int pci_match_bus(struct device *dev, const void *data)
>>  {
>> -	struct pci_bus* child;
>> -	struct list_head *tmp;
>> +	struct pci_bus *bus = to_pci_bus(dev);
>> +	const struct pci_bus_match_arg *arg = data;
>>  
>> -	if(bus->number == busnr)
>> -		return bus;
>> +	return (pci_domain_nr(bus) == arg->domain && bus->number == arg->bus);
>> +}
>>  
>> -	list_for_each(tmp, &bus->children) {
>> -		child = pci_do_find_bus(pci_bus_b(tmp), busnr);
>> -		if(child)
>> -			return child;
>> -	}
>> -	return NULL;
>> +static int pci_match_next_bus(struct device *dev, const void *data)
>> +{
>> +	return 1;
>> +}
>> +
>> +static int pci_match_next_root_bus(struct device *dev, const void *data)
>> +{
>> +	return pci_is_root_bus(to_pci_bus(dev));
>>  }
>>  
>>  /**
>> @@ -76,20 +83,19 @@ static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
>>   * Given a PCI bus number and domain number, the desired PCI bus is located
>>   * in the global list of PCI buses.  If the bus is found, a pointer to its
>>   * data structure is returned.  If no bus is found, %NULL is returned.
>> + *
>> + * Note: it's not hotplug safe, the returned bus may be destroyed at any time.
>> + * Please use pci_get_bus() instead which holds a reference on the returned
>> + * PCI bus.
>>   */
>> -struct pci_bus * pci_find_bus(int domain, int busnr)
>> +struct pci_bus *pci_find_bus(int domain, int busnr)
>>  {
>> -	struct pci_bus *bus = NULL;
>> -	struct pci_bus *tmp_bus;
>> +	struct pci_bus *bus;
>>  
>> -	while ((bus = pci_find_next_bus(bus)) != NULL)  {
>> -		if (pci_domain_nr(bus) != domain)
>> -			continue;
>> -		tmp_bus = pci_do_find_bus(bus, busnr);
>> -		if (tmp_bus)
>> -			return tmp_bus;
>> -	}
>> -	return NULL;
>> +	bus = pci_get_bus(domain, busnr);
>> +	pci_bus_put(bus);
>> +
>> +	return bus;
>>  }
>>  
>>  /**
>> @@ -100,21 +106,114 @@ struct pci_bus * pci_find_bus(int domain, int busnr)
>>   * initiated by passing %NULL as the @from argument.  Otherwise if
>>   * @from is not %NULL, searches continue from next device on the
>>   * global list.
>> + *
>> + * Note: it's not hotplug safe, the returned bus may be destroyed at any time.
>> + * Please use pci_get_next_root_bus() instead which holds a reference
>> + * on the returned PCI root bus.
>>   */
>>  struct pci_bus * 
>>  pci_find_next_bus(const struct pci_bus *from)
>>  {
>> -	struct list_head *n;
>> -	struct pci_bus *b = NULL;
>> +	struct device *dev = from ? (struct device *)&from->dev : NULL;
>> +
>> +	dev = class_find_device(&pcibus_class, dev, NULL,
>> +				&pci_match_next_root_bus);
>> +	if (dev) {
>> +		put_device(dev);
>> +		return to_pci_bus(dev);
>> +	}
>> +
>> +	return NULL;
>> +}
>> +
>> +bool pci_bus_exists(int domain, int busnr)
>> +{
>> +	struct device *dev;
>> +	struct pci_bus_match_arg arg = { domain, busnr };
>>  
>>  	WARN_ON(in_interrupt());
>> -	down_read(&pci_bus_sem);
>> -	n = from ? from->node.next : pci_root_buses.next;
>> -	if (n != &pci_root_buses)
>> -		b = pci_bus_b(n);
>> -	up_read(&pci_bus_sem);
>> -	return b;
>> +	dev = class_find_device(&pcibus_class, NULL, &arg, &pci_match_bus);
>> +	if (dev)
>> +		put_device(dev);
>> +
>> +	return dev != NULL;
>> +}
>> +EXPORT_SYMBOL(pci_bus_exists);
>> +
>> +/**
>> + * pci_get_bus - locate PCI bus from a given domain and bus number
>> + * @domain: number of PCI domain to search
>> + * @busnr: number of desired PCI bus
>> + *
>> + * Given a PCI bus number and domain number, the desired PCI bus is located.
>> + * If the bus is found, a pointer to its data structure is returned.
>> + * If no bus is found, %NULL is returned.
>> + * Caller needs to release the returned bus by calling pci_bus_put().
>> + */
>> +struct pci_bus *pci_get_bus(int domain, int busnr)
>> +{
>> +	struct device *dev;
>> +	struct pci_bus_match_arg arg = { domain, busnr };
>> +
>> +	WARN_ON(in_interrupt());
>> +	dev = class_find_device(&pcibus_class, NULL, &arg, &pci_match_bus);
>> +	if (dev)
>> +		return to_pci_bus(dev);
>> +
>> +	return NULL;
>> +}
>> +EXPORT_SYMBOL(pci_get_bus);
>> +
>> +/**
>> + * pci_get_next_bus - begin or continue searching for a PCI bus
>> + * @from: Previous PCI bus found, or %NULL for new search.
>> + *
>> + * Iterates through the list of known PCI busses. If a PCI bus is found,
>> + * the reference count to the bus is incremented and a pointer to it is
>> + * returned. Otherwise, %NULL is returned. A new search is initiated by
>> + * passing %NULL as the @from argument. Otherwise if @from is not %NULL,
>> + * searches continue from next bus on the global list. The reference count
>> + * for @from is always decremented if it is not %NULL.
>> + */
>> +struct pci_bus *pci_get_next_bus(struct pci_bus *from)
>> +{
>> +	struct device *dev = from ? &from->dev : NULL;
>> +
>> +	WARN_ON(in_interrupt());
>> +	dev = class_find_device(&pcibus_class, dev, NULL, &pci_match_next_bus);
>> +	pci_bus_put(from);
>> +	if (dev)
>> +		return to_pci_bus(dev);
>> +
>> +	return NULL;
>> +}
>> +EXPORT_SYMBOL(pci_get_next_bus);
>> +
>> +/**
>> + * pci_find_next_root_bus - begin or continue searching for a PCI root bus
>> + * @from: Previous PCI bus found, or %NULL for new search.
>> + *
>> + * Iterates through the list of known PCI root busses. If a PCI bus is found,
>> + * the reference count to the root bus is incremented and a pointer to it is
>> + * returned. Otherwise, %NULL is returned. A new search is initiated by
>> + * passing %NULL as the @from argument. Otherwise if @from is not %NULL,
>> + * searches continue from next root bus on the global list. The reference
>> + * count for @from is always decremented if it is not %NULL.
>> + */
>> +struct pci_bus *pci_get_next_root_bus(struct pci_bus *from)
>> +{
>> +	struct device *dev = from ? &from->dev : NULL;
>> +
>> +	WARN_ON(in_interrupt());
>> +	dev = class_find_device(&pcibus_class, dev, NULL,
>> +				&pci_match_next_root_bus);
>> +	pci_bus_put(from);
>> +	if (dev)
>> +		return to_pci_bus(dev);
>> +
>> +	return NULL;
>>  }
>> +EXPORT_SYMBOL(pci_get_next_root_bus);
>>  
>>  /**
>>   * pci_get_slot - locate PCI device for a given PCI slot
>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>> index 7b23fa0..1e43423 100644
>> --- a/include/linux/pci.h
>> +++ b/include/linux/pci.h
>> @@ -454,6 +454,9 @@ struct pci_bus {
>>  
>>  #define pci_bus_b(n)	list_entry(n, struct pci_bus, node)
>>  #define to_pci_bus(n)	container_of(n, struct pci_bus, dev)
>> +#define for_each_pci_bus(b)	for (b = NULL; (b = pci_get_next_bus(b)); )
>> +#define for_each_pci_root_bus(b) \
>> +			for (b = NULL; (b = pci_get_next_root_bus(b)); )
>>  
>>  /*
>>   * Returns true if the pci bus is root (behind host-pci bridge),
>> @@ -718,7 +721,6 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
>>  void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
>>  			     struct pci_bus_region *region);
>>  void pcibios_scan_specific_bus(int busn);
>> -struct pci_bus *pci_find_bus(int domain, int busnr);
>>  void pci_bus_add_devices(const struct pci_bus *bus);
>>  struct pci_bus * __deprecated pci_scan_bus_parented(struct device *parent,
>>  			int bus, struct pci_ops *ops, void *sysdata);
>> @@ -778,8 +780,15 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap);
>>  int pci_find_next_ext_capability(struct pci_dev *dev, int pos, int cap);
>>  int pci_find_ht_capability(struct pci_dev *dev, int ht_cap);
>>  int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
>> +
>> +struct pci_bus *pci_find_bus(int domain, int busnr);
>>  struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
>>  
>> +bool pci_bus_exists(int domain, int busnr);
>> +struct pci_bus *pci_get_bus(int domain, int busnr);
>> +struct pci_bus *pci_get_next_bus(struct pci_bus *from);
>> +struct pci_bus *pci_get_next_root_bus(struct pci_bus *from);
>> +
>>  struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
>>  				struct pci_dev *from);
>>  struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
>> @@ -1430,6 +1439,18 @@ static inline void pci_unblock_cfg_access(struct pci_dev *dev)
>>  static inline struct pci_bus *pci_find_next_bus(const struct pci_bus *from)
>>  { return NULL; }
>>  
>> +static inline bool pci_bus_exists(int domain, int busnr)
>> +{ return false; }
>> +
>> +static inline struct pci_bus *pci_get_bus(int domain, int busnr)
>> +{ return NULL; }
>> +
>> +static inline struct pci_bus *pci_get_next_bus(struct pci_bus *from)
>> +{ return NULL; }
>> +
>> +static inline struct pci_bus *pci_get_next_root_bus(struct pci_bus *from)
>> +{ return NULL; }
>> +
>>  static inline struct pci_dev *pci_get_slot(struct pci_bus *bus,
>>  						unsigned int devfn)
>>  { return NULL; }
>> -- 
>> 1.8.1.2
>>


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3, part2 01/20] PCI: introduce hotplug-safe PCI bus iterators
  2013-06-20 16:18     ` Jiang Liu
@ 2013-06-26  2:58       ` Bjorn Helgaas
  0 siblings, 0 replies; 36+ messages in thread
From: Bjorn Helgaas @ 2013-06-26  2:58 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Yinghai Lu, Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman,
	Gu Zheng, Toshi Kani, Myron Stowe, Yijing Wang, linux-pci,
	linux-kernel

On Thu, Jun 20, 2013 at 10:18 AM, Jiang Liu <liuj97@gmail.com> wrote:
> On 06/18/2013 04:06 AM, Bjorn Helgaas wrote:
>> On Sun, May 26, 2013 at 11:52:58PM +0800, Jiang Liu wrote:
>>> Introduce hotplug-safe PCI bus iterators as below, which hold a
>>> reference on the returned PCI bus object.
>>> bool pci_bus_exists(int domain, int busnr);
>>> struct pci_bus *pci_get_bus(int domain, int busnr);
>>> struct pci_bus *pci_get_next_bus(struct pci_bus *from);
>>> struct pci_bus *pci_get_next_root_bus(struct pci_bus *from);
>>> #define for_each_pci_bus(b) for (b = NULL; (b = pci_get_next_bus(b)); )
>>> #define for_each_pci_root_bus(b)  \
>>>              for (b = NULL; (b = pci_get_next_root_bus(b)); )
>>>
>>> The long-term goal is to remove hotplug-unsafe pci_find_bus(),
>>> pci_find_next_bus() and the global pci_root_buses list.
>>
>> I think you should mark the unsafe interfaces as __deprecated so
>> users will get compile-time warnings.
>>
>> I don't think pci_bus_exists() is a safe interface, because the value
>> it returns may be incorrect before the caller can look at it.  The
>> only safe thing would be to make it so we try to create the bus
>> and return failure if it already exists.  Then the mutex can be in
>> the code that creates the bus.
>>
>> I don't see any uses of for_each_pci_bus(), so please remove that.
>>
>> It sounds like we don't have a consensus on how to iterate over
>> PCI root buses.  If you separate that from the pci_get_bus()
>> changes, maybe we can at least move forward on the pci_get_bus()
>> stuff.
> Hi Bjorn and Yinghai,
>     I have thought about the way to implement pci_for_each_root_bus()
> again. And there are several possible ways here:
> 1) Yinghai has a patch set implementing an iterator for PCI host
> bridges, but we can't safely refer the PCI root bus associated with a
> host bridge device because the host bridge doesn't hold a reference to
> associated PCI root bus. So we need to find a safe way to refer the PCI
> root bus associated with a PCI host bridge.
> 2) Unexport pci_root_buses and convert it to klist, then we could walk
> all root buses effectively. This solution is straight-forward, but it
> may break out of tree drivers.
> 3) Keep current implementation, which does waste some computation cycles:(
>
> So what's your thoughts about above solutions? Or any other suggestions?
> Regards!
> Gerry

Iteration is generally the wrong approach because it doesn't fit well
with hot plug.  I recognize that it may be impossible to fix all the
places that currently iterate over root buses, so we may have to
accept iteration at least in the short term.

Sometimes when we fix the things we *know* how to fix, it makes it
easier to see how to fix the hard problem.  Your pci_bus ref counting
fixes seem like a clear step forward, and I'd like to get them in
ASAP, even if the root bus iteration isn't figured out yet.

So my advice is, let's do the simple stuff we know how to do now, then
worry about the harder stuff later.

Bjorn

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3, part2 15/20] PCI, EDAC: use hotplug-safe PCI bus iterators to walk PCI buses
  2013-06-18 16:33     ` Jiang Liu
@ 2013-06-26  3:00       ` Bjorn Helgaas
  0 siblings, 0 replies; 36+ messages in thread
From: Bjorn Helgaas @ 2013-06-26  3:00 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Yinghai Lu, Jiang Liu, Rafael J . Wysocki, Greg Kroah-Hartman,
	Gu Zheng, Toshi Kani, Myron Stowe, Yijing Wang, linux-pci,
	linux-kernel, Mauro Carvalho Chehab, Doug Thompson, linux-edac

On Tue, Jun 18, 2013 at 10:33 AM, Jiang Liu <liuj97@gmail.com> wrote:
> On 06/18/2013 04:18 AM, Bjorn Helgaas wrote:
>> On Sun, May 26, 2013 at 11:53:12PM +0800, Jiang Liu wrote:
>>> Enhance EDAC drviers to use hotplug-safe iterators to walk PCI buses.
>>>
>>> Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
>>> Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
>>> Cc: Doug Thompson <dougthompson@xmission.com> r
>>> Cc: linux-edac@vger.kernel.org
>>> Cc: linux-kernel@vger.kernel.org
>>> ---
>>>  drivers/edac/i7core_edac.c | 2 +-
>>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
>>> index 0ec3e95..7146e10 100644
>>> --- a/drivers/edac/i7core_edac.c
>>> +++ b/drivers/edac/i7core_edac.c
>>> @@ -1296,7 +1296,7 @@ static unsigned i7core_pci_lastbus(void)
>>>      int last_bus = 0, bus;
>>>      struct pci_bus *b = NULL;
>>>
>>> -    while ((b = pci_find_next_bus(b)) != NULL) {
>>> +    for_each_pci_root_bus(b) {
>>
>> This doesn't look equivalent.  Previously, we iterated over all PCI
>> buses, so we returned the highest bus number seen anywhere.  Now we
>> only look at root buses, so we return the highest bus number of any
>> root bus.  But if that root bus has a bridge on it, obviously the
>> bus on the other side has a higher number.
> Hi Bjorn,
>         I think the name pci_find_next_bus() is misleading, it should be named
> pci_find_next_root_bus() actually because it returns next root bus indeed.

Oh, you forgot to mention that critical bit of information!  That
should be in the changelog of every patch that changes a call to
pci_find_next_bus().

Bjorn

^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2013-06-26  3:01 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-26 15:52 [PATCH v3, part2 00/20] Introduce hotplug-safe PCI bus iterators Jiang Liu
2013-05-26 15:52 ` [PATCH v3, part2 01/20] PCI: introduce " Jiang Liu
2013-05-28  4:22   ` Yinghai Lu
2013-05-28 15:06     ` Liu Jiang
2013-06-17 20:06   ` Bjorn Helgaas
2013-06-18 16:23     ` Jiang Liu
2013-06-20 16:18     ` Jiang Liu
2013-06-26  2:58       ` Bjorn Helgaas
2013-05-26 15:52 ` [PATCH v3, part2 02/20] PCI, core: use hotplug-safe iterators to walk PCI buses Jiang Liu
2013-05-26 15:53 ` [PATCH v3, part2 03/20] PCI, hotplug: " Jiang Liu
2013-05-26 15:53 ` [PATCH v3, part2 04/20] PCI, IOV: hold a reference to PCI bus when creating virtual PCI devices Jiang Liu
2013-05-26 15:53 ` [PATCH v3, part2 05/20] PCI, Alpha: use hotplug-safe iterators to walk PCI buses Jiang Liu
2013-05-26 15:53 ` [PATCH v3, part2 06/20] PCI, FRV: " Jiang Liu
2013-05-26 15:53 ` [PATCH v3, part2 07/20] PCI, IA64: " Jiang Liu
2013-05-26 15:53 ` [PATCH v3, part2 08/20] PCI, Microblaze: " Jiang Liu
2013-05-26 15:53 ` [PATCH v3, part2 09/20] PCI, mn10300: " Jiang Liu
2013-05-26 15:53 ` [PATCH v3, part2 10/20] PCI, PPC: " Jiang Liu
2013-05-26 15:53 ` [PATCH v3, part2 11/20] PCI, SPARC: " Jiang Liu
2013-05-26 17:11   ` David Miller
2013-05-26 15:53 ` [PATCH v3, part2 12/20] PCI, x86: " Jiang Liu
2013-05-26 15:53 ` [PATCH v3, part2 13/20] PCI, ACPI: " Jiang Liu
2013-05-26 15:53 ` [PATCH v3, part2 14/20] PCI, DRM: " Jiang Liu
2013-06-17 18:08   ` Bjorn Helgaas
2013-05-26 15:53 ` [PATCH v3, part2 15/20] PCI, EDAC: use hotplug-safe PCI bus " Jiang Liu
2013-06-17 20:18   ` Bjorn Helgaas
2013-06-18 16:33     ` Jiang Liu
2013-06-26  3:00       ` Bjorn Helgaas
2013-05-26 15:53 ` [PATCH v3, part2 16/20] PCI, via-camera: use hotplug-safe " Jiang Liu
2013-05-26 15:53 ` [PATCH v3, part2 17/20] PCI, iommu: " Jiang Liu
2013-06-17 20:20   ` Bjorn Helgaas
2013-06-17 20:34     ` Don Dutile
2013-06-18 16:34       ` Jiang Liu
2013-05-26 15:53 ` [PATCH v3, part2 18/20] PCI, eeepc-laptop: " Jiang Liu
2013-05-26 15:53 ` [PATCH v3, part2 19/20] PCI, asus-wmi: " Jiang Liu
2013-05-26 15:53 ` [PATCH v3, part2 20/20] PCI, ARM: use hotplug-safe PCI bus " Jiang Liu
2013-06-17 18:24   ` Bjorn Helgaas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).