[RFC PATCH 00/16] Refine PCI host bridge scan interfaces

STALE4353d

65 messages, 6 authors, 2014-11-21 · open the first message on its own page

[RFC PATCH 00/16] Refine PCI host bridge scan interfaces

From: Yijing Wang <hidden>
Date: 2014-11-17 09:41:05

This series is based Linux 3.18-rc1 and Lorenzo Pieralisi's
arm PCI domain cleanup patches, link: 
https://patchwork.ozlabs.org/patch/407585/

Current pci scan interfaces like pci_scan_root_bus() and directly
call pci_create_root_bus()/pci_scan_child_bus() lack flexiblity.
Some platform infos like PCI domain and msi_chip have to be
associated to PCI bus by some arch specific function.
We want to make a generic pci_host_bridge, and make it hold
the platform infos or hook. Then we could eliminate the lots
of arch pci_domain_nr, also we could associate some platform 
ops something like pci_get_msi_chip(struct pci_dev *dev)
with pci_host_bridge to avoid introduce arch weak functions.

This RFC version not for all platforms, just applied the new
scan interface in x86/arm/powerpc/ia64, I will refresh other
platforms after the core pci scan interfaces are ok.

Only test in x86.

Thanks!
Yijing.

Yijing Wang (16):
  PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources
  PCI: Use pci_scan_root_bus() instead of pci_scan_bus()
  PCI: Clean up pci_scan_bus()
  PCI: Rip out pci_bus_add_devices() from pci_scan_root_bus()
  PCI: Use pci_scan_root_bus() instead of pci_scan_bus_parented()
  PCI: Use u32 type to combine PCI domain and bus number
  PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
  PCI: Introduce pci_scan_host_bridge() and pci_host_info
  PCI: Associate .get_msi_ctrl() with pci_host_bridge
  PCI: Add of_scan_bus() to pci_host_info
  x86/PCI: Use pci_scan_host_bridge() instead of pci_create_root_bus()
  ia64/PCI: Remove the redundant bus variable
  ia64/PCI: Use pci_scan_host_bridge() to refactor pci_acpi_scan_root()
  arm/PCI: Introduce pci_get_domain_nr()
  arm/PCI: Use pci_scan_host_bridge() instead of pci_scan_root_bus()
  powerpc/PCI: Use pci_scan_host_bridge() to scan PCI bus

 arch/alpha/include/asm/pci.h      |    2 +-
 arch/alpha/kernel/pci.c           |    1 +
 arch/alpha/kernel/sys_nautilus.c  |    3 +-
 arch/arm/include/asm/mach/pci.h   |   10 ++
 arch/arm/kernel/bios32.c          |   60 +++++++----
 arch/cris/include/asm/pci.h       |    2 +-
 arch/frv/mb93090-mb00/pci-vdk.c   |    8 +-
 arch/ia64/include/asm/pci.h       |    2 +-
 arch/ia64/pci/pci.c               |   85 +++++++--------
 arch/ia64/sn/kernel/io_init.c     |    2 +
 arch/m68k/coldfire/pci.c          |    3 +-
 arch/microblaze/pci/pci-common.c  |    2 +-
 arch/mips/include/asm/pci.h       |    2 +-
 arch/mips/pci/pci.c               |    1 +
 arch/mn10300/include/asm/pci.h    |    2 +-
 arch/mn10300/unit-asb2305/pci.c   |    7 +-
 arch/powerpc/kernel/pci-common.c  |   81 ++++++++------
 arch/s390/pci/pci.c               |    2 +-
 arch/sh/drivers/pci/pci.c         |    1 +
 arch/sh/include/asm/pci.h         |    2 +-
 arch/sparc/include/asm/pci_32.h   |    2 +-
 arch/sparc/include/asm/pci_64.h   |    2 +-
 arch/sparc/kernel/leon_pci.c      |    1 +
 arch/sparc/kernel/pcic.c          |    5 +-
 arch/tile/kernel/pci.c            |    3 +-
 arch/tile/kernel/pci_gx.c         |    3 +-
 arch/unicore32/kernel/pci.c       |    4 +-
 arch/x86/include/asm/pci.h        |    2 +-
 arch/x86/pci/acpi.c               |   65 +++++++-----
 arch/x86/pci/amd_bus.c            |    2 +-
 arch/x86/pci/common.c             |   27 ++++--
 arch/xtensa/include/asm/pci.h     |    2 +-
 arch/xtensa/kernel/pci.c          |    1 +
 drivers/parisc/dino.c             |    4 +-
 drivers/pci/host-bridge.c         |  104 ++++++++++++++++++
 drivers/pci/host/pci-xgene.c      |    2 +-
 drivers/pci/hotplug/ibmphp_core.c |    6 +-
 drivers/pci/probe.c               |  214 +++++++++++++++++++------------------
 drivers/pci/xen-pcifront.c        |    6 +-
 include/linux/pci.h               |   41 ++++++-
 include/uapi/linux/pci.h          |    3 +
 41 files changed, 497 insertions(+), 280 deletions(-)

[RFC PATCH 10/16] PCI: Add of_scan_bus() to pci_host_info

From: Yijing Wang <hidden>
Date: 2014-11-17 09:40:55

Add of_scan_bus() to support some platforms
scan bus by of_node.

Signed-off-by: Yijing Wang <redacted>
---
 drivers/pci/host-bridge.c |    1 +
 drivers/pci/probe.c       |   10 +++++++---
 include/linux/pci.h       |    3 +++
 3 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 872cae1..1a1f81b 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -52,6 +52,7 @@ struct pci_host_bridge *pci_create_host_bridge(
 		return NULL;
 
 	host->sysdata = info->arg;
+	host->node = info->node;
 	host->busnum = PCI_BUSNUM(db);
 	host->domain = PCI_DOMAIN(db);
 	host->ops = ops;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 42158fd..2729c41 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2126,9 +2126,13 @@ struct pci_host_bridge *pci_scan_host_bridge(
 		pci_bus_insert_busn_res(host->bus, host->busnum, 255);
 	}
 
-	max = pci_scan_child_bus(host->bus);
-	if (!found)
-		pci_bus_update_busn_res_end(host->bus, max);
+	if (info->of_scan_bus) {
+		info->of_scan_bus(host);
+	} else {
+		max = pci_scan_child_bus(host->bus);
+		if (!found)
+			pci_bus_update_busn_res_end(host->bus, max);
+	}
 
 	return host;
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index af1ee86..c4f4438 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -407,6 +407,7 @@ struct pci_host_bridge {
 	int busnum;
 	int domain;
 	void *sysdata;
+	struct device_node *node;
 	struct pci_ops *ops;
 	struct msi_controller *(*get_msi_ctrl)(struct pci_dev *pdev);
 	void (*release_fn)(struct pci_host_bridge *);
@@ -416,10 +417,12 @@ struct pci_host_bridge {
 struct pci_host_info {
 	u8 res_type;
 	void *arg;
+	struct device_node *node;
 	struct list_head *resources; /*just for build, will clean up later */
 	struct msi_controller *(*get_msi_ctrl)(struct pci_dev *pdev);
 	int (*init_res)(struct pci_host_bridge *host, 
 			struct pci_host_info *info);
+	void (*of_scan_bus)(struct pci_host_bridge *host);
 };
 
 static inline void init_pci_host_info(struct pci_host_info *info)
-- 
1.7.1

[RFC PATCH 09/16] PCI: Associate .get_msi_ctrl() with pci_host_bridge

From: Yijing Wang <hidden>
Date: 2014-11-17 09:40:58

From: Yijing Wang <redacted>

Signed-off-by: Yijing Wang <redacted>
---
 drivers/pci/host-bridge.c |    1 +
 include/linux/pci.h       |    2 ++
 2 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 49b6c21..872cae1 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -58,6 +58,7 @@ struct pci_host_bridge *pci_create_host_bridge(
 	host->dev.parent = parent;
 	INIT_LIST_HEAD(&host->windows);
 	host->dev.release = pci_release_host_bridge_dev;
+	host->get_msi_ctrl = info->get_msi_ctrl;
 
 	/* this is hack, just for build, will be removed later*/
 	b = kzalloc(sizeof(*b), GFP_KERNEL);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index a51f5f5..af1ee86 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -408,6 +408,7 @@ struct pci_host_bridge {
 	int domain;
 	void *sysdata;
 	struct pci_ops *ops;
+	struct msi_controller *(*get_msi_ctrl)(struct pci_dev *pdev);
 	void (*release_fn)(struct pci_host_bridge *);
 	void *release_data;
 };
@@ -416,6 +417,7 @@ struct pci_host_info {
 	u8 res_type;
 	void *arg;
 	struct list_head *resources; /*just for build, will clean up later */
+	struct msi_controller *(*get_msi_ctrl)(struct pci_dev *pdev);
 	int (*init_res)(struct pci_host_bridge *host, 
 			struct pci_host_info *info);
 };
-- 
1.7.1

[RFC PATCH 03/16] PCI: Clean up pci_scan_bus()

From: Yijing Wang <hidden>
Date: 2014-11-17 09:40:59

No one uses it, clean up.

Signed-off-by: Yijing Wang <redacted>
---
 drivers/pci/probe.c |   20 --------------------
 include/linux/pci.h |    1 -
 2 files changed, 0 insertions(+), 21 deletions(-)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index fc99e88..0a02fc2 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2125,26 +2125,6 @@ struct pci_bus *pci_scan_bus_parented(struct device *parent,
 }
 EXPORT_SYMBOL(pci_scan_bus_parented);
 
-struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops,
-					void *sysdata)
-{
-	LIST_HEAD(resources);
-	struct pci_bus *b;
-
-	pci_add_resource(&resources, &ioport_resource);
-	pci_add_resource(&resources, &iomem_resource);
-	pci_add_resource(&resources, &busn_resource);
-	b = pci_create_root_bus(NULL, bus, ops, sysdata, &resources);
-	if (b) {
-		pci_scan_child_bus(b);
-		pci_bus_add_devices(b);
-	} else {
-		pci_free_resource_list(&resources);
-	}
-	return b;
-}
-EXPORT_SYMBOL(pci_scan_bus);
-
 /**
  * pci_rescan_bus_bridge_resize - scan a PCI bus for devices.
  * @bridge: PCI bridge for the bus to scan
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 5be8db4..f8045d6 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -769,7 +769,6 @@ struct pci_bus *pci_find_bus(int domain, int busnr);
 void pci_bus_add_devices(const struct pci_bus *bus);
 struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus,
 				      struct pci_ops *ops, void *sysdata);
-struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata);
 struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 				    struct pci_ops *ops, void *sysdata,
 				    struct list_head *resources);
-- 
1.7.1

[RFC PATCH 12/16] ia64/PCI: Remove the redundant bus variable

From: Yijing Wang <hidden>
Date: 2014-11-17 09:41:02

Signed-off-by: Yijing Wang <redacted>
---
 arch/ia64/pci/pci.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 291a582..aac3220 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -424,7 +424,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 {
 	struct acpi_device *device = root->device;
 	int domain = root->segment;
-	int bus = root->secondary.start;
 	struct pci_controller *controller;
 	struct pci_root_info *info = NULL;
 	int busnum = root->secondary.start;
@@ -465,7 +464,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 	 * should handle the case here, but it appears that IA64 hasn't
 	 * such quirk. So we just ignore the case now.
 	 */
-	pbus = pci_create_root_bus(NULL, bus, &pci_root_ops, controller,
+	pbus = pci_create_root_bus(NULL, busnum, &pci_root_ops, controller,
 				   &info->resources);
 	if (!pbus) {
 		pci_free_resource_list(&info->resources);
-- 
1.7.1

[RFC PATCH 05/16] PCI: Use pci_scan_root_bus() instead of pci_scan_bus_parented()

From: Yijing Wang <hidden>
Date: 2014-11-17 09:41:03

Now we can remove the deprecated pci_scan_bus_parented(),
and use pci_scan_root_bus() instead.

Signed-off-by: Yijing Wang <redacted>
---
 drivers/pci/probe.c        |   19 -------------------
 drivers/pci/xen-pcifront.c |    6 +++---
 include/linux/pci.h        |    2 --
 3 files changed, 3 insertions(+), 24 deletions(-)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 97711f3..623bfff 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2105,25 +2105,6 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
 }
 EXPORT_SYMBOL(pci_scan_root_bus);
 
-/* Deprecated; use pci_scan_root_bus() instead */
-struct pci_bus *pci_scan_bus_parented(struct device *parent,
-		int bus, struct pci_ops *ops, void *sysdata)
-{
-	LIST_HEAD(resources);
-	struct pci_bus *b;
-
-	pci_add_resource(&resources, &ioport_resource);
-	pci_add_resource(&resources, &iomem_resource);
-	pci_add_resource(&resources, &busn_resource);
-	b = pci_create_root_bus(parent, bus, ops, sysdata, &resources);
-	if (b)
-		pci_scan_child_bus(b);
-	else
-		pci_free_resource_list(&resources);
-	return b;
-}
-EXPORT_SYMBOL(pci_scan_bus_parented);
-
 /**
  * pci_rescan_bus_bridge_resize - scan a PCI bus for devices.
  * @bridge: PCI bridge for the bus to scan
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index 116ca37..fa2e312 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -474,8 +474,8 @@ static int pcifront_scan_root(struct pcifront_device *pdev,
 
 	pci_lock_rescan_remove();
 
-	b = pci_scan_bus_parented(&pdev->xdev->dev, bus,
-				  &pcifront_bus_ops, sd);
+	b = pci_scan_root_bus(&pdev->xdev->dev, bus,
+				  &pcifront_bus_ops, sd, NULL);
 	if (!b) {
 		dev_err(&pdev->xdev->dev,
 			"Error creating PCI Frontend Bus!\n");
@@ -488,7 +488,7 @@ static int pcifront_scan_root(struct pcifront_device *pdev,
 
 	list_add(&bus_entry->list, &pdev->root_buses);
 
-	/* pci_scan_bus_parented skips devices which do not have a have
+	/* pci_scan_root_bus skips devices which do not have a have
 	* devfn==0. The pcifront_scan_bus enumerates all devfn. */
 	err = pcifront_scan_bus(pdev, domain, bus, b);
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index f8045d6..4daef65 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -767,8 +767,6 @@ void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res,
 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 *pci_scan_bus_parented(struct device *parent, int bus,
-				      struct pci_ops *ops, void *sysdata);
 struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 				    struct pci_ops *ops, void *sysdata,
 				    struct list_head *resources);
-- 
1.7.1

[RFC PATCH 13/16] ia64/PCI: Use pci_scan_host_bridge() to refactor pci_acpi_scan_root()

From: Yijing Wang <hidden>
Date: 2014-11-17 09:42:10

Signed-off-by: Yijing Wang <redacted>
---
 arch/ia64/pci/pci.c |   84 +++++++++++++++++++++++---------------------------
 1 files changed, 39 insertions(+), 45 deletions(-)
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index aac3220..c7d97ae 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -115,23 +115,10 @@ struct pci_ops pci_root_ops = {
 	.write = pci_write,
 };
 
-/* Called by ACPI when it finds a new root bus.  */
-
-static struct pci_controller *alloc_pci_controller(int seg)
-{
-	struct pci_controller *controller;
-
-	controller = kzalloc(sizeof(*controller), GFP_KERNEL);
-	if (!controller)
-		return NULL;
-
-	controller->segment = seg;
-	return controller;
-}
-
 struct pci_root_info {
 	struct acpi_device *bridge;
-	struct pci_controller *controller;
+	struct pci_controller controller;
+	struct acpi_pci_root *root;
 	struct list_head resources;
 	struct resource *res;
 	resource_size_t *res_offset;
@@ -340,8 +327,6 @@ static void free_pci_root_info_res(struct pci_root_info *info)
 	kfree(info->res_offset);
 	info->res_offset = NULL;
 	info->res_num = 0;
-	kfree(info->controller);
-	info->controller = NULL;
 }
 
 static void __release_pci_root_info(struct pci_root_info *info)
@@ -395,7 +380,7 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
 	if (info->res_num) {
 		info->res =
 			kzalloc_node(sizeof(*info->res) * info->res_num,
-				     GFP_KERNEL, info->controller->node);
+				     GFP_KERNEL, info->controller.node);
 		if (!info->res) {
 			kfree(name);
 			return -ENOMEM;
@@ -403,7 +388,7 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
 
 		info->res_offset =
 			kzalloc_node(sizeof(*info->res_offset) * info->res_num,
-					GFP_KERNEL, info->controller->node);
+					GFP_KERNEL, info->controller.node);
 		if (!info->res_offset) {
 			kfree(name);
 			kfree(info->res);
@@ -420,6 +405,27 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
 	return 0;
 }
 
+static int pci_acpi_init_res(struct pci_host_bridge *host,
+		struct pci_host_info *info)
+{
+	int ret;
+	struct pci_host_bridge_window *window, *n;
+	struct pci_controller *ctrl = info->arg;
+	struct pci_root_info *arg = container_of(ctrl,
+			struct pci_root_info, controller);
+
+	ret = probe_pci_root_info(arg, arg->root->device, 
+			host->busnum, host->domain);
+	if (ret) 
+		return -1;
+	list_for_each_entry_safe(window, n, &arg->resources,
+			list)
+		list_move_tail(&window->list, &host->windows);
+	/* insert busn resource at first */
+	pci_add_resource(&host->windows, &arg->root->secondary);
+	return 0;
+}
+
 struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 {
 	struct acpi_device *device = root->device;
@@ -427,55 +433,43 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 	struct pci_controller *controller;
 	struct pci_root_info *info = NULL;
 	int busnum = root->secondary.start;
-	struct pci_bus *pbus;
-	int ret;
-
-	controller = alloc_pci_controller(domain);
-	if (!controller)
-		return NULL;
-
-	controller->companion = device;
-	controller->node = acpi_get_node(device->handle);
+	struct pci_host_bridge *host;
+	struct pci_host_info arg;
 
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (!info) {
 		dev_err(&device->dev,
 				"pci_bus %04x:%02x: ignored (out of memory)\n",
 				domain, busnum);
-		kfree(controller);
 		return NULL;
 	}
 
-	info->controller = controller;
+	controller = &info->controller;
+	controller->segment = domain;
+	controller->companion = device;
+	controller->node = acpi_get_node(device->handle);
 	INIT_LIST_HEAD(&info->io_resources);
 	INIT_LIST_HEAD(&info->resources);
+	init_pci_host_info(&arg);
+	arg.arg = controller;
+	arg.init_res = pci_acpi_init_res;
 
-	ret = probe_pci_root_info(info, device, busnum, domain);
-	if (ret) {
-		kfree(info->controller);
-		kfree(info);
-		return NULL;
-	}
-	/* insert busn resource at first */
-	pci_add_resource(&info->resources, &root->secondary);
 	/*
 	 * See arch/x86/pci/acpi.c.
 	 * The desired pci bus might already be scanned in a quirk. We
 	 * should handle the case here, but it appears that IA64 hasn't
 	 * such quirk. So we just ignore the case now.
 	 */
-	pbus = pci_create_root_bus(NULL, busnum, &pci_root_ops, controller,
-				   &info->resources);
-	if (!pbus) {
-		pci_free_resource_list(&info->resources);
+	host = pci_scan_host_bridge(NULL, PCI_DOMBUS(domain, busnum), 
+			&pci_root_ops, &arg);
+	if (!host) {
 		__release_pci_root_info(info);
 		return NULL;
 	}
 
-	pci_set_host_bridge_release(to_pci_host_bridge(pbus->bridge),
+	pci_set_host_bridge_release(host,
 			release_pci_root_info, info);
-	pci_scan_child_bus(pbus);
-	return pbus;
+	return host->bus;
 }
 
 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
-- 
1.7.1

[RFC PATCH 14/16] arm/PCI: Introduce pci_get_domain_nr()

From: Yijing Wang <hidden>
Date: 2014-11-17 09:42:12

Signed-off-by: Yijing Wang <redacted>
---
 arch/arm/include/asm/mach/pci.h |    9 +++++++++
 arch/arm/kernel/bios32.c        |    8 ++++++--
 2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h
index f19f627..370b3bd 100644
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -90,6 +90,15 @@ extern void pci_map_io_early(unsigned long pfn);
 static inline void pci_map_io_early(unsigned long pfn) {}
 #endif
 
+#ifdef CONFIG_PCI_DOMAINS_GENERIC
+int pci_get_domain_nr(struct device *parent)
+#else
+static inline int pci_get_domain_nr(struct device *parent)
+{
+	return 0;
+}
+#endif
+
 /*
  * PCI controllers
  */
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index d8c2b4e..3fe56f1 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -513,7 +513,7 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
 #ifdef CONFIG_PCI_DOMAINS_GENERIC
 static bool dt_domain_found;
 
-void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
+int pci_get_domain_nr(struct device *parent)
 {
 	int domain = of_get_pci_domain_nr(parent->of_node);
 
@@ -526,8 +526,12 @@ void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
 	} else {
 		domain = pci_get_new_domain_nr();
 	}
+	return domain;
+}
 
-	bus->domain_nr = domain;
+void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
+{
+	bus->domain_nr = pci_get_domain_nr(parent);
 }
 #endif
 
-- 
1.7.1

[RFC PATCH 15/16] arm/PCI: Use pci_scan_host_bridge() instead of pci_scan_root_bus()

From: Yijing Wang <hidden>
Date: 2014-11-17 09:42:13

Signed-off-by: Yijing Wang <redacted>
---
 arch/arm/include/asm/mach/pci.h |    1 +
 arch/arm/kernel/bios32.c        |   52 +++++++++++++++++++++++---------------
 2 files changed, 32 insertions(+), 21 deletions(-)
diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h
index 370b3bd..a26eb3a 100644
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -46,6 +46,7 @@ struct hw_pci {
 struct pci_sys_data {
 	struct list_head node;
 	int		busnr;		/* primary bus number			*/
+	u8		nr;
 	u64		mem_offset;	/* bus->cpu memory mapping offset	*/
 	unsigned long	io_offset;	/* bus->cpu IO mapping offset		*/
 	struct pci_bus	*bus;		/* PCI bus				*/
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 3fe56f1..535d7ec 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -426,33 +426,41 @@ static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 	return irq;
 }
 
-static int pcibios_init_resources(int busnr, struct pci_sys_data *sys)
+static int pcibios_init_resources(struct pci_host_bridge *host,
+		struct pci_host_info *info)
 {
 	int ret;
-	struct pci_host_bridge_window *window;
+	struct pci_sys_data *sys = info->arg;
+	struct pci_host_bridge_window *window, *n;
 
 	if (list_empty(&sys->resources)) {
-		pci_add_resource_offset(&sys->resources,
+		pci_add_resource_offset(&host->windows,
 			 &iomem_resource, sys->mem_offset);
+	} else {
+		list_for_each_entry_safe(window, n,
+				&sys->resources, list) {
+			list_move_tail(&window->list,
+					&host->windows);
+		}
 	}
 
-	list_for_each_entry(window, &sys->resources, list) {
+	list_for_each_entry(window, &host->windows, list) {
 		if (resource_type(window->res) == IORESOURCE_IO)
 			return 0;
 	}
 
-	sys->io_res.start = (busnr * SZ_64K) ?  : pcibios_min_io;
-	sys->io_res.end = (busnr + 1) * SZ_64K - 1;
+	sys->io_res.start = (sys->nr * SZ_64K) ?  : pcibios_min_io;
+	sys->io_res.end = (sys->nr + 1) * SZ_64K - 1;
 	sys->io_res.flags = IORESOURCE_IO;
 	sys->io_res.name = sys->io_res_name;
-	sprintf(sys->io_res_name, "PCI%d I/O", busnr);
+	sprintf(sys->io_res_name, "PCI%d I/O", sys->nr);
 
 	ret = request_resource(&ioport_resource, &sys->io_res);
 	if (ret) {
 		pr_err("PCI: unable to allocate I/O port region (%d)\n", ret);
 		return ret;
 	}
-	pci_add_resource_offset(&sys->resources, &sys->io_res,
+	pci_add_resource_offset(&host->windows, &sys->io_res,
 				sys->io_offset);
 
 	return 0;
@@ -462,8 +470,9 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
 			    struct list_head *head)
 {
 	struct pci_sys_data *sys = NULL;
-	int ret;
-	int nr, busnr;
+	int ret, nr, busnr, domain;
+	struct pci_host_bridge *host;
+	struct pci_host_info info;
 
 	for (nr = busnr = 0; nr < hw->nr_controllers; nr++) {
 		sys = kzalloc(sizeof(struct pci_sys_data), GFP_KERNEL);
@@ -471,6 +480,7 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
 			panic("PCI: unable to allocate sys data!");
 
 		sys->busnr   = busnr;
+		sys->nr		 = nr;
 		sys->swizzle = hw->swizzle;
 		sys->map_irq = hw->map_irq;
 		sys->align_resource = hw->align_resource;
@@ -482,25 +492,25 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
 			sys->private_data = hw->private_data[nr];
 
 		ret = hw->setup(nr, sys);
-
 		if (ret > 0) {
-			ret = pcibios_init_resources(nr, sys);
-			if (ret)  {
-				kfree(sys);
-				break;
-			}
-
+			init_pci_host_info(&info);
+			info.arg = sys;
+			info.init_res = pcibios_init_resources;
+			domain = pci_get_domain_nr(parent);
 			if (hw->scan)
 				sys->bus = hw->scan(nr, sys);
-			else
-				sys->bus = pci_scan_root_bus(parent, sys->busnr,
-						hw->ops, sys, &sys->resources);
+			else {
+				host = pci_scan_host_bridge(parent, 
+						PCI_DOMBUS(domain, sys->busnr),
+						hw->ops, &info);
+				if (host)
+					sys->bus = host->bus;
+			}
 
 			if (!sys->bus)
 				panic("PCI: unable to scan bus!");
 
 			busnr = sys->bus->busn_res.end + 1;
-
 			list_add(&sys->node, head);
 		} else {
 			kfree(sys);
-- 
1.7.1

[RFC PATCH 16/16] powerpc/PCI: Use pci_scan_host_bridge() to scan PCI bus

From: Yijing Wang <hidden>
Date: 2014-11-17 09:42:15

Signed-off-by: Yijing Wang <redacted>
---
 arch/powerpc/kernel/pci-common.c |   81 ++++++++++++++++++++++---------------
 1 files changed, 48 insertions(+), 33 deletions(-)
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index e5dad9a..5b0f078 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1578,54 +1578,69 @@ struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
 	return of_node_get(hose->dn);
 }
 
-/**
- * pci_scan_phb - Given a pci_controller, setup and scan the PCI bus
- * @hose: Pointer to the PCI host controller instance structure
- */
-void pcibios_scan_phb(struct pci_controller *hose)
+static int pcibios_host_init_res(struct pci_host_bridge *host,
+		struct pci_host_info *info)
 {
-	LIST_HEAD(resources);
-	struct pci_bus *bus;
-	struct device_node *node = hose->dn;
-	int mode;
-
-	pr_debug("PCI: Scanning PHB %s\n", of_node_full_name(node));
+	struct pci_controller *hose = info->arg;
 
 	/* Get some IO space for the new PHB */
 	pcibios_setup_phb_io_space(hose);
-
 	/* Wire up PHB bus resources */
-	pcibios_setup_phb_resources(hose, &resources);
+	pcibios_setup_phb_resources(hose, &host->windows);
 
 	hose->busn.start = hose->first_busno;
 	hose->busn.end	 = hose->last_busno;
 	hose->busn.flags = IORESOURCE_BUS;
-	pci_add_resource(&resources, &hose->busn);
+	pci_add_resource(&host->windows, &hose->busn);
+	return 0;
+}
 
-	/* Create an empty bus for the toplevel */
-	bus = pci_create_root_bus(hose->parent, hose->first_busno,
-				  hose->ops, hose, &resources);
-	if (bus == NULL) {
-		pr_err("Failed to create bus for PCI domain %04x\n",
-			hose->global_number);
-		pci_free_resource_list(&resources);
-		return;
-	}
-	hose->bus = bus;
+static void pcibios_of_scan_bus(struct pci_host_bridge *host)
+{
+	int mode;
+	int max;
 
 	/* Get probe mode and perform scan */
 	mode = PCI_PROBE_NORMAL;
-	if (node && ppc_md.pci_probe_mode)
-		mode = ppc_md.pci_probe_mode(bus);
+	if (host->node && ppc_md.pci_probe_mode)
+		mode = ppc_md.pci_probe_mode(host->bus);
 	pr_debug("    probe mode: %d\n", mode);
 	if (mode == PCI_PROBE_DEVTREE)
-		of_scan_bus(node, bus);
-
+		of_scan_bus(host->node, host->bus);
+	
 	if (mode == PCI_PROBE_NORMAL) {
-		pci_bus_update_busn_res_end(bus, 255);
-		hose->last_busno = pci_scan_child_bus(bus);
-		pci_bus_update_busn_res_end(bus, hose->last_busno);
+		pci_bus_update_busn_res_end(host->bus, 255);
+		max = pci_scan_child_bus(host->bus);
+		pci_bus_update_busn_res_end(host->bus, max);
+	}
+}
+/**
+ * pci_scan_phb - Given a pci_controller, setup and scan the PCI bus
+ * @hose: Pointer to the PCI host controller instance structure
+ */
+void pcibios_scan_phb(struct pci_controller *hose)
+{
+	struct pci_host_bridge *host;
+	struct pci_host_info info;
+
+	pr_debug("PCI: Scanning PHB %s\n", of_node_full_name(hose->dn));
+
+	init_pci_host_info(&info);
+	info.arg = hose;
+	info.node = hose->dn;
+	info.init_res = pcibios_host_init_res;
+	info.of_scan_bus = pcibios_of_scan_bus;
+	/* Create an empty bus for the toplevel */
+	host = pci_scan_host_bridge(hose->parent, 
+			PCI_DOMBUS(hose->global_number,hose->first_busno),
+				  hose->ops, &info);
+	if (host == NULL) {
+		pr_err("Failed to create bus for PCI domain %04x\n",
+			hose->global_number);
+		return;
 	}
+	hose->bus = host->bus;
+	hose->last_busno = host->bus->busn_res.end;
 
 	/* Platform gets a chance to do some global fixups before
 	 * we proceed to resource allocation
@@ -1634,9 +1649,9 @@ void pcibios_scan_phb(struct pci_controller *hose)
 		ppc_md.pcibios_fixup_phb(hose);
 
 	/* Configure PCI Express settings */
-	if (bus && !pci_has_flag(PCI_PROBE_ONLY)) {
+	if (!pci_has_flag(PCI_PROBE_ONLY)) {
 		struct pci_bus *child;
-		list_for_each_entry(child, &bus->children, node)
+		list_for_each_entry(child, &host->bus->children, node)
 			pcie_bus_configure_settings(child);
 	}
 }
-- 
1.7.1

[RFC PATCH 04/16] PCI: Rip out pci_bus_add_devices() from pci_scan_root_bus()

From: Yijing Wang <hidden>
Date: 2014-11-17 09:43:39

Rip out pci_bus_add_devices() from pci_scan_root_bus()
for following reasons.
1. pci_scan_root_bus() means we only do the scan, we should
not add pci busses.
2. A lots of drviers which use pci_scan_root_bus() call
pci_bus_size_bridges(), pci_bus_assign_resources() after
pci_scan_root_bus(). But strictly speaking pci_bus_add_devices()
should be called after the resources assignment.

Signed-off-by: Yijing Wang <redacted>
---
 arch/alpha/kernel/pci.c           |    1 +
 arch/alpha/kernel/sys_nautilus.c  |    1 +
 arch/frv/mb93090-mb00/pci-vdk.c   |    8 +++++---
 arch/ia64/sn/kernel/io_init.c     |    2 ++
 arch/m68k/coldfire/pci.c          |    1 +
 arch/microblaze/pci/pci-common.c  |    2 +-
 arch/mips/pci/pci.c               |    1 +
 arch/mn10300/unit-asb2305/pci.c   |    7 +++++--
 arch/s390/pci/pci.c               |    2 +-
 arch/sh/drivers/pci/pci.c         |    1 +
 arch/sparc/kernel/leon_pci.c      |    1 +
 arch/sparc/kernel/pcic.c          |    2 ++
 arch/tile/kernel/pci.c            |    3 ++-
 arch/tile/kernel/pci_gx.c         |    3 ++-
 arch/unicore32/kernel/pci.c       |    2 +-
 arch/x86/pci/common.c             |   10 ++++++----
 arch/xtensa/kernel/pci.c          |    1 +
 drivers/pci/host/pci-xgene.c      |    2 +-
 drivers/pci/hotplug/ibmphp_core.c |    6 ++++--
 drivers/pci/probe.c               |    1 -
 20 files changed, 39 insertions(+), 18 deletions(-)
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 076c35c..81251a5 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -349,6 +349,7 @@ common_init_pci(void)
 
 	pci_assign_unassigned_resources();
 	pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
+	pci_bus_add_devices(bus);
 }
 
 
diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
index 1047ab3..60fbd77 100644
--- a/arch/alpha/kernel/sys_nautilus.c
+++ b/arch/alpha/kernel/sys_nautilus.c
@@ -253,6 +253,7 @@ nautilus_init_pci(void)
 	   for the root bus, so just clear it. */
 	bus->self = NULL;
 	pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
+	pci_bus_add_devices(bus);
 }
 
 /*
diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c
index efa5d65..85f87dc 100644
--- a/arch/frv/mb93090-mb00/pci-vdk.c
+++ b/arch/frv/mb93090-mb00/pci-vdk.c
@@ -316,6 +316,7 @@ void pcibios_fixup_bus(struct pci_bus *bus)
 
 int __init pcibios_init(void)
 {
+	struct pci_bus *bus = NULL;
 	struct pci_ops *dir = NULL;
 	LIST_HEAD(resources);
 
@@ -383,12 +384,13 @@ int __init pcibios_init(void)
 	printk("PCI: Probing PCI hardware\n");
 	pci_add_resource(&resources, &pci_ioport_resource);
 	pci_add_resource(&resources, &pci_iomem_resource);
-	pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources);
-
+	bus = pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources);
+	if (!bus)
+		return -ENXIO;
 	pcibios_irq_init();
 	pcibios_fixup_irqs();
 	pcibios_resource_survey();
-
+	pci_bus_add_devices(bus);
 	return 0;
 }
 
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index 0b5ce82..1be65eb 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -271,7 +271,9 @@ sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
  	if (bus == NULL) {
 		kfree(res);
 		kfree(controller);
+		return;
 	}
+	pci_bus_add_devices(bus);
 }
 
 /*
diff --git a/arch/m68k/coldfire/pci.c b/arch/m68k/coldfire/pci.c
index 4d242fb..840a431 100644
--- a/arch/m68k/coldfire/pci.c
+++ b/arch/m68k/coldfire/pci.c
@@ -319,6 +319,7 @@ static int __init mcf_pci_init(void)
 	pci_fixup_irqs(pci_common_swizzle, mcf_pci_map_irq);
 	pci_bus_size_bridges(rootbus);
 	pci_bus_assign_resources(rootbus);
+	pci_bus_add_devices(rootbus);
 	return 0;
 }
 
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index 9037914..9ca7e3f 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -1344,8 +1344,8 @@ static void pcibios_scan_phb(struct pci_controller *hose)
 	}
 	bus->busn_res.start = hose->first_busno;
 	hose->bus = bus;
-
 	hose->last_busno = bus->busn_res.end;
+	pci_bus_add_devices(bus);
 }
 
 static int __init pcibios_init(void)
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 1bf60b1..f083688 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -113,6 +113,7 @@ static void pcibios_scanbus(struct pci_controller *hose)
 		if (!pci_has_flag(PCI_PROBE_ONLY)) {
 			pci_bus_size_bridges(bus);
 			pci_bus_assign_resources(bus);
+			pci_bus_add_devices(bus);
 		}
 	}
 }
diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c
index 6b4339f..011af54 100644
--- a/arch/mn10300/unit-asb2305/pci.c
+++ b/arch/mn10300/unit-asb2305/pci.c
@@ -345,6 +345,7 @@ void pcibios_fixup_bus(struct pci_bus *bus)
  */
 static int __init pcibios_init(void)
 {
+	struct pci_bus *bus;
 	resource_size_t io_offset, mem_offset;
 	LIST_HEAD(resources);
 
@@ -376,11 +377,13 @@ static int __init pcibios_init(void)
 
 	pci_add_resource_offset(&resources, &pci_ioport_resource, io_offset);
 	pci_add_resource_offset(&resources, &pci_iomem_resource, mem_offset);
-	pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources);
-
+	bus = pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources);
+	if (!bus)
+		return 0;
 	pcibios_irq_init();
 	pcibios_fixup_irqs();
 	pcibios_resource_survey();
+	pci_bus_add_devices(bus);
 	return 0;
 }
 
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 2fa7b14..016ea48 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -755,7 +755,7 @@ static int zpci_scan_bus(struct zpci_dev *zdev)
 		zpci_cleanup_bus_resources(zdev);
 		return -EIO;
 	}
-
+	pci_bus_add_devices(zdev->bus);
 	zdev->bus->max_bus_speed = zdev->max_bus_speed;
 	return 0;
 }
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index 1bc09ee..efc1051 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -69,6 +69,7 @@ static void pcibios_scanbus(struct pci_channel *hose)
 
 		pci_bus_size_bridges(bus);
 		pci_bus_assign_resources(bus);
+		pci_bus_add_devices(bus);
 	} else {
 		pci_free_resource_list(&resources);
 	}
diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c
index 899b720..2971076 100644
--- a/arch/sparc/kernel/leon_pci.c
+++ b/arch/sparc/kernel/leon_pci.c
@@ -40,6 +40,7 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
 
 		/* Assign devices with resources */
 		pci_assign_unassigned_resources();
+		pci_bus_add_devices(root_bus);
 	} else {
 		pci_free_resource_list(&resources);
 	}
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 64aafac..5457814 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -392,6 +392,8 @@ static void __init pcic_pbm_scan_bus(struct linux_pcic *pcic)
 
 	pbm->pci_bus = pci_scan_root_bus(NULL, pbm->pci_first_busno, 
 			&pcic_ops, pbm, NULL);
+	if (pbm->pci_bus)
+		pci_bus_add_devices(pbm->pci_bus);
 #if 0 /* deadwood transplanted from sparc64 */
 	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
 	pci_record_assignments(pbm, pbm->pci_bus);
diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c
index 1f80a88..268423e 100644
--- a/arch/tile/kernel/pci.c
+++ b/arch/tile/kernel/pci.c
@@ -326,7 +326,8 @@ int __init pcibios_init(void)
 
 	/* Configure the max_read_size and max_payload_size values. */
 	fixup_read_and_payload_sizes();
-
+	if (bus)
+		pci_bus_add_devices(bus);
 	/* Record the I/O resources in the PCI controller structure. */
 	for (i = 0; i < TILE_NUM_PCIE; i++) {
 		/*
diff --git a/arch/tile/kernel/pci_gx.c b/arch/tile/kernel/pci_gx.c
index e39f9c5..5f05a9a 100644
--- a/arch/tile/kernel/pci_gx.c
+++ b/arch/tile/kernel/pci_gx.c
@@ -903,7 +903,8 @@ int __init pcibios_init(void)
 	 * associated with the devices read in above.
 	 */
 	pci_assign_unassigned_resources();
-
+	if (bus)
+		pci_bus_add_devices(bus);
 	/* Record the I/O resources in the PCI controller structure. */
 	for (i = 0; i < num_rc_controllers; i++) {
 		struct pci_controller *controller = &pci_controllers[i];
diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
index be0f261..0d4c563 100644
--- a/arch/unicore32/kernel/pci.c
+++ b/arch/unicore32/kernel/pci.c
@@ -270,11 +270,11 @@ static int __init pci_common_init(void)
 		 * Size the bridge windows.
 		 */
 		pci_bus_size_bridges(puv3_bus);
-
 		/*
 		 * Assign resources.
 		 */
 		pci_bus_assign_resources(puv3_bus);
+		pci_bus_add_devices(puv3_bus);
 	}
 
 	return 0;
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 7b20bcc..b16632b 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -471,10 +471,12 @@ void pcibios_scan_root(int busnum)
 	x86_pci_root_bus_resources(busnum, &resources);
 	printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
 	bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, sd, &resources);
-	if (!bus) {
-		pci_free_resource_list(&resources);
-		kfree(sd);
-	}
+	if (bus) {
+		pci_bus_add_devices(bus);
+		return;
+	} 
+	pci_free_resource_list(&resources);
+	kfree(sd);
 }
 
 void __init pcibios_set_cache_line_size(void)
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
index 5b34033..c4b5b5d 100644
--- a/arch/xtensa/kernel/pci.c
+++ b/arch/xtensa/kernel/pci.c
@@ -185,6 +185,7 @@ static int __init pcibios_init(void)
 		pci_controller_apertures(pci_ctrl, &resources);
 		bus = pci_scan_root_bus(NULL, pci_ctrl->first_busno,
 					pci_ctrl->ops, pci_ctrl, &resources);
+		pci_bus_add_devices(bus);
 		pci_ctrl->bus = bus;
 		pci_ctrl->last_busno = bus->busn_res.end;
 		if (next_busno <= pci_ctrl->last_busno)
diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c
index 9ecabfa..e7a4f66 100644
--- a/drivers/pci/host/pci-xgene.c
+++ b/drivers/pci/host/pci-xgene.c
@@ -634,7 +634,7 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev)
 	bus = pci_scan_root_bus(&pdev->dev, 0, &xgene_pcie_ops, port, &res);
 	if (!bus)
 		return -ENOMEM;
-
+	pci_bus_add_devices(bus);
 	platform_set_drvdata(pdev, port);
 	return 0;
 }
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index b486432..76ce157 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -740,7 +740,7 @@ static void ibm_unconfigure_device(struct pci_func *func)
  */
 static u8 bus_structure_fixup(u8 busno)
 {
-	struct pci_bus *bus;
+	struct pci_bus *bus, *b;
 	struct pci_dev *dev;
 	u16 l;
 
@@ -767,7 +767,9 @@ static u8 bus_structure_fixup(u8 busno)
 					(l != 0x0000) && (l != 0xffff)) {
 			debug("%s - Inside bus_structure_fixup()\n",
 							__func__);
-			pci_scan_root_bus(NULL, busno, ibmphp_pci_bus->ops, NULL, NULL);
+			b = pci_scan_root_bus(NULL, busno, ibmphp_pci_bus->ops, NULL, NULL);
+			if (b)
+				pci_bus_add_devices(b);
 			break;
 		}
 	}
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 0a02fc2..97711f3 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2101,7 +2101,6 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
 	if (!found)
 		pci_bus_update_busn_res_end(b, max);
 
-	pci_bus_add_devices(b);
 	return b;
 }
 EXPORT_SYMBOL(pci_scan_root_bus);
-- 
1.7.1

[RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()

From: Yijing Wang <hidden>
Date: 2014-11-17 09:43:41

There are some common PCI infos like domain, msi_controller, these
infos are saved in arch PCI sysdata, and lots arch specific functions
like pci_domain_nr() and pcibios_msi_controller() required.
We could separate pci_host_bridge creation out of pci_create_root_bus(),
then we could put the common infos in, then we could eliminate
the arch specifc functions.

Signed-off-by: Yijing Wang <redacted>
---
 drivers/pci/host-bridge.c |   99 +++++++++++++++++++++++++++++++++
 drivers/pci/probe.c       |  134 ++++++++++++++++----------------------------
 include/linux/pci.h       |   11 +++-
 3 files changed, 158 insertions(+), 86 deletions(-)
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 0e5f3c9..e31604f 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -8,6 +8,105 @@
 
 #include "pci.h"
 
+LIST_HEAD(pci_host_bridge_list);
+DECLARE_RWSEM(pci_host_bridge_sem);
+
+static struct resource busn_resource = {
+	.name	= "PCI busn",
+	.start	= 0,
+	.end	= 255,
+	.flags	= IORESOURCE_BUS,
+};
+
+static void pci_release_host_bridge_dev(struct device *dev)
+{
+	struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
+
+	if (bridge->release_fn)
+		bridge->release_fn(bridge);
+	pci_free_resource_list(&bridge->windows);
+	kfree(bridge);
+}
+
+struct pci_host_bridge *pci_create_host_bridge(
+		struct device *parent, u32 db, 
+		struct pci_ops *ops, void *sysdata, 
+		struct list_head *resources)
+{
+	int error;
+	struct pci_bus *b;
+	struct pci_host_bridge *host, *h;
+	struct pci_host_bridge_window *window, *n;
+
+	down_read(&pci_host_bridge_sem);
+	list_for_each_entry(h, &pci_host_bridge_list, list) {
+		if (h->domain == PCI_DOMAIN(db) &&
+				h->busnum == PCI_BUSNUM(db)) {
+			dev_dbg(&h->dev, "pci host bridge exist\n");
+			up_read(&pci_host_bridge_sem);
+			return NULL;
+		}
+	}
+	up_read(&pci_host_bridge_sem);
+
+	host = kzalloc(sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return NULL;
+
+	host->sysdata = sysdata;
+	host->busnum = PCI_BUSNUM(db);
+	host->domain = PCI_DOMAIN(db);
+	host->ops = ops;
+	host->dev.parent = parent;
+	INIT_LIST_HEAD(&host->windows);
+	host->dev.release = pci_release_host_bridge_dev;
+
+	/* this is hack, just for build, will be removed later*/
+	b = kzalloc(sizeof(*b), GFP_KERNEL);
+	b->sysdata = sysdata;
+	pci_bus_assign_domain_nr(b, parent);
+	host->domain = pci_domain_nr(b);
+
+	if (!resources) {
+		/* Use default IO/MEM/BUS resources*/
+		pci_add_resource(&host->windows, &ioport_resource);
+		pci_add_resource(&host->windows, &iomem_resource);
+		pci_add_resource(&host->windows, &busn_resource);
+	} else {
+		list_for_each_entry_safe(window, n, resources, list)
+			list_move_tail(&window->list, &host->windows);
+	}
+
+	dev_set_name(&host->dev, "pci%04x:%02x", host->domain, 
+			host->busnum);
+	error = pcibios_root_bridge_prepare(host);
+	if(error) {
+		kfree(host);
+		return NULL;
+	}
+
+	error = device_register(&host->dev);
+	if (error) {
+		put_device(&host->dev);
+		return NULL;
+	}
+
+	down_write(&pci_host_bridge_sem);
+	list_add_tail(&host->list, &pci_host_bridge_list);
+	up_write(&pci_host_bridge_sem);
+	return host;
+}
+EXPORT_SYMBOL(pci_create_host_bridge);
+
+void pci_free_host_bridge(struct pci_host_bridge *host)
+{
+	down_write(&pci_host_bridge_sem);
+	list_del(&host->list);
+	up_write(&pci_host_bridge_sem);
+
+	device_unregister(&host->dev);
+}
+
 static struct pci_bus *find_pci_root_bus(struct pci_bus *bus)
 {
 	while (bus->parent)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index adf4d09..d472da4 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -17,13 +17,6 @@
 #define CARDBUS_LATENCY_TIMER	176	/* secondary latency timer */
 #define CARDBUS_RESERVE_BUSNR	3
 
-static struct resource busn_resource = {
-	.name	= "PCI busn",
-	.start	= 0,
-	.end	= 255,
-	.flags	= IORESOURCE_BUS,
-};
-
 /* Ugh.  Need to stop exporting this to modules. */
 LIST_HEAD(pci_root_buses);
 EXPORT_SYMBOL(pci_root_buses);
@@ -508,31 +501,6 @@ static struct pci_bus *pci_alloc_bus(struct pci_bus *parent)
 	return b;
 }
 
-static void pci_release_host_bridge_dev(struct device *dev)
-{
-	struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
-
-	if (bridge->release_fn)
-		bridge->release_fn(bridge);
-
-	pci_free_resource_list(&bridge->windows);
-
-	kfree(bridge);
-}
-
-static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
-{
-	struct pci_host_bridge *bridge;
-
-	bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
-	if (!bridge)
-		return NULL;
-
-	INIT_LIST_HEAD(&bridge->windows);
-	bridge->bus = b;
-	return bridge;
-}
-
 static const unsigned char pcix_bus_speed[] = {
 	PCI_SPEED_UNKNOWN,		/* 0 */
 	PCI_SPEED_66MHz_PCIX,		/* 1 */
@@ -1895,52 +1863,33 @@ void __weak pcibios_remove_bus(struct pci_bus *bus)
 {
 }
 
-struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
-		struct pci_ops *ops, void *sysdata, struct list_head *resources)
+struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *bridge)
 {
 	int error;
-	struct pci_host_bridge *bridge;
 	struct pci_bus *b, *b2;
-	struct pci_host_bridge_window *window, *n;
+	struct pci_host_bridge_window *window;
 	struct resource *res;
 	resource_size_t offset;
 	char bus_addr[64];
 	char *fmt;
-	u8	bus = PCI_BUSNUM(db);
+	struct device *parent = bridge->dev.parent;
 
 	b = pci_alloc_bus(NULL);
 	if (!b)
 		return NULL;
 
-	b->sysdata = sysdata;
-	b->ops = ops;
-	b->number = b->busn_res.start = bus;
+	b->sysdata = bridge->sysdata;
+	b->ops = bridge->ops;
+	b->number = b->busn_res.start = bridge->busnum;
 	pci_bus_assign_domain_nr(b, parent);
-	b2 = pci_find_bus(pci_domain_nr(b), bus);
+	bridge->domain = pci_domain_nr(b);
+	b2 = pci_find_bus(pci_domain_nr(b), bridge->busnum);
 	if (b2) {
 		/* If we already got to this bus through a different bridge, ignore it */
 		dev_dbg(&b2->dev, "bus already known\n");
 		goto err_out;
 	}
 
-	bridge = pci_alloc_host_bridge(b);
-	if (!bridge)
-		goto err_out;
-
-	bridge->dev.parent = parent;
-	bridge->dev.release = pci_release_host_bridge_dev;
-	dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
-	error = pcibios_root_bridge_prepare(bridge);
-	if (error) {
-		kfree(bridge);
-		goto err_out;
-	}
-
-	error = device_register(&bridge->dev);
-	if (error) {
-		put_device(&bridge->dev);
-		goto err_out;
-	}
 	b->bridge = get_device(&bridge->dev);
 	device_enable_async_suspend(b->bridge);
 	pci_set_bus_of_node(b);
@@ -1950,7 +1899,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
 
 	b->dev.class = &pcibus_class;
 	b->dev.parent = b->bridge;
-	dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
+	dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), b->number);
 	error = device_register(&b->dev);
 	if (error)
 		goto class_dev_reg_err;
@@ -1966,12 +1915,11 @@ struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
 		printk(KERN_INFO "PCI host bridge to bus %s\n", dev_name(&b->dev));
 
 	/* Add initial resources to the bus */
-	list_for_each_entry_safe(window, n, resources, list) {
-		list_move_tail(&window->list, &bridge->windows);
+	list_for_each_entry(window, &bridge->windows, list) {
 		res = window->res;
 		offset = window->offset;
 		if (res->flags & IORESOURCE_BUS)
-			pci_bus_insert_busn_res(b, bus, res->end);
+			pci_bus_insert_busn_res(b, b->number, res->end);
 		else
 			pci_bus_add_resource(b, res, 0);
 		if (offset) {
@@ -2001,6 +1949,25 @@ err_out:
 	return NULL;
 }
 
+struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
+		struct pci_ops *ops, void *sysdata, struct list_head *resources)
+{
+	struct pci_host_bridge *host;
+
+	host = pci_create_host_bridge(parent, bus, ops, 
+			sysdata ,resources);
+	if (!host)
+		return NULL;
+
+	host->bus = __pci_create_root_bus(host);
+	if (!host->bus) {
+		pci_free_host_bridge(host);
+		return NULL;
+	}
+		
+	return host->bus;
+}
+
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
 {
 	struct resource *res = &b->busn_res;
@@ -2069,40 +2036,37 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
 {
 	struct pci_host_bridge_window *window;
 	bool found = false;
-	struct pci_bus *b;
-	LIST_HEAD(default_res);
+	struct pci_host_bridge *host;
 	int max;
 
-	if (!resources) {
-		pci_add_resource(&default_res, &ioport_resource);
-		pci_add_resource(&default_res, &iomem_resource);
-		pci_add_resource(&default_res, &busn_resource);
-	} else {
-		list_for_each_entry(window, resources, list)
-			if (window->res->flags & IORESOURCE_BUS) {
-				found = true;
-				break;
-			}
-	}
+	host = pci_create_host_bridge(parent, db, ops, sysdata, resources);
+	if (!host)
+		return NULL;
 
-	b = pci_create_root_bus(parent, db, ops, sysdata, 
-			resources ? resources : &default_res);
-	if (!b)
+	list_for_each_entry(window, &host->windows, list)
+		if (window->res->flags & IORESOURCE_BUS) {
+			found = true;
+			break;
+		}
+
+	host->bus = __pci_create_root_bus(host);
+	if (!host->bus) {
+		pci_free_host_bridge(host);
 		return NULL;
+	}
 
 	if (!found) {
-		dev_info(&b->dev,
+		dev_info(&host->bus->dev,
 		 "No busn resource found for root bus, will use [bus %02x-ff]\n",
 			PCI_BUSNUM(db));
-		pci_bus_insert_busn_res(b, PCI_BUSNUM(db), 255);
+		pci_bus_insert_busn_res(host->bus, PCI_BUSNUM(db), 255);
 	}
 
-	max = pci_scan_child_bus(b);
-
+	max = pci_scan_child_bus(host->bus);
 	if (!found)
-		pci_bus_update_busn_res_end(b, max);
+		pci_bus_update_busn_res_end(host->bus, max);
 
-	return b;
+	return host->bus;
 }
 EXPORT_SYMBOL(pci_scan_root_bus);
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 8b11b38..daa7f40 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -402,7 +402,12 @@ struct pci_host_bridge_window {
 struct pci_host_bridge {
 	struct device dev;
 	struct pci_bus *bus;		/* root bus */
+	struct list_head list;
 	struct list_head windows;	/* pci_host_bridge_windows */
+	int busnum;
+	int domain;
+	void *sysdata;
+	struct pci_ops *ops;
 	void (*release_fn)(struct pci_host_bridge *);
 	void *release_data;
 };
@@ -413,7 +418,9 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
 		     void *release_data);
 
 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
-
+struct pci_host_bridge *pci_create_host_bridge(
+		struct device *parent, u32 db, struct pci_ops *ops, 
+		void *sys, struct list_head *resources);
 /*
  * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
  * to P2P or CardBus bridge windows) go in a table.  Additional ones (for
@@ -770,6 +777,8 @@ void pci_bus_add_devices(const struct pci_bus *bus);
 struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
 				    struct pci_ops *ops, void *sysdata,
 				    struct list_head *resources);
+struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *host);
+void pci_free_host_bridge(struct pci_host_bridge *host);
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
 int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
 void pci_bus_release_busn_res(struct pci_bus *b);
-- 
1.7.1

[RFC PATCH 11/16] x86/PCI: Use pci_scan_host_bridge() instead of pci_create_root_bus()

From: Yijing Wang <hidden>
Date: 2014-11-17 09:43:43

Now we could use pci_scan_host_bridge() to refactor
pci_acpi_scan_root().

Signed-off-by: Yijing Wang <redacted>
---
 arch/x86/pci/acpi.c   |   65 ++++++++++++++++++++++++++++++-------------------
 arch/x86/pci/common.c |   23 ++++++++++++-----
 2 files changed, 56 insertions(+), 32 deletions(-)
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index cfd1b13..528fca3 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -13,6 +13,7 @@ struct pci_root_info {
 	unsigned int res_num;
 	struct resource *res;
 	resource_size_t *res_offset;
+	struct acpi_pci_root *root;
 	struct pci_sysdata sd;
 #ifdef	CONFIG_PCI_MMCONFIG
 	bool mcfg_added;
@@ -467,16 +468,40 @@ static void probe_pci_root_info(struct pci_root_info *info,
 				info);
 }
 
+static int pci_acpi_init_res(struct pci_host_bridge *host,
+		struct pci_host_info *arg)
+{
+	struct pci_sysdata *sd = arg->arg;
+	struct pci_root_info *info = container_of(sd,
+			struct pci_root_info, sd);
+
+	/* insert busn res at first */
+	pci_add_resource(&host->windows,  &info->root->secondary);
+	/*
+	 * _CRS with no apertures is normal, so only fall back to
+	 * defaults or native bridge info if we're ignoring _CRS.
+	 */
+	if (pci_use_crs)
+		add_resources(info, &host->windows);
+	else {
+		free_pci_root_info_res(info);
+		x86_pci_root_bus_resources(host->busnum, &host->windows);
+	}
+	
+	return 0;
+}
+
 struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 {
 	struct acpi_device *device = root->device;
 	struct pci_root_info *info;
 	int domain = root->segment;
 	int busnum = root->secondary.start;
-	LIST_HEAD(resources);
 	struct pci_bus *bus;
 	struct pci_sysdata *sd;
 	int node;
+	struct pci_host_info arg;
+	struct pci_host_bridge *host;
 
 	if (pci_ignore_seg)
 		domain = 0;
@@ -506,10 +531,14 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 		return NULL;
 	}
 
+	info->root = root;
 	sd = &info->sd;
 	sd->domain = domain;
 	sd->node = node;
 	sd->companion = device;
+	init_pci_host_info(&arg);
+	arg.arg = sd;
+	arg.init_res = pci_acpi_init_res;
 
 	bus = pci_find_bus(domain, busnum);
 	if (bus) {
@@ -522,33 +551,19 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 	} else {
 		probe_pci_root_info(info, device, busnum, domain);
 
-		/* insert busn res at first */
-		pci_add_resource(&resources,  &root->secondary);
-		/*
-		 * _CRS with no apertures is normal, so only fall back to
-		 * defaults or native bridge info if we're ignoring _CRS.
-		 */
-		if (pci_use_crs)
-			add_resources(info, &resources);
-		else {
-			free_pci_root_info_res(info);
-			x86_pci_root_bus_resources(busnum, &resources);
+		if (!setup_mcfg_map(info, domain, (u8)root->secondary.start,
+				    (u8)root->secondary.end, root->mcfg_addr)) {
+			host = pci_scan_host_bridge(NULL, PCI_DOMBUS(domain, busnum), 
+					&pci_root_ops, &arg);
+			bus = host->bus;
 		}
 
-		if (!setup_mcfg_map(info, domain, (u8)root->secondary.start,
-				    (u8)root->secondary.end, root->mcfg_addr))
-			bus = pci_create_root_bus(NULL, busnum, &pci_root_ops,
-						  sd, &resources);
-
-		if (bus) {
-			pci_scan_child_bus(bus);
-			pci_set_host_bridge_release(
-				to_pci_host_bridge(bus->bridge),
+		if (bus) 
+			pci_set_host_bridge_release(host,
 				release_pci_root_info, info);
-		} else {
-			pci_free_resource_list(&resources);
+		else 
 			__release_pci_root_info(info);
-		}
+		
 	}
 
 	/* After the PCI-E bus has been walked and all devices discovered,
@@ -568,7 +583,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 
 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
 {
-	struct pci_sysdata *sd = bridge->bus->sysdata;
+	struct pci_sysdata *sd = bridge->sysdata;
 
 	ACPI_COMPANION_SET(&bridge->dev, sd->companion);
 	return 0;
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index b16632b..0032065 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -456,11 +456,18 @@ void __init dmi_check_pciprobe(void)
 	dmi_check_system(pciprobe_dmi_table);
 }
 
+static int pcibios_init_res(struct pci_host_bridge *host,
+		struct pci_host_info *info)
+{
+	x86_pci_root_bus_resources(host->busnum, &host->windows);
+	return 0;
+}
+
 void pcibios_scan_root(int busnum)
 {
-	struct pci_bus *bus;
 	struct pci_sysdata *sd;
-	LIST_HEAD(resources);
+	struct pci_host_info info;
+	struct pci_host_bridge *host;
 
 	sd = kzalloc(sizeof(*sd), GFP_KERNEL);
 	if (!sd) {
@@ -468,14 +475,16 @@ void pcibios_scan_root(int busnum)
 		return;
 	}
 	sd->node = x86_pci_root_bus_node(busnum);
-	x86_pci_root_bus_resources(busnum, &resources);
+	init_pci_host_info(&info);
+	info.init_res = pcibios_init_res;
+	info.arg = sd;
 	printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
-	bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, sd, &resources);
-	if (bus) {
-		pci_bus_add_devices(bus);
+	host = pci_scan_host_bridge(NULL, PCI_DOMBUS(0, busnum),
+		   	&pci_root_ops, &info);
+	if (host) {
+		pci_bus_add_devices(host->bus);
 		return;
 	} 
-	pci_free_resource_list(&resources);
 	kfree(sd);
 }
 
-- 
1.7.1

[RFC PATCH 08/16] PCI: Introduce pci_scan_host_bridge() and pci_host_info

From: Yijing Wang <hidden>
Date: 2014-11-17 09:43:45

From: Yijing Wang <redacted>

Now pci_host_bridge has been ripped out from pci root
bus creation. Currently pci_scan_root_bus() lacks
scalability, so platform host drivers have no proper
way to configure pci_host_bridge. E.g we should assign
msi_controller to pci_host_bridge, add argument for
pci_scan_root_bus() is not a good idea, it has already
five, so introudce struct pci_host_info to make
pci scan interfaces more scalable. Because almost
all host drivers need to configure host resources,
so we put .init_res() in it first, and add other
hooks when need.

Signed-off-by: Yijing Wang <redacted>
---
 drivers/pci/host-bridge.c |   27 +++++++++-------
 drivers/pci/probe.c       |   73 ++++++++++++++++++++++++++++++++++++++++++--
 include/linux/pci.h       |   20 ++++++++++++-
 3 files changed, 103 insertions(+), 17 deletions(-)
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index e31604f..49b6c21 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -8,9 +8,6 @@
 
 #include "pci.h"
 
-LIST_HEAD(pci_host_bridge_list);
-DECLARE_RWSEM(pci_host_bridge_sem);
-
 static struct resource busn_resource = {
 	.name	= "PCI busn",
 	.start	= 0,
@@ -18,6 +15,9 @@ static struct resource busn_resource = {
 	.flags	= IORESOURCE_BUS,
 };
 
+LIST_HEAD(pci_host_bridge_list);
+DECLARE_RWSEM(pci_host_bridge_sem);
+
 static void pci_release_host_bridge_dev(struct device *dev)
 {
 	struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
@@ -29,14 +29,12 @@ static void pci_release_host_bridge_dev(struct device *dev)
 }
 
 struct pci_host_bridge *pci_create_host_bridge(
-		struct device *parent, u32 db, 
-		struct pci_ops *ops, void *sysdata, 
-		struct list_head *resources)
+		struct device *parent, u32 db, struct pci_ops *ops, 
+		struct pci_host_info *info)
 {
 	int error;
 	struct pci_bus *b;
 	struct pci_host_bridge *host, *h;
-	struct pci_host_bridge_window *window, *n;
 
 	down_read(&pci_host_bridge_sem);
 	list_for_each_entry(h, &pci_host_bridge_list, list) {
@@ -53,7 +51,7 @@ struct pci_host_bridge *pci_create_host_bridge(
 	if (!host)
 		return NULL;
 
-	host->sysdata = sysdata;
+	host->sysdata = info->arg;
 	host->busnum = PCI_BUSNUM(db);
 	host->domain = PCI_DOMAIN(db);
 	host->ops = ops;
@@ -63,18 +61,23 @@ struct pci_host_bridge *pci_create_host_bridge(
 
 	/* this is hack, just for build, will be removed later*/
 	b = kzalloc(sizeof(*b), GFP_KERNEL);
-	b->sysdata = sysdata;
+	b->sysdata = host->sysdata;
 	pci_bus_assign_domain_nr(b, parent);
 	host->domain = pci_domain_nr(b);
+	kfree(b);
 
-	if (!resources) {
+	if (info->res_type == PCI_HOST_RES_DEFAULT) {
 		/* Use default IO/MEM/BUS resources*/
 		pci_add_resource(&host->windows, &ioport_resource);
 		pci_add_resource(&host->windows, &iomem_resource);
 		pci_add_resource(&host->windows, &busn_resource);
 	} else {
-		list_for_each_entry_safe(window, n, resources, list)
-			list_move_tail(&window->list, &host->windows);
+		if (!info->init_res || info->init_res(host, info)) {
+			pr_err("pci host %04x:%02x init resources fail\n",
+					host->domain, host->busnum);
+			kfree(host);
+			return NULL;
+		}
 	}
 
 	dev_set_name(&host->dev, "pci%04x:%02x", host->domain, 
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index d472da4..42158fd 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1863,6 +1863,21 @@ void __weak pcibios_remove_bus(struct pci_bus *bus)
 {
 }
 
+static int pci_default_init_res(struct pci_host_bridge *host,
+		struct pci_host_info *info)
+{
+	struct pci_host_bridge_window *window, *n;
+
+	if (info->res_type != PCI_HOST_RES_DEFAULT) 
+		list_for_each_entry_safe(window, n, info->resources,
+				list)
+			list_move_tail(&window->list, &host->windows);
+	else
+		info->res_type = PCI_HOST_RES_DEFAULT;
+
+	return 0;
+}
+
 struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *bridge)
 {
 	int error;
@@ -1949,13 +1964,17 @@ err_out:
 	return NULL;
 }
 
-struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
+struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
 		struct pci_ops *ops, void *sysdata, struct list_head *resources)
 {
 	struct pci_host_bridge *host;
+	struct pci_host_info info;
+	
+	info.arg= sysdata;
+	info.resources = resources;
+	info.init_res = pci_default_init_res;
 
-	host = pci_create_host_bridge(parent, bus, ops, 
-			sysdata ,resources);
+	host = pci_create_host_bridge(parent, db, ops, &info);
 	if (!host)
 		return NULL;
 
@@ -2038,8 +2057,13 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
 	bool found = false;
 	struct pci_host_bridge *host;
 	int max;
+	struct pci_host_info info;
+	
+	info.arg = sysdata;
+	info.resources = resources;
+	info.init_res = pci_default_init_res;
 
-	host = pci_create_host_bridge(parent, db, ops, sysdata, resources);
+	host = pci_create_host_bridge(parent, db, ops, &info);
 	if (!host)
 		return NULL;
 
@@ -2070,6 +2094,47 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
 }
 EXPORT_SYMBOL(pci_scan_root_bus);
 
+struct pci_host_bridge *pci_scan_host_bridge(
+		struct device *parent, u32 db, struct pci_ops *ops,
+		struct pci_host_info *info)
+{
+	struct pci_host_bridge_window *window;
+	bool found = false;
+	struct pci_host_bridge *host;
+	int max;
+
+	host = pci_create_host_bridge(parent, db, ops, info);
+	if (!host)
+		return NULL;
+
+	list_for_each_entry(window, &host->windows, list)
+		if (window->res->flags & IORESOURCE_BUS) {
+			found = true;
+			break;
+		}
+
+	host->bus = __pci_create_root_bus(host);
+	if (!host->bus) {
+		pci_free_host_bridge(host);
+		return NULL;
+	}
+
+	if (!found) {
+		dev_info(&host->bus->dev,
+		 "No busn resource found for root bus, will use [bus %02x-ff]\n",
+			host->busnum);
+		pci_bus_insert_busn_res(host->bus, host->busnum, 255);
+	}
+
+	max = pci_scan_child_bus(host->bus);
+	if (!found)
+		pci_bus_update_busn_res_end(host->bus, max);
+
+	return host;
+
+}
+EXPORT_SYMBOL(pci_scan_host_bridge);
+
 /**
  * pci_rescan_bus_bridge_resize - scan a PCI bus for devices.
  * @bridge: PCI bridge for the bus to scan
diff --git a/include/linux/pci.h b/include/linux/pci.h
index daa7f40..a51f5f5 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -412,6 +412,21 @@ struct pci_host_bridge {
 	void *release_data;
 };
 
+struct pci_host_info {
+	u8 res_type;
+	void *arg;
+	struct list_head *resources; /*just for build, will clean up later */
+	int (*init_res)(struct pci_host_bridge *host, 
+			struct pci_host_info *info);
+};
+
+static inline void init_pci_host_info(struct pci_host_info *info)
+{
+	memset(info, 0 , sizeof(*info));
+}
+
+#define PCI_HOST_RES_DEFAULT	0x2
+
 #define	to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)
 void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
 		     void (*release_fn)(struct pci_host_bridge *),
@@ -420,7 +435,7 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
 struct pci_host_bridge *pci_create_host_bridge(
 		struct device *parent, u32 db, struct pci_ops *ops, 
-		void *sys, struct list_head *resources);
+		struct pci_host_info *info);
 /*
  * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
  * to P2P or CardBus bridge windows) go in a table.  Additional ones (for
@@ -785,6 +800,9 @@ void pci_bus_release_busn_res(struct pci_bus *b);
 struct pci_bus *pci_scan_root_bus(struct device *parent, u32 bus,
 					     struct pci_ops *ops, void *sysdata,
 					     struct list_head *resources);
+struct pci_host_bridge *pci_scan_host_bridge(struct device *parent,
+		u32 db, struct pci_ops *ops,
+		struct pci_host_info *info);
 struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
 				int busnr);
 void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);
-- 
1.7.1

[RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources

From: Yijing Wang <hidden>
Date: 2014-11-17 09:43:46

From: Yijing Wang <redacted>

Pci_scan_root_bus(), pci_scan_bus() and pci_scan_bus_parented()
are very similar. But the latter two use the default
io/mem resources. Enhance pci_scan_root_bus() to support
default io/mem resources, then we could use
pci_scan_root_bus() instead of them, and clean them up.

Signed-off-by: Yijing Wang <redacted>
---
 drivers/pci/probe.c |   20 ++++++++++++++------
 1 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 5ed9930..fc99e88 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2069,15 +2069,23 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
 	struct pci_host_bridge_window *window;
 	bool found = false;
 	struct pci_bus *b;
+	LIST_HEAD(default_res);
 	int max;
 
-	list_for_each_entry(window, resources, list)
-		if (window->res->flags & IORESOURCE_BUS) {
-			found = true;
-			break;
-		}
+	if (!resources) {
+		pci_add_resource(&default_res, &ioport_resource);
+		pci_add_resource(&default_res, &iomem_resource);
+		pci_add_resource(&default_res, &busn_resource);
+	} else {
+		list_for_each_entry(window, resources, list)
+			if (window->res->flags & IORESOURCE_BUS) {
+				found = true;
+				break;
+			}
+	}
 
-	b = pci_create_root_bus(parent, bus, ops, sysdata, resources);
+	b = pci_create_root_bus(parent, bus, ops, sysdata, 
+			resources ? resources : &default_res);
 	if (!b)
 		return NULL;
 
-- 
1.7.1

[RFC PATCH 02/16] PCI: Use pci_scan_root_bus() instead of pci_scan_bus()

From: Yijing Wang <hidden>
Date: 2014-11-17 09:43:48

From: Yijing Wang <redacted>

Now we could use pci_scan_root_bus() instead of
pci_scan_bus(), pass NULL resources means use the default
io/mem.

Signed-off-by: Yijing Wang <redacted>
---
 arch/alpha/include/asm/pci.h      |    2 +-
 arch/alpha/kernel/sys_nautilus.c  |    2 +-
 arch/cris/include/asm/pci.h       |    2 +-
 arch/ia64/include/asm/pci.h       |    2 +-
 arch/m68k/coldfire/pci.c          |    2 +-
 arch/mips/include/asm/pci.h       |    2 +-
 arch/mn10300/include/asm/pci.h    |    2 +-
 arch/sh/include/asm/pci.h         |    2 +-
 arch/sparc/include/asm/pci_32.h   |    2 +-
 arch/sparc/include/asm/pci_64.h   |    2 +-
 arch/sparc/kernel/pcic.c          |    3 ++-
 arch/unicore32/kernel/pci.c       |    2 +-
 arch/x86/include/asm/pci.h        |    2 +-
 arch/x86/pci/amd_bus.c            |    2 +-
 arch/xtensa/include/asm/pci.h     |    2 +-
 drivers/parisc/dino.c             |    4 ++--
 drivers/pci/hotplug/ibmphp_core.c |    2 +-
 17 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/arch/alpha/include/asm/pci.h b/arch/alpha/include/asm/pci.h
index f7f680f..157925a 100644
--- a/arch/alpha/include/asm/pci.h
+++ b/arch/alpha/include/asm/pci.h
@@ -49,7 +49,7 @@ struct pci_controller {
 	void *sysdata;
 };
 
-/* Override the logic in pci_scan_bus for skipping already-configured
+/* Override the logic in pci_scan_root_bus for skipping already-configured
    bus numbers.  */
 
 #define pcibios_assign_all_busses()	1
diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
index 837c0fa..1047ab3 100644
--- a/arch/alpha/kernel/sys_nautilus.c
+++ b/arch/alpha/kernel/sys_nautilus.c
@@ -206,7 +206,7 @@ nautilus_init_pci(void)
 	unsigned long memtop = max_low_pfn << PAGE_SHIFT;
 
 	/* Scan our single hose.  */
-	bus = pci_scan_bus(0, alpha_mv.pci_ops, hose);
+	bus = pci_scan_root_bus(NULL, 0, alpha_mv.pci_ops, hose, NULL);
 	hose->bus = bus;
 	pcibios_claim_one_bus(bus);
 
diff --git a/arch/cris/include/asm/pci.h b/arch/cris/include/asm/pci.h
index cc2399c..96b33a6 100644
--- a/arch/cris/include/asm/pci.h
+++ b/arch/cris/include/asm/pci.h
@@ -5,7 +5,7 @@
 #ifdef __KERNEL__
 #include <linux/mm.h>		/* for struct page */
 
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
    already-configured bus numbers - to be used for buggy BIOSes
    or architectures with incomplete PCI setup by the loader */
 
diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h
index 52af5ed..64b34d6 100644
--- a/arch/ia64/include/asm/pci.h
+++ b/arch/ia64/include/asm/pci.h
@@ -20,7 +20,7 @@ struct pci_vector_struct {
 };
 
 /*
- * Can be used to override the logic in pci_scan_bus for skipping already-configured bus
+ * Can be used to override the logic in pci_scan_root_bus for skipping already-configured bus
  * numbers - to be used for buggy BIOSes or architectures with incomplete PCI setup by the
  * loader.
  */
diff --git a/arch/m68k/coldfire/pci.c b/arch/m68k/coldfire/pci.c
index df96792..4d242fb 100644
--- a/arch/m68k/coldfire/pci.c
+++ b/arch/m68k/coldfire/pci.c
@@ -312,7 +312,7 @@ static int __init mcf_pci_init(void)
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(msecs_to_jiffies(200));
 
-	rootbus = pci_scan_bus(0, &mcf_pci_ops, NULL);
+	rootbus = pci_scan_root_bus(NULL, 0, &mcf_pci_ops, NULL, NULL);
 	rootbus->resource[0] = &mcf_pci_io;
 	rootbus->resource[1] = &mcf_pci_mem;
 
diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h
index 974b0e3..212030a 100644
--- a/arch/mips/include/asm/pci.h
+++ b/arch/mips/include/asm/pci.h
@@ -60,7 +60,7 @@ extern void register_pci_controller(struct pci_controller *hose);
 extern int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
 
 
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
    already-configured bus numbers - to be used for buggy BIOSes
    or architectures with incomplete PCI setup by the loader */
 
diff --git a/arch/mn10300/include/asm/pci.h b/arch/mn10300/include/asm/pci.h
index 5f70af2..6305f14 100644
--- a/arch/mn10300/include/asm/pci.h
+++ b/arch/mn10300/include/asm/pci.h
@@ -33,7 +33,7 @@ do {							\
 #define __pcidebug(FMT, BUS, DEVFN, WHERE, ...)	do {} while (0)
 #endif
 
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
  * already-configured bus numbers - to be used for buggy BIOSes or
  * architectures with incomplete PCI setup by the loader */
 
diff --git a/arch/sh/include/asm/pci.h b/arch/sh/include/asm/pci.h
index 5b45115..69bcb78 100644
--- a/arch/sh/include/asm/pci.h
+++ b/arch/sh/include/asm/pci.h
@@ -3,7 +3,7 @@
 
 #ifdef __KERNEL__
 
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
    already-configured bus numbers - to be used for buggy BIOSes
    or architectures with incomplete PCI setup by the loader */
 
diff --git a/arch/sparc/include/asm/pci_32.h b/arch/sparc/include/asm/pci_32.h
index 53e9b49..4ef6064 100644
--- a/arch/sparc/include/asm/pci_32.h
+++ b/arch/sparc/include/asm/pci_32.h
@@ -5,7 +5,7 @@
 
 #include <linux/dma-mapping.h>
 
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
  * already-configured bus numbers - to be used for buggy BIOSes
  * or architectures with incomplete PCI setup by the loader.
  */
diff --git a/arch/sparc/include/asm/pci_64.h b/arch/sparc/include/asm/pci_64.h
index bd00a62..6e017f9 100644
--- a/arch/sparc/include/asm/pci_64.h
+++ b/arch/sparc/include/asm/pci_64.h
@@ -5,7 +5,7 @@
 
 #include <linux/dma-mapping.h>
 
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
  * already-configured bus numbers - to be used for buggy BIOSes
  * or architectures with incomplete PCI setup by the loader.
  */
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 6cc78c2..64aafac 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -390,7 +390,8 @@ static void __init pcic_pbm_scan_bus(struct linux_pcic *pcic)
 {
 	struct linux_pbm_info *pbm = &pcic->pbm;
 
-	pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, &pcic_ops, pbm);
+	pbm->pci_bus = pci_scan_root_bus(NULL, pbm->pci_first_busno, 
+			&pcic_ops, pbm, NULL);
 #if 0 /* deadwood transplanted from sparc64 */
 	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
 	pci_record_assignments(pbm, pbm->pci_bus);
diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
index 374a055..be0f261 100644
--- a/arch/unicore32/kernel/pci.c
+++ b/arch/unicore32/kernel/pci.c
@@ -258,7 +258,7 @@ static int __init pci_common_init(void)
 
 	pci_puv3_preinit();
 
-	puv3_bus = pci_scan_bus(0, &pci_puv3_ops, NULL);
+	puv3_bus = pci_scan_root_bus(NULL, 0, &pci_puv3_ops, NULL, NULL);
 
 	if (!puv3_bus)
 		panic("PCI: unable to scan bus!");
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 0892ea0..0540ff7 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -41,7 +41,7 @@ static inline int pci_proc_domain(struct pci_bus *bus)
 }
 #endif
 
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
    already-configured bus numbers - to be used for buggy BIOSes
    or architectures with incomplete PCI setup by the loader */
 
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index c20d2cc..baf6209 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -52,7 +52,7 @@ static struct pci_root_info __init *find_pci_root_info(int node, int link)
 
 /**
  * early_root_info_init()
- * called before pcibios_scan_root and pci_scan_bus
+ * called before pcibios_scan_root and pci_scan_root_bus
  * fills the mp_bus_to_cpumask array based according
  * to the LDT Bus Number Registers found in the northbridge.
  */
diff --git a/arch/xtensa/include/asm/pci.h b/arch/xtensa/include/asm/pci.h
index 5d52dc4..377fae9 100644
--- a/arch/xtensa/include/asm/pci.h
+++ b/arch/xtensa/include/asm/pci.h
@@ -13,7 +13,7 @@
 
 #ifdef __KERNEL__
 
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
  * already-configured bus numbers - to be used for buggy BIOSes
  * or architectures with incomplete PCI setup by the loader
  */
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index a0580af..67c31bd 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -74,7 +74,7 @@
 ** assigned a PCI bus number based on "when" it's discovered.
 **
 ** The "secondary" bus number is set to this before calling
-** pci_scan_bus(). If any PPB's are present, the scan will
+** pci_scan_root_bus(). If any PPB's are present, the scan will
 ** discover them and update the "secondary" and "subordinate"
 ** fields in Dino's pci_bus structure.
 **
@@ -787,7 +787,7 @@ static int __init dino_common_init(struct parisc_device *dev,
 
 	pcibios_register_hba(&dino_dev->hba);
 
-	pci_bios = &dino_bios_ops;   /* used by pci_scan_bus() */
+	pci_bios = &dino_bios_ops;   
 	pci_port = &dino_port_ops;
 
 	/*
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index 3efaf4c..b486432 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -767,7 +767,7 @@ static u8 bus_structure_fixup(u8 busno)
 					(l != 0x0000) && (l != 0xffff)) {
 			debug("%s - Inside bus_structure_fixup()\n",
 							__func__);
-			pci_scan_bus(busno, ibmphp_pci_bus->ops, NULL);
+			pci_scan_root_bus(NULL, busno, ibmphp_pci_bus->ops, NULL, NULL);
 			break;
 		}
 	}
-- 
1.7.1

[RFC PATCH 06/16] PCI: Use u32 type to combine PCI domain and bus number

From: Yijing Wang <hidden>
Date: 2014-11-17 09:43:50

Currently, we use int type for bus number in
pci_create_root_bus() and pci_scan_root_bus().
Because bus number is <= 255, so we could
change the bus number argument type to u32,
and combine PCI domain and bus number, we will
save the domain number in pci_host_bridge in
later patch, and eliminate the arch specific
pci_domain_nr().

Signed-off-by: Yijing Wang <redacted>
---
 drivers/pci/probe.c      |   11 ++++++-----
 include/linux/pci.h      |    4 ++--
 include/uapi/linux/pci.h |    3 +++
 3 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 623bfff..adf4d09 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1895,7 +1895,7 @@ void __weak pcibios_remove_bus(struct pci_bus *bus)
 {
 }
 
-struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
+struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
 		struct pci_ops *ops, void *sysdata, struct list_head *resources)
 {
 	int error;
@@ -1906,6 +1906,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 	resource_size_t offset;
 	char bus_addr[64];
 	char *fmt;
+	u8	bus = PCI_BUSNUM(db);
 
 	b = pci_alloc_bus(NULL);
 	if (!b)
@@ -2063,7 +2064,7 @@ void pci_bus_release_busn_res(struct pci_bus *b)
 			res, ret ? "can not be" : "is");
 }
 
-struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
+struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
 		struct pci_ops *ops, void *sysdata, struct list_head *resources)
 {
 	struct pci_host_bridge_window *window;
@@ -2084,7 +2085,7 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
 			}
 	}
 
-	b = pci_create_root_bus(parent, bus, ops, sysdata, 
+	b = pci_create_root_bus(parent, db, ops, sysdata, 
 			resources ? resources : &default_res);
 	if (!b)
 		return NULL;
@@ -2092,8 +2093,8 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
 	if (!found) {
 		dev_info(&b->dev,
 		 "No busn resource found for root bus, will use [bus %02x-ff]\n",
-			bus);
-		pci_bus_insert_busn_res(b, bus, 255);
+			PCI_BUSNUM(db));
+		pci_bus_insert_busn_res(b, PCI_BUSNUM(db), 255);
 	}
 
 	max = pci_scan_child_bus(b);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 4daef65..8b11b38 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -767,13 +767,13 @@ void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res,
 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 *pci_create_root_bus(struct device *parent, int bus,
+struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
 				    struct pci_ops *ops, void *sysdata,
 				    struct list_head *resources);
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
 int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
 void pci_bus_release_busn_res(struct pci_bus *b);
-struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
+struct pci_bus *pci_scan_root_bus(struct device *parent, u32 bus,
 					     struct pci_ops *ops, void *sysdata,
 					     struct list_head *resources);
 struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
diff --git a/include/uapi/linux/pci.h b/include/uapi/linux/pci.h
index 3c292bc..89c6f15 100644
--- a/include/uapi/linux/pci.h
+++ b/include/uapi/linux/pci.h
@@ -30,6 +30,9 @@
 #define PCI_DEVFN(slot, func)	((((slot) & 0x1f) << 3) | ((func) & 0x07))
 #define PCI_SLOT(devfn)		(((devfn) >> 3) & 0x1f)
 #define PCI_FUNC(devfn)		((devfn) & 0x07)
+#define PCI_DOMAIN(db)		((db) >> 16)
+#define PCI_BUSNUM(db)		((db) & 0xffff)
+#define PCI_DOMBUS(domain, bus)		(((domain) << 16) | (bus))
 
 /* Ioctls for /proc/bus/pci/X/Y nodes. */
 #define PCIIOC_BASE		('P' << 24 | 'C' << 16 | 'I' << 8)
-- 
1.7.1

Re: [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources

From: Arnd Bergmann <arnd@arndb.de>
Date: 2014-11-17 10:09:10

On Monday 17 November 2014 18:21:35 Yijing Wang wrote:
quoted hunk
-       list_for_each_entry(window, resources, list)
-               if (window->res->flags & IORESOURCE_BUS) {
-                       found = true;
-                       break;
-               }
+       if (!resources) {
+               pci_add_resource(&default_res, &ioport_resource);
+               pci_add_resource(&default_res, &iomem_resource);
+               pci_add_resource(&default_res, &busn_resource);
+       } else {
Isn't it almost always wrong to do this? You are adding all of the
I/O ports and memory to the host bridge, which will prevent you from
adding another host bridge, and the iomem_resource normally
includes a lot of addresses that are not accessible by the PCI host.

	Arnd

Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()

From: Arnd Bergmann <arnd@arndb.de>
Date: 2014-11-17 10:57:56

On Monday 17 November 2014 18:21:41 Yijing Wang wrote:
quoted hunk
There are some common PCI infos like domain, msi_controller, these
infos are saved in arch PCI sysdata, and lots arch specific functions
like pci_domain_nr() and pcibios_msi_controller() required.
We could separate pci_host_bridge creation out of pci_create_root_bus(),
then we could put the common infos in, then we could eliminate
the arch specifc functions.

Signed-off-by: Yijing Wang <redacted>
---
 drivers/pci/host-bridge.c |   99 +++++++++++++++++++++++++++++++++
 drivers/pci/probe.c       |  134 ++++++++++++++++----------------------------
 include/linux/pci.h       |   11 +++-
 3 files changed, 158 insertions(+), 86 deletions(-)
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 0e5f3c9..e31604f 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -8,6 +8,105 @@
 
 #include "pci.h"
 
+LIST_HEAD(pci_host_bridge_list);
+DECLARE_RWSEM(pci_host_bridge_sem);
Unless the pci_host_bridge_sem is accessed thousands of times per second,
it's normally better to use a simple mutex instead.
quoted hunk
+static struct resource busn_resource = {
+	.name	= "PCI busn",
+	.start	= 0,
+	.end	= 255,
+	.flags	= IORESOURCE_BUS,
+};
I think it would be better to require callers to pass the bus resource
down to the function.
quoted hunk
+struct pci_host_bridge *pci_create_host_bridge(
+		struct device *parent, u32 db, 
+		struct pci_ops *ops, void *sysdata, 
+		struct list_head *resources)
+{
Do we still need to pass the 'sysdata' in here? If we are guaranteed to
have a device pointer, we should always be able to get the driver
private data from dev_get_drvdata(host->dev->parent).
quoted hunk
+	host = kzalloc(sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return NULL;
devm_kzalloc maybe?
quoted hunk
+	if (!resources) {
+		/* Use default IO/MEM/BUS resources*/
+		pci_add_resource(&host->windows, &ioport_resource);
+		pci_add_resource(&host->windows, &iomem_resource);
+		pci_add_resource(&host->windows, &busn_resource);
+	} else {
+		list_for_each_entry_safe(window, n, resources, list)
+			list_move_tail(&window->list, &host->windows);
+	}
I think we should assume that the correct resources are passed. You
could add a wrapper around this function to convert old platforms
though.
+EXPORT_SYMBOL(pci_create_host_bridge);
EXPORT_SYMBOL_GPL() maybe?
quoted hunk
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 8b11b38..daa7f40 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -402,7 +402,12 @@ struct pci_host_bridge_window {
 struct pci_host_bridge {
 	struct device dev;
 	struct pci_bus *bus;		/* root bus */
+	struct list_head list;
 	struct list_head windows;	/* pci_host_bridge_windows */
+	int busnum;
The busnum should already be implied through the bus resource.

	Arnd

Re: [RFC PATCH 14/16] arm/PCI: Introduce pci_get_domain_nr()

From: Lorenzo Pieralisi <hidden>
Date: 2014-11-17 12:08:52

On Mon, Nov 17, 2014 at 10:21:48AM +0000, Yijing Wang wrote:
quoted hunk
Signed-off-by: Yijing Wang <redacted>
---
 arch/arm/include/asm/mach/pci.h |    9 +++++++++
 arch/arm/kernel/bios32.c        |    8 ++++++--
 2 files changed, 15 insertions(+), 2 deletions(-)
=20
diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/=
pci.h
quoted hunk
index f19f627..370b3bd 100644
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -90,6 +90,15 @@ extern void pci_map_io_early(unsigned long pfn);
 static inline void pci_map_io_early(unsigned long pfn) {}
 #endif
=20
+#ifdef CONFIG_PCI_DOMAINS_GENERIC
+int pci_get_domain_nr(struct device *parent)
+#else
+static inline int pci_get_domain_nr(struct device *parent)
+{
+=09return 0;
+}
+#endif
+
 /*
  * PCI controllers
  */
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index d8c2b4e..3fe56f1 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -513,7 +513,7 @@ static void pcibios_init_hw(struct device *parent, st=
ruct hw_pci *hw,
 #ifdef CONFIG_PCI_DOMAINS_GENERIC
 static bool dt_domain_found;
=20
-void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent=
)
quoted hunk
+int pci_get_domain_nr(struct device *parent)
 {
 =09int domain =3D of_get_pci_domain_nr(parent->of_node);
=20
@@ -526,8 +526,12 @@ void pci_bus_assign_domain_nr(struct pci_bus *bus, s=
truct device *parent)
 =09} else {
 =09=09domain =3D pci_get_new_domain_nr();
 =09}
+=09return domain;
+}
=20
-=09bus->domain_nr =3D domain;
+void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent=
)
quoted hunk
+{
+=09bus->domain_nr =3D pci_get_domain_nr(parent);
 }
 #endif
This code is superseded by the last patches I sent to move the domain
assignment to PCI core code.

http://lists.infradead.org/pipermail/linux-arm-kernel/2014-November/301220.=
html

Lorenzo

Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces

From: Arnd Bergmann <arnd@arndb.de>
Date: 2014-11-17 14:14:24

On Monday 17 November 2014 18:21:34 Yijing Wang wrote:
This series is based Linux 3.18-rc1 and Lorenzo Pieralisi's
arm PCI domain cleanup patches, link: 
https://patchwork.ozlabs.org/patch/407585/

Current pci scan interfaces like pci_scan_root_bus() and directly
call pci_create_root_bus()/pci_scan_child_bus() lack flexiblity.
Some platform infos like PCI domain and msi_chip have to be
associated to PCI bus by some arch specific function.
We want to make a generic pci_host_bridge, and make it hold
the platform infos or hook. Then we could eliminate the lots
of arch pci_domain_nr, also we could associate some platform 
ops something like pci_get_msi_chip(struct pci_dev *dev)
with pci_host_bridge to avoid introduce arch weak functions.

This RFC version not for all platforms, just applied the new
scan interface in x86/arm/powerpc/ia64, I will refresh other
platforms after the core pci scan interfaces are ok.
I think overall this is a good direction to take, in particular
moving more things into struct pci_host_bridge so we can
slim down the architecture specific code.

I don't particularly like the way you use the 'pci_host_info'
to pass callback pointers and some of the generic information.
This duplicates some of the issues we are currently trying
to untangle in the arm32 code to make drivers easier to share
between architectures.

As a general approach, I'd rather see generic helper functions
being exported by the PCI core that a driver may or may not
call. 
The way you split the interface between things that happen
before scanning the buses (pci_create_host_bridge) and
the actual scanning (__pci_create_root_bus, pci_scan_child_bus)
seems very helpful and I think we can expand that concept further:

- The normal pci_create_host_bridge() function can contain
  all of the DT scanning functions (finding bus/mem/io resources, 
  finding the msi-parent), while drivers that don't depend on DT
  for this information can call the same function and fill the
  same things after they have the pci_host_bridge pointer.

- If a driver needs to set up mapping windows, it can do that after
  calling pci_create_host_bridge(). E.g. all the dw_pcie glue drivers
  can call a dw_pcie_setup_windows() function that takes the resources
  out of the pci_host_bridge pointer before the bus is scanned.

- The ACPI code can have a completely different way of creating
  a struct pci_host_bridge, which is also passed into the same
  bus scanning functions, but doesn't have to come from
  pci_create_host_bridge.

- The PowerPC of_scan_bus function can take the same pci_host_bridge
  pointer that comes from pci_create_host_bridge(), but we'd call
  either pci_create_root_bus or of_scan_bus instead of calling
  of_scan_bus through an indirect pointer from pci_create_root_bus.

	Arnd

Re: [RFC PATCH 09/16] PCI: Associate .get_msi_ctrl() with pci_host_bridge

From: Lorenzo Pieralisi <hidden>
Date: 2014-11-17 15:03:48

On Mon, Nov 17, 2014 at 10:21:43AM +0000, Yijing Wang wrote:
quoted hunk
From: Yijing Wang <redacted>
=20
Signed-off-by: Yijing Wang <redacted>
---
 drivers/pci/host-bridge.c |    1 +
 include/linux/pci.h       |    2 ++
 2 files changed, 3 insertions(+), 0 deletions(-)
=20
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 49b6c21..872cae1 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -58,6 +58,7 @@ struct pci_host_bridge *pci_create_host_bridge(
 =09host->dev.parent =3D parent;
 =09INIT_LIST_HEAD(&host->windows);
 =09host->dev.release =3D pci_release_host_bridge_dev;
+=09host->get_msi_ctrl =3D info->get_msi_ctrl;
=20
 =09/* this is hack, just for build, will be removed later*/
 =09b =3D kzalloc(sizeof(*b), GFP_KERNEL);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index a51f5f5..af1ee86 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -408,6 +408,7 @@ struct pci_host_bridge {
 =09int domain;
 =09void *sysdata;
 =09struct pci_ops *ops;
+=09struct msi_controller *(*get_msi_ctrl)(struct pci_dev *pdev);
 =09void (*release_fn)(struct pci_host_bridge *);
 =09void *release_data;
 };
@@ -416,6 +417,7 @@ struct pci_host_info {
 =09u8 res_type;
 =09void *arg;
 =09struct list_head *resources; /*just for build, will clean up later */
+=09struct msi_controller *(*get_msi_ctrl)(struct pci_dev *pdev);
 =09int (*init_res)(struct pci_host_bridge *host,=20
 =09=09=09struct pci_host_info *info);
 };
Where would you use the get_msi_ctrl pointer then ? Wasn't it better
to wait for this patchset to take shape before adding more churn to
the ARM (and other archs) pci_sys_data structure and consequently add
another pcibios call to achieve what the get_msi_ctrl pointer is there to
achieve (ie making msi_controller retrieval arch independent ?)

I just do not see what the pci_sys_data intermediate step buys you if
we consider the approach taken in this patch as the proper solution.

Thanks,
Lorenzo

Re: [RFC PATCH 14/16] arm/PCI: Introduce pci_get_domain_nr()

From: Yijing Wang <hidden>
Date: 2014-11-18 00:55:39

quoted
 
-	bus->domain_nr = domain;
+void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
+{
+	bus->domain_nr = pci_get_domain_nr(parent);
 }
 #endif
This code is superseded by the last patches I sent to move the domain
assignment to PCI core code.

http://lists.infradead.org/pipermail/linux-arm-kernel/2014-November/301220.html
OK, I will update it based the latest one.
Lorenzo


.

-- 
Thanks!
Yijing

Re: [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources

From: Yijing Wang <hidden>
Date: 2014-11-18 07:45:12

On 2014/11/17 18:08, Arnd Bergmann wrote:
On Monday 17 November 2014 18:21:35 Yijing Wang wrote:
quoted
-       list_for_each_entry(window, resources, list)
-               if (window->res->flags & IORESOURCE_BUS) {
-                       found = true;
-                       break;
-               }
+       if (!resources) {
+               pci_add_resource(&default_res, &ioport_resource);
+               pci_add_resource(&default_res, &iomem_resource);
+               pci_add_resource(&default_res, &busn_resource);
+       } else {
Isn't it almost always wrong to do this? You are adding all of the
I/O ports and memory to the host bridge, which will prevent you from
adding another host bridge, and the iomem_resource normally
includes a lot of addresses that are not accessible by the PCI host.
Hi Arnd, pci host bridge windows are the ranges allow child devices to setup
from. Add all of IO/MEM here just a limit to child devices, no request for these
resources, so it won't hurt another host bridge. Some platforms have no dts or ACPI
report host bridge resources, in this case, we directly assign ioport/iomem_resources
as the root resources of PCI devices.

Thanks!
Yijing.
	Arnd

.

-- 
Thanks!
Yijing

Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()

From: Yijing Wang <hidden>
Date: 2014-11-18 08:32:56

quoted
+LIST_HEAD(pci_host_bridge_list);
+DECLARE_RWSEM(pci_host_bridge_sem);
Unless the pci_host_bridge_sem is accessed thousands of times per second,
it's normally better to use a simple mutex instead.
OK, I will use simple mutex instead.
quoted
+static struct resource busn_resource = {
+	.name	= "PCI busn",
+	.start	= 0,
+	.end	= 255,
+	.flags	= IORESOURCE_BUS,
+};
I think it would be better to require callers to pass the bus resource
down to the function.
Hmm, I think most of caller will provide the bus resource, but some others
will not give any bus resource, extremely, no any resources :(. But we still
need properly configure their resources for compatibility.
quoted
+struct pci_host_bridge *pci_create_host_bridge(
+		struct device *parent, u32 db, 
+		struct pci_ops *ops, void *sysdata, 
+		struct list_head *resources)
+{
Do we still need to pass the 'sysdata' in here? If we are guaranteed to
have a device pointer, we should always be able to get the driver
private data from dev_get_drvdata(host->dev->parent).
We need, some platforms pass NULL pointer as host bridge parent.
quoted
+	host = kzalloc(sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return NULL;
devm_kzalloc maybe?
I don't know much detail about devm_kzalloc(), but we have no pci host driver
here, and I found no devm_kzalloc() uses in core PCI code before.
quoted
+	if (!resources) {
+		/* Use default IO/MEM/BUS resources*/
+		pci_add_resource(&host->windows, &ioport_resource);
+		pci_add_resource(&host->windows, &iomem_resource);
+		pci_add_resource(&host->windows, &busn_resource);
+	} else {
+		list_for_each_entry_safe(window, n, resources, list)
+			list_move_tail(&window->list, &host->windows);
+	}
I think we should assume that the correct resources are passed. You
could add a wrapper around this function to convert old platforms
though.
OK, I will move these code out of pci_create_host_bridge, and add a wrapper
to setup the default resources.
quoted
+EXPORT_SYMBOL(pci_create_host_bridge);
EXPORT_SYMBOL_GPL() maybe?
OK, will update it.
quoted
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 8b11b38..daa7f40 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -402,7 +402,12 @@ struct pci_host_bridge_window {
 struct pci_host_bridge {
 	struct device dev;
 	struct pci_bus *bus;		/* root bus */
+	struct list_head list;
 	struct list_head windows;	/* pci_host_bridge_windows */
+	int busnum;
The busnum should already be implied through the bus resource.
Yes, I will consider remove it and introduce a helper function to get the root bus number, thanks!

Thanks!
Yijing.
	Arnd

.

-- 
Thanks!
Yijing

Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()

From: Arnd Bergmann <arnd@arndb.de>
Date: 2014-11-18 09:31:40

On Tuesday 18 November 2014 16:32:26 Yijing Wang wrote:
quoted
quoted
+static struct resource busn_resource = {
+	.name	= "PCI busn",
+	.start	= 0,
+	.end	= 255,
+	.flags	= IORESOURCE_BUS,
+};
I think it would be better to require callers to pass the bus resource
down to the function.
Hmm, I think most of caller will provide the bus resource, but some others
will not give any bus resource, extremely, no any resources :(. But we still
need properly configure their resources for compatibility.
I think that is what the conversion to pci_scan_bus_parented() is about:
The idea is that we add the correct bus resource to callers of
pci_scan_bus_parented or pci_scan_bus and then change them to call
pci_scan_root_bus instead.
quoted
quoted
+struct pci_host_bridge *pci_create_host_bridge(
+		struct device *parent, u32 db, 
+		struct pci_ops *ops, void *sysdata, 
+		struct list_head *resources)
+{
Do we still need to pass the 'sysdata' in here? If we are guaranteed to
have a device pointer, we should always be able to get the driver
private data from dev_get_drvdata(host->dev->parent).
We need, some platforms pass NULL pointer as host bridge parent.
But those don't have to use the new pci_create_host_bridge() function,
right?
quoted
quoted
+	host = kzalloc(sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return NULL;
devm_kzalloc maybe?
I don't know much detail about devm_kzalloc(), but we have no pci host driver
here, and I found no devm_kzalloc() uses in core PCI code before.
It also depends on having a valid device pointer. The idea is that the memory
is automatically freed if the probe() function returns with an error, or
the device driver gets unloaded. For the classic PCI hosts that are not
connected to a device, that wouldn't work of course.

	Arnd

Re: [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources

From: Arnd Bergmann <arnd@arndb.de>
Date: 2014-11-18 09:38:10

On Tuesday 18 November 2014 15:44:23 Yijing Wang wrote:
On 2014/11/17 18:08, Arnd Bergmann wrote:
quoted
On Monday 17 November 2014 18:21:35 Yijing Wang wrote:
quoted
-       list_for_each_entry(window, resources, list)
-               if (window->res->flags & IORESOURCE_BUS) {
-                       found = true;
-                       break;
-               }
+       if (!resources) {
+               pci_add_resource(&default_res, &ioport_resource);
+               pci_add_resource(&default_res, &iomem_resource);
+               pci_add_resource(&default_res, &busn_resource);
+       } else {
Isn't it almost always wrong to do this? You are adding all of the
I/O ports and memory to the host bridge, which will prevent you from
adding another host bridge, and the iomem_resource normally
includes a lot of addresses that are not accessible by the PCI host.
Hi Arnd, pci host bridge windows are the ranges allow child devices to setup
from. Add all of IO/MEM here just a limit to child devices, no request for these
resources, so it won't hurt another host bridge. Some platforms have no dts or ACPI
report host bridge resources, in this case, we directly assign ioport/iomem_resources
as the root resources of PCI devices.
But it would be wrong to allow hosts to allocate a device BAR that is not
visible through the host bridge. I think we need to keep these separate
from the general case: if you call any of the modern interfaces you have
to provide the resources and a device. I notice that there is only one
caller of pci_scan_bus_parented(), we should probably change that over to
pci_scan_root_bus() or your new interface and remove the old one, but
keep pci_scan_bus() as the only entry point for all of the legacy users
that do not know about the resources.

	Arnd

Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces

From: Yijing Wang <hidden>
Date: 2014-11-18 11:18:11

On 2014/11/17 22:13, Arnd Bergmann wrote:
On Monday 17 November 2014 18:21:34 Yijing Wang wrote:
quoted
This series is based Linux 3.18-rc1 and Lorenzo Pieralisi's
arm PCI domain cleanup patches, link: 
https://patchwork.ozlabs.org/patch/407585/

Current pci scan interfaces like pci_scan_root_bus() and directly
call pci_create_root_bus()/pci_scan_child_bus() lack flexiblity.
Some platform infos like PCI domain and msi_chip have to be
associated to PCI bus by some arch specific function.
We want to make a generic pci_host_bridge, and make it hold
the platform infos or hook. Then we could eliminate the lots
of arch pci_domain_nr, also we could associate some platform 
ops something like pci_get_msi_chip(struct pci_dev *dev)
with pci_host_bridge to avoid introduce arch weak functions.

This RFC version not for all platforms, just applied the new
scan interface in x86/arm/powerpc/ia64, I will refresh other
platforms after the core pci scan interfaces are ok.
I think overall this is a good direction to take, in particular
moving more things into struct pci_host_bridge so we can
slim down the architecture specific code.
Hi Arnd, thanks very much for your review and comments!
I don't particularly like the way you use the 'pci_host_info'
to pass callback pointers and some of the generic information.
This duplicates some of the issues we are currently trying
to untangle in the arm32 code to make drivers easier to share
between architectures.
What arm32 code you are trying to untangle for example ?

Introduce pci_host_info here because I want to make the PCI scan interfaces
simple to host drviers, host drivers only need to call one scan
interface(pci_scan_host_bridge), but from your comments,
The combination pci_create_host_bridge() + pci_scan_xx()
seems to be more popular.
As a general approach, I'd rather see generic helper functions
being exported by the PCI core that a driver may or may not
call. 
The way you split the interface between things that happen
before scanning the buses (pci_create_host_bridge) and
the actual scanning (__pci_create_root_bus, pci_scan_child_bus)
seems very helpful and I think we can expand that concept further:

- The normal pci_create_host_bridge() function can contain
  all of the DT scanning functions (finding bus/mem/io resources, 
  finding the msi-parent), while drivers that don't depend on DT
  for this information can call the same function and fill the
  same things after they have the pci_host_bridge pointer.

- If a driver needs to set up mapping windows, it can do that after
  calling pci_create_host_bridge(). E.g. all the dw_pcie glue drivers
  can call a dw_pcie_setup_windows() function that takes the resources
  out of the pci_host_bridge pointer before the bus is scanned.

- The ACPI code can have a completely different way of creating
  a struct pci_host_bridge, which is also passed into the same
  bus scanning functions, but doesn't have to come from
  pci_create_host_bridge.
I hope platforms with ACPI or DT could both use pci_create_host_bridge().
Why we need to use two different ways to process it ?
- The PowerPC of_scan_bus function can take the same pci_host_bridge
  pointer that comes from pci_create_host_bridge(), but we'd call
  either pci_create_root_bus or of_scan_bus instead of calling
  of_scan_bus through an indirect pointer from pci_create_root_bus.

	Arnd

.

-- 
Thanks!
Yijing

Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces

From: Arnd Bergmann <arnd@arndb.de>
Date: 2014-11-18 11:31:40

On Tuesday 18 November 2014 19:17:32 Yijing Wang wrote:
On 2014/11/17 22:13, Arnd Bergmann wrote:
quoted
On Monday 17 November 2014 18:21:34 Yijing Wang wrote:
quoted
This series is based Linux 3.18-rc1 and Lorenzo Pieralisi's
arm PCI domain cleanup patches, link: 
https://patchwork.ozlabs.org/patch/407585/

Current pci scan interfaces like pci_scan_root_bus() and directly
call pci_create_root_bus()/pci_scan_child_bus() lack flexiblity.
Some platform infos like PCI domain and msi_chip have to be
associated to PCI bus by some arch specific function.
We want to make a generic pci_host_bridge, and make it hold
the platform infos or hook. Then we could eliminate the lots
of arch pci_domain_nr, also we could associate some platform 
ops something like pci_get_msi_chip(struct pci_dev *dev)
with pci_host_bridge to avoid introduce arch weak functions.

This RFC version not for all platforms, just applied the new
scan interface in x86/arm/powerpc/ia64, I will refresh other
platforms after the core pci scan interfaces are ok.
I think overall this is a good direction to take, in particular
moving more things into struct pci_host_bridge so we can
slim down the architecture specific code.
Hi Arnd, thanks very much for your review and comments!
quoted
I don't particularly like the way you use the 'pci_host_info'
to pass callback pointers and some of the generic information.
This duplicates some of the issues we are currently trying
to untangle in the arm32 code to make drivers easier to share
between architectures.
What arm32 code you are trying to untangle for example ?
We have a few problems that currently prevent us from using shared
drivers across arm32 and arm64:

- arm32 has an architecture-defined pci_sys_data structure, but
  we really want to have one that is defined by the host bridge driver
  and that is architecture independent. Some core functions depend
  on this structure at the moment, which Lorenzo is trying to
  undo

- The pci_common_init interface on arm32 doesn't work well on
  loadable drivers, it does not return an error, and it is built
  around the assumption that you probe all pci host bridges at
  the same time, while the standard Linux driver model assumes
  that you probe one at a time.

- The way we pass a temporary structure (hw_pci) with function pointers
  into the architecture code makes it relatively hard to follow
  how the initialization sequence works.
 
Introduce pci_host_info here because I want to make the PCI scan interfaces
simple to host drviers, host drivers only need to call one scan
interface(pci_scan_host_bridge), but from your comments,
The combination pci_create_host_bridge() + pci_scan_xx()
seems to be more popular.
Yes, I think a simpler interface structure would be better than trying
to minimize the amount of code needed in drivers at the expense of
interface complexity.
quoted
As a general approach, I'd rather see generic helper functions
being exported by the PCI core that a driver may or may not
call. 
The way you split the interface between things that happen
before scanning the buses (pci_create_host_bridge) and
the actual scanning (__pci_create_root_bus, pci_scan_child_bus)
seems very helpful and I think we can expand that concept further:

- The normal pci_create_host_bridge() function can contain
  all of the DT scanning functions (finding bus/mem/io resources, 
  finding the msi-parent), while drivers that don't depend on DT
  for this information can call the same function and fill the
  same things after they have the pci_host_bridge pointer.

- If a driver needs to set up mapping windows, it can do that after
  calling pci_create_host_bridge(). E.g. all the dw_pcie glue drivers
  can call a dw_pcie_setup_windows() function that takes the resources
  out of the pci_host_bridge pointer before the bus is scanned.

- The ACPI code can have a completely different way of creating
  a struct pci_host_bridge, which is also passed into the same
  bus scanning functions, but doesn't have to come from
  pci_create_host_bridge.
I hope platforms with ACPI or DT could both use pci_create_host_bridge().
Why we need to use two different ways to process it ?
These are completely different use cases:

a) For DT, we want loadable device drivers that start by probing a host
   bridge device which was added through the DT platform code. The
   driver is self-contained, and eventually we want to be able to unload
   it. We have lots of different per-soc drivers that require different
   quirks

b) For ACPI, the interface is defined in the ACPI spec across architectures
   and SoCs, we don't have host bridge drivers and the code that initializes
   the PCI is required early during boot and called from architecture
   code. There is no parent device, as ACPI sees PCI as a fundamental building
   block by itself, and there are no drivers because the firmware does
   the initial hardware setup, so we only have to access the config space.

	Arnd

Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()

From: Yijing Wang <hidden>
Date: 2014-11-18 11:45:03

On 2014/11/18 17:30, Arnd Bergmann wrote:
On Tuesday 18 November 2014 16:32:26 Yijing Wang wrote:
quoted
quoted
quoted
+static struct resource busn_resource = {
+	.name	= "PCI busn",
+	.start	= 0,
+	.end	= 255,
+	.flags	= IORESOURCE_BUS,
+};
I think it would be better to require callers to pass the bus resource
down to the function.
Hmm, I think most of caller will provide the bus resource, but some others
will not give any bus resource, extremely, no any resources :(. But we still
need properly configure their resources for compatibility.
I think that is what the conversion to pci_scan_bus_parented() is about:
The idea is that we add the correct bus resource to callers of
pci_scan_bus_parented or pci_scan_bus and then change them to call
pci_scan_root_bus instead.
It looks good to me, but for simplification, or I will try to use a wrapper to
process the drivers don't pass the busnr resources, and make sure the generic
pci_create_host_bridge() always get the valid resources.
quoted
quoted
quoted
+struct pci_host_bridge *pci_create_host_bridge(
+		struct device *parent, u32 db, 
+		struct pci_ops *ops, void *sysdata, 
+		struct list_head *resources)
+{
Do we still need to pass the 'sysdata' in here? If we are guaranteed to
have a device pointer, we should always be able to get the driver
private data from dev_get_drvdata(host->dev->parent).
We need, some platforms pass NULL pointer as host bridge parent.
But those don't have to use the new pci_create_host_bridge() function,
right?
As I mentioned in another reply, I hope all pci host drivers could use
pci_create_host_bridge(), keep different PCI scan interfaces in PCI core
make things become complex.

quoted
quoted
quoted
+	host = kzalloc(sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return NULL;
devm_kzalloc maybe?
I don't know much detail about devm_kzalloc(), but we have no pci host driver
here, and I found no devm_kzalloc() uses in core PCI code before.
It also depends on having a valid device pointer. The idea is that the memory
is automatically freed if the probe() function returns with an error, or
the device driver gets unloaded. For the classic PCI hosts that are not
connected to a device, that wouldn't work of course.

	Arnd

.

-- 
Thanks!
Yijing

Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces

From: Lorenzo Pieralisi <hidden>
Date: 2014-11-18 11:45:45

On Tue, Nov 18, 2014 at 11:30:11AM +0000, Arnd Bergmann wrote:
On Tuesday 18 November 2014 19:17:32 Yijing Wang wrote:
quoted
On 2014/11/17 22:13, Arnd Bergmann wrote:
quoted
On Monday 17 November 2014 18:21:34 Yijing Wang wrote:
quoted
This series is based Linux 3.18-rc1 and Lorenzo Pieralisi's
arm PCI domain cleanup patches, link: 
https://patchwork.ozlabs.org/patch/407585/

Current pci scan interfaces like pci_scan_root_bus() and directly
call pci_create_root_bus()/pci_scan_child_bus() lack flexiblity.
Some platform infos like PCI domain and msi_chip have to be
associated to PCI bus by some arch specific function.
We want to make a generic pci_host_bridge, and make it hold
the platform infos or hook. Then we could eliminate the lots
of arch pci_domain_nr, also we could associate some platform 
ops something like pci_get_msi_chip(struct pci_dev *dev)
with pci_host_bridge to avoid introduce arch weak functions.

This RFC version not for all platforms, just applied the new
scan interface in x86/arm/powerpc/ia64, I will refresh other
platforms after the core pci scan interfaces are ok.
I think overall this is a good direction to take, in particular
moving more things into struct pci_host_bridge so we can
slim down the architecture specific code.
Hi Arnd, thanks very much for your review and comments!
quoted
I don't particularly like the way you use the 'pci_host_info'
to pass callback pointers and some of the generic information.
This duplicates some of the issues we are currently trying
to untangle in the arm32 code to make drivers easier to share
between architectures.
What arm32 code you are trying to untangle for example ?
We have a few problems that currently prevent us from using shared
drivers across arm32 and arm64:

- arm32 has an architecture-defined pci_sys_data structure, but
  we really want to have one that is defined by the host bridge driver
  and that is architecture independent. Some core functions depend
  on this structure at the moment, which Lorenzo is trying to
  undo
Yes, and on this specific point I would like to understand why we
are adding yet more pci_sys_data data in the last series that is
already in -next:

https://lkml.org/lkml/2014/10/27/85

What does this buy us ? The cover letter says already that there *is*
a better solution, why do not we work on that instead of adding more churn
to arch specific code ?

Thanks,
Lorenzo

Re: [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources

From: Yijing Wang <hidden>
Date: 2014-11-18 11:46:36

On 2014/11/18 17:36, Arnd Bergmann wrote:
On Tuesday 18 November 2014 15:44:23 Yijing Wang wrote:
quoted
On 2014/11/17 18:08, Arnd Bergmann wrote:
quoted
On Monday 17 November 2014 18:21:35 Yijing Wang wrote:
quoted
-       list_for_each_entry(window, resources, list)
-               if (window->res->flags & IORESOURCE_BUS) {
-                       found = true;
-                       break;
-               }
+       if (!resources) {
+               pci_add_resource(&default_res, &ioport_resource);
+               pci_add_resource(&default_res, &iomem_resource);
+               pci_add_resource(&default_res, &busn_resource);
+       } else {
Isn't it almost always wrong to do this? You are adding all of the
I/O ports and memory to the host bridge, which will prevent you from
adding another host bridge, and the iomem_resource normally
includes a lot of addresses that are not accessible by the PCI host.
Hi Arnd, pci host bridge windows are the ranges allow child devices to setup
from. Add all of IO/MEM here just a limit to child devices, no request for these
resources, so it won't hurt another host bridge. Some platforms have no dts or ACPI
report host bridge resources, in this case, we directly assign ioport/iomem_resources
as the root resources of PCI devices.
But it would be wrong to allow hosts to allocate a device BAR that is not
visible through the host bridge. I think we need to keep these separate
from the general case: if you call any of the modern interfaces you have
to provide the resources and a device. I notice that there is only one
caller of pci_scan_bus_parented(), we should probably change that over to
pci_scan_root_bus() or your new interface and remove the old one, but
keep pci_scan_bus() as the only entry point for all of the legacy users
that do not know about the resources.
Ok, I will move this out of the generic interface.

Thanks!
Yijing.
	Arnd

.

-- 
Thanks!
Yijing

Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces

From: Yijing Wang <hidden>
Date: 2014-11-18 12:14:57

On 2014/11/18 19:45, Lorenzo Pieralisi wrote:
On Tue, Nov 18, 2014 at 11:30:11AM +0000, Arnd Bergmann wrote:
quoted
On Tuesday 18 November 2014 19:17:32 Yijing Wang wrote:
quoted
On 2014/11/17 22:13, Arnd Bergmann wrote:
quoted
On Monday 17 November 2014 18:21:34 Yijing Wang wrote:
quoted
This series is based Linux 3.18-rc1 and Lorenzo Pieralisi's
arm PCI domain cleanup patches, link: 
https://patchwork.ozlabs.org/patch/407585/

Current pci scan interfaces like pci_scan_root_bus() and directly
call pci_create_root_bus()/pci_scan_child_bus() lack flexiblity.
Some platform infos like PCI domain and msi_chip have to be
associated to PCI bus by some arch specific function.
We want to make a generic pci_host_bridge, and make it hold
the platform infos or hook. Then we could eliminate the lots
of arch pci_domain_nr, also we could associate some platform 
ops something like pci_get_msi_chip(struct pci_dev *dev)
with pci_host_bridge to avoid introduce arch weak functions.

This RFC version not for all platforms, just applied the new
scan interface in x86/arm/powerpc/ia64, I will refresh other
platforms after the core pci scan interfaces are ok.
I think overall this is a good direction to take, in particular
moving more things into struct pci_host_bridge so we can
slim down the architecture specific code.
Hi Arnd, thanks very much for your review and comments!
quoted
I don't particularly like the way you use the 'pci_host_info'
to pass callback pointers and some of the generic information.
This duplicates some of the issues we are currently trying
to untangle in the arm32 code to make drivers easier to share
between architectures.
What arm32 code you are trying to untangle for example ?
We have a few problems that currently prevent us from using shared
drivers across arm32 and arm64:

- arm32 has an architecture-defined pci_sys_data structure, but
  we really want to have one that is defined by the host bridge driver
  and that is architecture independent. Some core functions depend
  on this structure at the moment, which Lorenzo is trying to
  undo
Yes, and on this specific point I would like to understand why we
are adding yet more pci_sys_data data in the last series that is
already in -next:

https://lkml.org/lkml/2014/10/27/85

What does this buy us ? The cover letter says already that there *is*
a better solution, why do not we work on that instead of adding more churn
to arch specific code ?
In my plan, first save msi_chip in pci_sys_data, so we could remove the lots duplicate
pcibios_add_bus(), second, make a generic pci_host_bridge, and move the msi_chip in that,
so we could eliminate all MSI arch weak functions. And in arm I think it's no need to
associate msi_chip with PCI bus, because all pci devices under the same pci host bridge
share the same msi_chip.


Thanks,
Lorenzo

.

-- 
Thanks!
Yijing

Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces

From: Yijing Wang <hidden>
Date: 2014-11-18 12:18:31

On 2014/11/18 19:30, Arnd Bergmann wrote:
On Tuesday 18 November 2014 19:17:32 Yijing Wang wrote:
quoted
On 2014/11/17 22:13, Arnd Bergmann wrote:
quoted
On Monday 17 November 2014 18:21:34 Yijing Wang wrote:
quoted
This series is based Linux 3.18-rc1 and Lorenzo Pieralisi's
arm PCI domain cleanup patches, link: 
https://patchwork.ozlabs.org/patch/407585/

Current pci scan interfaces like pci_scan_root_bus() and directly
call pci_create_root_bus()/pci_scan_child_bus() lack flexiblity.
Some platform infos like PCI domain and msi_chip have to be
associated to PCI bus by some arch specific function.
We want to make a generic pci_host_bridge, and make it hold
the platform infos or hook. Then we could eliminate the lots
of arch pci_domain_nr, also we could associate some platform 
ops something like pci_get_msi_chip(struct pci_dev *dev)
with pci_host_bridge to avoid introduce arch weak functions.

This RFC version not for all platforms, just applied the new
scan interface in x86/arm/powerpc/ia64, I will refresh other
platforms after the core pci scan interfaces are ok.
I think overall this is a good direction to take, in particular
moving more things into struct pci_host_bridge so we can
slim down the architecture specific code.
Hi Arnd, thanks very much for your review and comments!
quoted
I don't particularly like the way you use the 'pci_host_info'
to pass callback pointers and some of the generic information.
This duplicates some of the issues we are currently trying
to untangle in the arm32 code to make drivers easier to share
between architectures.
What arm32 code you are trying to untangle for example ?
We have a few problems that currently prevent us from using shared
drivers across arm32 and arm64:

- arm32 has an architecture-defined pci_sys_data structure, but
  we really want to have one that is defined by the host bridge driver
  and that is architecture independent. Some core functions depend
  on this structure at the moment, which Lorenzo is trying to
  undo

- The pci_common_init interface on arm32 doesn't work well on
  loadable drivers, it does not return an error, and it is built
  around the assumption that you probe all pci host bridges at
  the same time, while the standard Linux driver model assumes
  that you probe one at a time.

- The way we pass a temporary structure (hw_pci) with function pointers
  into the architecture code makes it relatively hard to follow
  how the initialization sequence works.
 
quoted
Introduce pci_host_info here because I want to make the PCI scan interfaces
simple to host drviers, host drivers only need to call one scan
interface(pci_scan_host_bridge), but from your comments,
The combination pci_create_host_bridge() + pci_scan_xx()
seems to be more popular.
Yes, I think a simpler interface structure would be better than trying
to minimize the amount of code needed in drivers at the expense of
interface complexity.
quoted
quoted
As a general approach, I'd rather see generic helper functions
being exported by the PCI core that a driver may or may not
call. 
The way you split the interface between things that happen
before scanning the buses (pci_create_host_bridge) and
the actual scanning (__pci_create_root_bus, pci_scan_child_bus)
seems very helpful and I think we can expand that concept further:

- The normal pci_create_host_bridge() function can contain
  all of the DT scanning functions (finding bus/mem/io resources, 
  finding the msi-parent), while drivers that don't depend on DT
  for this information can call the same function and fill the
  same things after they have the pci_host_bridge pointer.

- If a driver needs to set up mapping windows, it can do that after
  calling pci_create_host_bridge(). E.g. all the dw_pcie glue drivers
  can call a dw_pcie_setup_windows() function that takes the resources
  out of the pci_host_bridge pointer before the bus is scanned.

- The ACPI code can have a completely different way of creating
  a struct pci_host_bridge, which is also passed into the same
  bus scanning functions, but doesn't have to come from
  pci_create_host_bridge.
Thanks for your explanation, I will consider these problems when I refactor the
core generic interfaces.
quoted
I hope platforms with ACPI or DT could both use pci_create_host_bridge().
Why we need to use two different ways to process it ?
These are completely different use cases:

a) For DT, we want loadable device drivers that start by probing a host
   bridge device which was added through the DT platform code. The
   driver is self-contained, and eventually we want to be able to unload
   it. We have lots of different per-soc drivers that require different
   quirks

b) For ACPI, the interface is defined in the ACPI spec across architectures
   and SoCs, we don't have host bridge drivers and the code that initializes
   the PCI is required early during boot and called from architecture
   code. There is no parent device, as ACPI sees PCI as a fundamental building
   block by itself, and there are no drivers because the firmware does
   the initial hardware setup, so we only have to access the config space.
Hmmm, I'm a little confused, so why you think ACPI host driver should not use
pci_create_host_bridge(), because ACPI PCI driver has no parent device ?
	Arnd

.

-- 
Thanks!
Yijing

Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()

From: Arnd Bergmann <arnd@arndb.de>
Date: 2014-11-18 12:26:40

On Tuesday 18 November 2014 19:44:36 Yijing Wang wrote:
On 2014/11/18 17:30, Arnd Bergmann wrote:
quoted
On Tuesday 18 November 2014 16:32:26 Yijing Wang wrote:
quoted
quoted
quoted
+static struct resource busn_resource = {
+	.name	= "PCI busn",
+	.start	= 0,
+	.end	= 255,
+	.flags	= IORESOURCE_BUS,
+};
I think it would be better to require callers to pass the bus resource
down to the function.
Hmm, I think most of caller will provide the bus resource, but some others
will not give any bus resource, extremely, no any resources :(. But we still
need properly configure their resources for compatibility.
I think that is what the conversion to pci_scan_bus_parented() is about:
The idea is that we add the correct bus resource to callers of
pci_scan_bus_parented or pci_scan_bus and then change them to call
pci_scan_root_bus instead.
It looks good to me, but for simplification, or I will try to use a wrapper to
process the drivers don't pass the busnr resources, and make sure the generic
pci_create_host_bridge() always get the valid resources.
Ok.
 
quoted
quoted
quoted
quoted
+struct pci_host_bridge *pci_create_host_bridge(
+		struct device *parent, u32 db, 
+		struct pci_ops *ops, void *sysdata, 
+		struct list_head *resources)
+{
Do we still need to pass the 'sysdata' in here? If we are guaranteed to
have a device pointer, we should always be able to get the driver
private data from dev_get_drvdata(host->dev->parent).
We need, some platforms pass NULL pointer as host bridge parent.
But those don't have to use the new pci_create_host_bridge() function,
right?
As I mentioned in another reply, I hope all pci host drivers could use
pci_create_host_bridge(), keep different PCI scan interfaces in PCI core
make things become complex.
Doing this for all platforms that have PCI support would be a lot of
work though, I think it's better to focus on having a the best interface
for the majority of users.

	Arnd

Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces

From: Arnd Bergmann <arnd@arndb.de>
Date: 2014-11-18 12:29:01

On Tuesday 18 November 2014 20:17:57 Yijing Wang wrote:
quoted
quoted
I hope platforms with ACPI or DT could both use pci_create_host_bridge().
Why we need to use two different ways to process it ?
These are completely different use cases:

a) For DT, we want loadable device drivers that start by probing a host
   bridge device which was added through the DT platform code. The
   driver is self-contained, and eventually we want to be able to unload
   it. We have lots of different per-soc drivers that require different
   quirks

b) For ACPI, the interface is defined in the ACPI spec across architectures
   and SoCs, we don't have host bridge drivers and the code that initializes
   the PCI is required early during boot and called from architecture
   code. There is no parent device, as ACPI sees PCI as a fundamental building
   block by itself, and there are no drivers because the firmware does
   the initial hardware setup, so we only have to access the config space.
Hmmm, I'm a little confused, so why you think ACPI host driver should not use
pci_create_host_bridge(), because ACPI PCI driver has no parent device ?
It's one of the difference. Having a parent device can certainly make your
life simpler, since you have devm_kzalloc(), dev_info(), etc. Coming from
the other end, I think ACPI needs PCI to be available during early boot,
at a time where we might not want pci_create_host_bridge() to do the
right thing.

	Arnd

Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()

From: Yijing Wang <hidden>
Date: 2014-11-18 12:42:03

quoted
quoted
quoted
We need, some platforms pass NULL pointer as host bridge parent.
But those don't have to use the new pci_create_host_bridge() function,
right?
As I mentioned in another reply, I hope all pci host drivers could use
pci_create_host_bridge(), keep different PCI scan interfaces in PCI core
make things become complex.
Doing this for all platforms that have PCI support would be a lot of
work though, I think it's better to focus on having a the best interface
for the majority of users.
Yes.
	Arnd

.

-- 
Thanks!
Yijing

Re: [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources

From: Liviu Dudau <Liviu.Dudau@arm.com>
Date: 2014-11-18 14:24:06

On Tue, Nov 18, 2014 at 11:46:06AM +0000, Yijing Wang wrote:
On 2014/11/18 17:36, Arnd Bergmann wrote:
quoted
On Tuesday 18 November 2014 15:44:23 Yijing Wang wrote:
quoted
On 2014/11/17 18:08, Arnd Bergmann wrote:
quoted
On Monday 17 November 2014 18:21:35 Yijing Wang wrote:
quoted
-       list_for_each_entry(window, resources, list)
-               if (window->res->flags & IORESOURCE_BUS) {
-                       found =3D true;
-                       break;
-               }
+       if (!resources) {
+               pci_add_resource(&default_res, &ioport_resource);
+               pci_add_resource(&default_res, &iomem_resource);
+               pci_add_resource(&default_res, &busn_resource);
+       } else {
Isn't it almost always wrong to do this? You are adding all of the
I/O ports and memory to the host bridge, which will prevent you from
adding another host bridge, and the iomem_resource normally
includes a lot of addresses that are not accessible by the PCI host.
Hi Arnd, pci host bridge windows are the ranges allow child devices to=
 setup
quoted
quoted
from. Add all of IO/MEM here just a limit to child devices, no request=
 for these
quoted
quoted
resources, so it won't hurt another host bridge. Some platforms have n=
o dts or ACPI
quoted
quoted
report host bridge resources, in this case, we directly assign ioport/=
iomem_resources
quoted
quoted
as the root resources of PCI devices.
=20
But it would be wrong to allow hosts to allocate a device BAR that is n=
ot
quoted
visible through the host bridge. I think we need to keep these separate
from the general case: if you call any of the modern interfaces you hav=
e
quoted
to provide the resources and a device. I notice that there is only one
caller of pci_scan_bus_parented(), we should probably change that over =
to
quoted
pci_scan_root_bus() or your new interface and remove the old one, but
keep pci_scan_bus() as the only entry point for all of the legacy users
that do not know about the resources.
=20
Ok, I will move this out of the generic interface.
My suggestion would actually be to trigger a warning/error if you detect th=
at the resources
are missing. That way we can force the drivers to clean up.

Best regards,
Liviu
=20
Thanks!
Yijing.
=20
quoted
=20
=09Arnd
=20
.
=20
=20
=20
--=20
Thanks!
Yijing
=20
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
=20
--=20
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    =C2=AF\_(=E3=83=84)_/=C2=AF

Re: [RFC PATCH 02/16] PCI: Use pci_scan_root_bus() instead of pci_scan_bus()

From: Liviu Dudau <Liviu.Dudau@arm.com>
Date: 2014-11-18 14:28:28

On Mon, Nov 17, 2014 at 10:21:36AM +0000, Yijing Wang wrote:
From: Yijing Wang <redacted>
=20
Now we could use pci_scan_root_bus() instead of
pci_scan_bus(), pass NULL resources means use the default
io/mem.
Actually, I think this patch goes in the wrong direction. You are adding
two additional parameters that are NULL for every call you replace.
pci_scan_bus() was actually intended as a "shortcut with defaults" kind
of call so that you don't have to pass a value for parameters you don't
care about.

My suggestion would be to keep the function as is and replace the call
to pci_create_root_bus() inside with the appropriate sequence.

Best regards,
Liviu
quoted hunk
=20
Signed-off-by: Yijing Wang <redacted>
---
 arch/alpha/include/asm/pci.h      |    2 +-
 arch/alpha/kernel/sys_nautilus.c  |    2 +-
 arch/cris/include/asm/pci.h       |    2 +-
 arch/ia64/include/asm/pci.h       |    2 +-
 arch/m68k/coldfire/pci.c          |    2 +-
 arch/mips/include/asm/pci.h       |    2 +-
 arch/mn10300/include/asm/pci.h    |    2 +-
 arch/sh/include/asm/pci.h         |    2 +-
 arch/sparc/include/asm/pci_32.h   |    2 +-
 arch/sparc/include/asm/pci_64.h   |    2 +-
 arch/sparc/kernel/pcic.c          |    3 ++-
 arch/unicore32/kernel/pci.c       |    2 +-
 arch/x86/include/asm/pci.h        |    2 +-
 arch/x86/pci/amd_bus.c            |    2 +-
 arch/xtensa/include/asm/pci.h     |    2 +-
 drivers/parisc/dino.c             |    4 ++--
 drivers/pci/hotplug/ibmphp_core.c |    2 +-
 17 files changed, 19 insertions(+), 18 deletions(-)
=20
diff --git a/arch/alpha/include/asm/pci.h b/arch/alpha/include/asm/pci.h
index f7f680f..157925a 100644
--- a/arch/alpha/include/asm/pci.h
+++ b/arch/alpha/include/asm/pci.h
@@ -49,7 +49,7 @@ struct pci_controller {
 =09void *sysdata;
 };
=20
-/* Override the logic in pci_scan_bus for skipping already-configured
+/* Override the logic in pci_scan_root_bus for skipping already-configur=
ed
quoted hunk
    bus numbers.  */
=20
 #define pcibios_assign_all_busses()=091
diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nau=
tilus.c
quoted hunk
index 837c0fa..1047ab3 100644
--- a/arch/alpha/kernel/sys_nautilus.c
+++ b/arch/alpha/kernel/sys_nautilus.c
@@ -206,7 +206,7 @@ nautilus_init_pci(void)
 =09unsigned long memtop =3D max_low_pfn << PAGE_SHIFT;
=20
 =09/* Scan our single hose.  */
-=09bus =3D pci_scan_bus(0, alpha_mv.pci_ops, hose);
+=09bus =3D pci_scan_root_bus(NULL, 0, alpha_mv.pci_ops, hose, NULL);
 =09hose->bus =3D bus;
 =09pcibios_claim_one_bus(bus);
=20
diff --git a/arch/cris/include/asm/pci.h b/arch/cris/include/asm/pci.h
index cc2399c..96b33a6 100644
--- a/arch/cris/include/asm/pci.h
+++ b/arch/cris/include/asm/pci.h
@@ -5,7 +5,7 @@
 #ifdef __KERNEL__
 #include <linux/mm.h>=09=09/* for struct page */
=20
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
    already-configured bus numbers - to be used for buggy BIOSes
    or architectures with incomplete PCI setup by the loader */
=20
diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h
index 52af5ed..64b34d6 100644
--- a/arch/ia64/include/asm/pci.h
+++ b/arch/ia64/include/asm/pci.h
@@ -20,7 +20,7 @@ struct pci_vector_struct {
 };
=20
 /*
- * Can be used to override the logic in pci_scan_bus for skipping alread=
y-configured bus
+ * Can be used to override the logic in pci_scan_root_bus for skipping a=
lready-configured bus
  * numbers - to be used for buggy BIOSes or architectures with incomplet=
e PCI setup by the
quoted hunk
  * loader.
  */
diff --git a/arch/m68k/coldfire/pci.c b/arch/m68k/coldfire/pci.c
index df96792..4d242fb 100644
--- a/arch/m68k/coldfire/pci.c
+++ b/arch/m68k/coldfire/pci.c
@@ -312,7 +312,7 @@ static int __init mcf_pci_init(void)
 =09set_current_state(TASK_UNINTERRUPTIBLE);
 =09schedule_timeout(msecs_to_jiffies(200));
=20
-=09rootbus =3D pci_scan_bus(0, &mcf_pci_ops, NULL);
+=09rootbus =3D pci_scan_root_bus(NULL, 0, &mcf_pci_ops, NULL, NULL);
 =09rootbus->resource[0] =3D &mcf_pci_io;
 =09rootbus->resource[1] =3D &mcf_pci_mem;
=20
diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h
index 974b0e3..212030a 100644
--- a/arch/mips/include/asm/pci.h
+++ b/arch/mips/include/asm/pci.h
@@ -60,7 +60,7 @@ extern void register_pci_controller(struct pci_controll=
er *hose);
quoted hunk
 extern int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
=20
=20
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
    already-configured bus numbers - to be used for buggy BIOSes
    or architectures with incomplete PCI setup by the loader */
=20
diff --git a/arch/mn10300/include/asm/pci.h b/arch/mn10300/include/asm/pc=
i.h
quoted hunk
index 5f70af2..6305f14 100644
--- a/arch/mn10300/include/asm/pci.h
+++ b/arch/mn10300/include/asm/pci.h
@@ -33,7 +33,7 @@ do {=09=09=09=09=09=09=09\
 #define __pcidebug(FMT, BUS, DEVFN, WHERE, ...)=09do {} while (0)
 #endif
=20
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
  * already-configured bus numbers - to be used for buggy BIOSes or
  * architectures with incomplete PCI setup by the loader */
=20
diff --git a/arch/sh/include/asm/pci.h b/arch/sh/include/asm/pci.h
index 5b45115..69bcb78 100644
--- a/arch/sh/include/asm/pci.h
+++ b/arch/sh/include/asm/pci.h
@@ -3,7 +3,7 @@
=20
 #ifdef __KERNEL__
=20
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
    already-configured bus numbers - to be used for buggy BIOSes
    or architectures with incomplete PCI setup by the loader */
=20
diff --git a/arch/sparc/include/asm/pci_32.h b/arch/sparc/include/asm/pci=
_32.h
quoted hunk
index 53e9b49..4ef6064 100644
--- a/arch/sparc/include/asm/pci_32.h
+++ b/arch/sparc/include/asm/pci_32.h
@@ -5,7 +5,7 @@
=20
 #include <linux/dma-mapping.h>
=20
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
  * already-configured bus numbers - to be used for buggy BIOSes
  * or architectures with incomplete PCI setup by the loader.
  */
diff --git a/arch/sparc/include/asm/pci_64.h b/arch/sparc/include/asm/pci=
_64.h
quoted hunk
index bd00a62..6e017f9 100644
--- a/arch/sparc/include/asm/pci_64.h
+++ b/arch/sparc/include/asm/pci_64.h
@@ -5,7 +5,7 @@
=20
 #include <linux/dma-mapping.h>
=20
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
  * already-configured bus numbers - to be used for buggy BIOSes
  * or architectures with incomplete PCI setup by the loader.
  */
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 6cc78c2..64aafac 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -390,7 +390,8 @@ static void __init pcic_pbm_scan_bus(struct linux_pci=
c *pcic)
quoted hunk
 {
 =09struct linux_pbm_info *pbm =3D &pcic->pbm;
=20
-=09pbm->pci_bus =3D pci_scan_bus(pbm->pci_first_busno, &pcic_ops, pbm);
+=09pbm->pci_bus =3D pci_scan_root_bus(NULL, pbm->pci_first_busno,=20
+=09=09=09&pcic_ops, pbm, NULL);
 #if 0 /* deadwood transplanted from sparc64 */
 =09pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
 =09pci_record_assignments(pbm, pbm->pci_bus);
diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
index 374a055..be0f261 100644
--- a/arch/unicore32/kernel/pci.c
+++ b/arch/unicore32/kernel/pci.c
@@ -258,7 +258,7 @@ static int __init pci_common_init(void)
=20
 =09pci_puv3_preinit();
=20
-=09puv3_bus =3D pci_scan_bus(0, &pci_puv3_ops, NULL);
+=09puv3_bus =3D pci_scan_root_bus(NULL, 0, &pci_puv3_ops, NULL, NULL);
=20
 =09if (!puv3_bus)
 =09=09panic("PCI: unable to scan bus!");
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 0892ea0..0540ff7 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -41,7 +41,7 @@ static inline int pci_proc_domain(struct pci_bus *bus)
 }
 #endif
=20
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
    already-configured bus numbers - to be used for buggy BIOSes
    or architectures with incomplete PCI setup by the loader */
=20
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index c20d2cc..baf6209 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -52,7 +52,7 @@ static struct pci_root_info __init *find_pci_root_info(=
int node, int link)
quoted hunk
=20
 /**
  * early_root_info_init()
- * called before pcibios_scan_root and pci_scan_bus
+ * called before pcibios_scan_root and pci_scan_root_bus
  * fills the mp_bus_to_cpumask array based according
  * to the LDT Bus Number Registers found in the northbridge.
  */
diff --git a/arch/xtensa/include/asm/pci.h b/arch/xtensa/include/asm/pci.=
h
quoted hunk
index 5d52dc4..377fae9 100644
--- a/arch/xtensa/include/asm/pci.h
+++ b/arch/xtensa/include/asm/pci.h
@@ -13,7 +13,7 @@
=20
 #ifdef __KERNEL__
=20
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
  * already-configured bus numbers - to be used for buggy BIOSes
  * or architectures with incomplete PCI setup by the loader
  */
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index a0580af..67c31bd 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -74,7 +74,7 @@
 ** assigned a PCI bus number based on "when" it's discovered.
 **
 ** The "secondary" bus number is set to this before calling
-** pci_scan_bus(). If any PPB's are present, the scan will
+** pci_scan_root_bus(). If any PPB's are present, the scan will
 ** discover them and update the "secondary" and "subordinate"
 ** fields in Dino's pci_bus structure.
 **
@@ -787,7 +787,7 @@ static int __init dino_common_init(struct parisc_devi=
ce *dev,
quoted hunk
=20
 =09pcibios_register_hba(&dino_dev->hba);
=20
-=09pci_bios =3D &dino_bios_ops;   /* used by pci_scan_bus() */
+=09pci_bios =3D &dino_bios_ops;  =20
 =09pci_port =3D &dino_port_ops;
=20
 =09/*
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmp=
hp_core.c
quoted hunk
index 3efaf4c..b486432 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -767,7 +767,7 @@ static u8 bus_structure_fixup(u8 busno)
 =09=09=09=09=09(l !=3D 0x0000) && (l !=3D 0xffff)) {
 =09=09=09debug("%s - Inside bus_structure_fixup()\n",
 =09=09=09=09=09=09=09__func__);
-=09=09=09pci_scan_bus(busno, ibmphp_pci_bus->ops, NULL);
+=09=09=09pci_scan_root_bus(NULL, busno, ibmphp_pci_bus->ops, NULL, NULL)=
;
 =09=09=09break;
 =09=09}
 =09}
--=20
1.7.1
=20
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
=20
--=20
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    =C2=AF\_(=E3=83=84)_/=C2=AF

Re: [RFC PATCH 04/16] PCI: Rip out pci_bus_add_devices() from pci_scan_root_bus()

From: Liviu Dudau <Liviu.Dudau@arm.com>
Date: 2014-11-18 14:34:12

On Mon, Nov 17, 2014 at 10:21:38AM +0000, Yijing Wang wrote:
Rip out pci_bus_add_devices() from pci_scan_root_bus()
for following reasons.
1. pci_scan_root_bus() means we only do the scan, we should
not add pci busses.
2. A lots of drviers which use pci_scan_root_bus() call
pci_bus_size_bridges(), pci_bus_assign_resources() after
pci_scan_root_bus(). But strictly speaking pci_bus_add_devices()
should be called after the resources assignment.
This looks like a nice cleanup! Can we split this patch out
of the series and start the ball running on getting ACKs
for it? You are touching a lot of drivers here, you probably
don't want the whole series to wait on approvals for this.

Best regards,
Liviu
quoted hunk
=20
Signed-off-by: Yijing Wang <redacted>
---
 arch/alpha/kernel/pci.c           |    1 +
 arch/alpha/kernel/sys_nautilus.c  |    1 +
 arch/frv/mb93090-mb00/pci-vdk.c   |    8 +++++---
 arch/ia64/sn/kernel/io_init.c     |    2 ++
 arch/m68k/coldfire/pci.c          |    1 +
 arch/microblaze/pci/pci-common.c  |    2 +-
 arch/mips/pci/pci.c               |    1 +
 arch/mn10300/unit-asb2305/pci.c   |    7 +++++--
 arch/s390/pci/pci.c               |    2 +-
 arch/sh/drivers/pci/pci.c         |    1 +
 arch/sparc/kernel/leon_pci.c      |    1 +
 arch/sparc/kernel/pcic.c          |    2 ++
 arch/tile/kernel/pci.c            |    3 ++-
 arch/tile/kernel/pci_gx.c         |    3 ++-
 arch/unicore32/kernel/pci.c       |    2 +-
 arch/x86/pci/common.c             |   10 ++++++----
 arch/xtensa/kernel/pci.c          |    1 +
 drivers/pci/host/pci-xgene.c      |    2 +-
 drivers/pci/hotplug/ibmphp_core.c |    6 ++++--
 drivers/pci/probe.c               |    1 -
 20 files changed, 39 insertions(+), 18 deletions(-)
=20
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 076c35c..81251a5 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -349,6 +349,7 @@ common_init_pci(void)
=20
        pci_assign_unassigned_resources();
        pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
+       pci_bus_add_devices(bus);
 }
=20
=20
diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nau=
tilus.c
quoted hunk
index 1047ab3..60fbd77 100644
--- a/arch/alpha/kernel/sys_nautilus.c
+++ b/arch/alpha/kernel/sys_nautilus.c
@@ -253,6 +253,7 @@ nautilus_init_pci(void)
           for the root bus, so just clear it. */
        bus->self =3D NULL;
        pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
+       pci_bus_add_devices(bus);
 }
=20
 /*
diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-=
vdk.c
quoted hunk
index efa5d65..85f87dc 100644
--- a/arch/frv/mb93090-mb00/pci-vdk.c
+++ b/arch/frv/mb93090-mb00/pci-vdk.c
@@ -316,6 +316,7 @@ void pcibios_fixup_bus(struct pci_bus *bus)
=20
 int __init pcibios_init(void)
 {
+       struct pci_bus *bus =3D NULL;
        struct pci_ops *dir =3D NULL;
        LIST_HEAD(resources);
=20
@@ -383,12 +384,13 @@ int __init pcibios_init(void)
        printk("PCI: Probing PCI hardware\n");
        pci_add_resource(&resources, &pci_ioport_resource);
        pci_add_resource(&resources, &pci_iomem_resource);
-       pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources);
-
+       bus =3D pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources=
);
quoted hunk
+       if (!bus)
+               return -ENXIO;
        pcibios_irq_init();
        pcibios_fixup_irqs();
        pcibios_resource_survey();
-
+       pci_bus_add_devices(bus);
        return 0;
 }
=20
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.=
c
quoted hunk
index 0b5ce82..1be65eb 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -271,7 +271,9 @@ sn_pci_controller_fixup(int segment, int busnum, stru=
ct pci_bus *bus)
quoted hunk
        if (bus =3D=3D NULL) {
                kfree(res);
                kfree(controller);
+               return;
        }
+       pci_bus_add_devices(bus);
 }
=20
 /*
diff --git a/arch/m68k/coldfire/pci.c b/arch/m68k/coldfire/pci.c
index 4d242fb..840a431 100644
--- a/arch/m68k/coldfire/pci.c
+++ b/arch/m68k/coldfire/pci.c
@@ -319,6 +319,7 @@ static int __init mcf_pci_init(void)
        pci_fixup_irqs(pci_common_swizzle, mcf_pci_map_irq);
        pci_bus_size_bridges(rootbus);
        pci_bus_assign_resources(rootbus);
+       pci_bus_add_devices(rootbus);
        return 0;
 }
=20
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-c=
ommon.c
quoted hunk
index 9037914..9ca7e3f 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -1344,8 +1344,8 @@ static void pcibios_scan_phb(struct pci_controller =
*hose)
quoted hunk
        }
        bus->busn_res.start =3D hose->first_busno;
        hose->bus =3D bus;
-
        hose->last_busno =3D bus->busn_res.end;
+       pci_bus_add_devices(bus);
 }
=20
 static int __init pcibios_init(void)
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 1bf60b1..f083688 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -113,6 +113,7 @@ static void pcibios_scanbus(struct pci_controller *ho=
se)
quoted hunk
                if (!pci_has_flag(PCI_PROBE_ONLY)) {
                        pci_bus_size_bridges(bus);
                        pci_bus_assign_resources(bus);
+                       pci_bus_add_devices(bus);
                }
        }
 }
diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/=
pci.c
quoted hunk
index 6b4339f..011af54 100644
--- a/arch/mn10300/unit-asb2305/pci.c
+++ b/arch/mn10300/unit-asb2305/pci.c
@@ -345,6 +345,7 @@ void pcibios_fixup_bus(struct pci_bus *bus)
  */
 static int __init pcibios_init(void)
 {
+       struct pci_bus *bus;
        resource_size_t io_offset, mem_offset;
        LIST_HEAD(resources);
=20
@@ -376,11 +377,13 @@ static int __init pcibios_init(void)
=20
        pci_add_resource_offset(&resources, &pci_ioport_resource, io_offs=
et);
        pci_add_resource_offset(&resources, &pci_iomem_resource, mem_offs=
et);
quoted hunk
-       pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources);
-
+       bus =3D pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &reso=
urces);
quoted hunk
+       if (!bus)
+               return 0;
        pcibios_irq_init();
        pcibios_fixup_irqs();
        pcibios_resource_survey();
+       pci_bus_add_devices(bus);
        return 0;
 }
=20
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 2fa7b14..016ea48 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -755,7 +755,7 @@ static int zpci_scan_bus(struct zpci_dev *zdev)
                zpci_cleanup_bus_resources(zdev);
                return -EIO;
        }
-
+       pci_bus_add_devices(zdev->bus);
        zdev->bus->max_bus_speed =3D zdev->max_bus_speed;
        return 0;
 }
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index 1bc09ee..efc1051 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -69,6 +69,7 @@ static void pcibios_scanbus(struct pci_channel *hose)
=20
                pci_bus_size_bridges(bus);
                pci_bus_assign_resources(bus);
+               pci_bus_add_devices(bus);
        } else {
                pci_free_resource_list(&resources);
        }
diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c
index 899b720..2971076 100644
--- a/arch/sparc/kernel/leon_pci.c
+++ b/arch/sparc/kernel/leon_pci.c
@@ -40,6 +40,7 @@ void leon_pci_init(struct platform_device *ofdev, struc=
t leon_pci_info *info)
quoted hunk
=20
                /* Assign devices with resources */
                pci_assign_unassigned_resources();
+               pci_bus_add_devices(root_bus);
        } else {
                pci_free_resource_list(&resources);
        }
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 64aafac..5457814 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -392,6 +392,8 @@ static void __init pcic_pbm_scan_bus(struct linux_pci=
c *pcic)
quoted hunk
=20
        pbm->pci_bus =3D pci_scan_root_bus(NULL, pbm->pci_first_busno,
                        &pcic_ops, pbm, NULL);
+       if (pbm->pci_bus)
+               pci_bus_add_devices(pbm->pci_bus);
 #if 0 /* deadwood transplanted from sparc64 */
        pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
        pci_record_assignments(pbm, pbm->pci_bus);
diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c
index 1f80a88..268423e 100644
--- a/arch/tile/kernel/pci.c
+++ b/arch/tile/kernel/pci.c
@@ -326,7 +326,8 @@ int __init pcibios_init(void)
=20
        /* Configure the max_read_size and max_payload_size values. */
        fixup_read_and_payload_sizes();
-
+       if (bus)
+               pci_bus_add_devices(bus);
        /* Record the I/O resources in the PCI controller structure. */
        for (i =3D 0; i < TILE_NUM_PCIE; i++) {
                /*
diff --git a/arch/tile/kernel/pci_gx.c b/arch/tile/kernel/pci_gx.c
index e39f9c5..5f05a9a 100644
--- a/arch/tile/kernel/pci_gx.c
+++ b/arch/tile/kernel/pci_gx.c
@@ -903,7 +903,8 @@ int __init pcibios_init(void)
         * associated with the devices read in above.
         */
        pci_assign_unassigned_resources();
-
+       if (bus)
+               pci_bus_add_devices(bus);
        /* Record the I/O resources in the PCI controller structure. */
        for (i =3D 0; i < num_rc_controllers; i++) {
                struct pci_controller *controller =3D &pci_controllers[i]=
;
quoted hunk
diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
index be0f261..0d4c563 100644
--- a/arch/unicore32/kernel/pci.c
+++ b/arch/unicore32/kernel/pci.c
@@ -270,11 +270,11 @@ static int __init pci_common_init(void)
                 * Size the bridge windows.
                 */
                pci_bus_size_bridges(puv3_bus);
-
                /*
                 * Assign resources.
                 */
                pci_bus_assign_resources(puv3_bus);
+               pci_bus_add_devices(puv3_bus);
        }
=20
        return 0;
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 7b20bcc..b16632b 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -471,10 +471,12 @@ void pcibios_scan_root(int busnum)
        x86_pci_root_bus_resources(busnum, &resources);
        printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnu=
m);
        bus =3D pci_scan_root_bus(NULL, busnum, &pci_root_ops, sd, &resou=
rces);
quoted hunk
-       if (!bus) {
-               pci_free_resource_list(&resources);
-               kfree(sd);
-       }
+       if (bus) {
+               pci_bus_add_devices(bus);
+               return;
+       }
+       pci_free_resource_list(&resources);
+       kfree(sd);
 }
=20
 void __init pcibios_set_cache_line_size(void)
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
index 5b34033..c4b5b5d 100644
--- a/arch/xtensa/kernel/pci.c
+++ b/arch/xtensa/kernel/pci.c
@@ -185,6 +185,7 @@ static int __init pcibios_init(void)
                pci_controller_apertures(pci_ctrl, &resources);
                bus =3D pci_scan_root_bus(NULL, pci_ctrl->first_busno,
                                        pci_ctrl->ops, pci_ctrl, &resourc=
es);
quoted hunk
+               pci_bus_add_devices(bus);
                pci_ctrl->bus =3D bus;
                pci_ctrl->last_busno =3D bus->busn_res.end;
                if (next_busno <=3D pci_ctrl->last_busno)
diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c
index 9ecabfa..e7a4f66 100644
--- a/drivers/pci/host/pci-xgene.c
+++ b/drivers/pci/host/pci-xgene.c
@@ -634,7 +634,7 @@ static int xgene_pcie_probe_bridge(struct platform_de=
vice *pdev)
        bus =3D pci_scan_root_bus(&pdev->dev, 0, &xgene_pcie_ops, port, &=
res);
quoted hunk
        if (!bus)
                return -ENOMEM;
-
+       pci_bus_add_devices(bus);
        platform_set_drvdata(pdev, port);
        return 0;
 }
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmp=
hp_core.c
quoted hunk
index b486432..76ce157 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -740,7 +740,7 @@ static void ibm_unconfigure_device(struct pci_func *f=
unc)
quoted hunk
  */
 static u8 bus_structure_fixup(u8 busno)
 {
-       struct pci_bus *bus;
+       struct pci_bus *bus, *b;
        struct pci_dev *dev;
        u16 l;
=20
@@ -767,7 +767,9 @@ static u8 bus_structure_fixup(u8 busno)
                                        (l !=3D 0x0000) && (l !=3D 0xffff=
)) {
quoted hunk
                        debug("%s - Inside bus_structure_fixup()\n",
                                                        __func__);
-                       pci_scan_root_bus(NULL, busno, ibmphp_pci_bus->op=
s, NULL, NULL);
+                       b =3D pci_scan_root_bus(NULL, busno, ibmphp_pci_b=
us->ops, NULL, NULL);
quoted hunk
+                       if (b)
+                               pci_bus_add_devices(b);
                        break;
                }
        }
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 0a02fc2..97711f3 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2101,7 +2101,6 @@ struct pci_bus *pci_scan_root_bus(struct device *pa=
rent, int bus,
        if (!found)
                pci_bus_update_busn_res_end(b, max);
=20
-       pci_bus_add_devices(b);
        return b;
 }
 EXPORT_SYMBOL(pci_scan_root_bus);
--
1.7.1
=20
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
=20
--=20
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    =C2=AF\_(=E3=83=84)_/=C2=AF

Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()

From: Liviu Dudau <Liviu.Dudau@arm.com>
Date: 2014-11-18 14:49:25

On Tue, Nov 18, 2014 at 08:32:26AM +0000, Yijing Wang wrote:
=20
quoted
quoted
+LIST_HEAD(pci_host_bridge_list);
+DECLARE_RWSEM(pci_host_bridge_sem);
=20
Unless the pci_host_bridge_sem is accessed thousands of times per secon=
d,
quoted
it's normally better to use a simple mutex instead.
=20
OK, I will use simple mutex instead.
=20
quoted
=20
quoted
+static struct resource busn_resource =3D {
+=09.name=09=3D "PCI busn",
+=09.start=09=3D 0,
+=09.end=09=3D 255,
+=09.flags=09=3D IORESOURCE_BUS,
+};
=20
I think it would be better to require callers to pass the bus resource
down to the function.
=20
Hmm, I think most of caller will provide the bus resource, but some other=
s
will not give any bus resource, extremely, no any resources :(. But we st=
ill
need properly configure their resources for compatibility.
=20
quoted
=20
quoted
+struct pci_host_bridge *pci_create_host_bridge(
+=09=09struct device *parent, u32 db,=20
+=09=09struct pci_ops *ops, void *sysdata,=20
+=09=09struct list_head *resources)
+{
=20
Do we still need to pass the 'sysdata' in here? If we are guaranteed to
have a device pointer, we should always be able to get the driver
private data from dev_get_drvdata(host->dev->parent).
=20
We need, some platforms pass NULL pointer as host bridge parent.
Yijing,

May I suggest a different approach here? Rather than having to pass an opaq=
ue
pointer that gets converted by the host bridge driver back to the private
structure, what about promoting a new style of usage, that is similar to th=
e
way device drivers work? Lets try to promote the embedding of the generic
pci_host_bridge structure in the host bridge specific structure! Then we ca=
n
access the private data doing container_of().

Something like this:

struct pci_controller {
=09struct pci_host_bridge bridge;
=09/* private host bridge data here */
=09.....
};

#define PCI_CONTROLLER(bus)=09({
=09struct pci_host_bridge *hb =3D to_pci_host_bridge(bus->bridge); \
=09container_of(hb, struct pci_controller, bridge); })


Then we can retrieve the host bridge structure from everywhere we have a de=
vice.

Best regards,
Liviu
=20
quoted
=20
quoted
+=09host =3D kzalloc(sizeof(*host), GFP_KERNEL);
+=09if (!host)
+=09=09return NULL;
=20
devm_kzalloc maybe?
=20
I don't know much detail about devm_kzalloc(), but we have no pci host dr=
iver
here, and I found no devm_kzalloc() uses in core PCI code before.
=20
quoted
=20
quoted
+=09if (!resources) {
+=09=09/* Use default IO/MEM/BUS resources*/
+=09=09pci_add_resource(&host->windows, &ioport_resource);
+=09=09pci_add_resource(&host->windows, &iomem_resource);
+=09=09pci_add_resource(&host->windows, &busn_resource);
+=09} else {
+=09=09list_for_each_entry_safe(window, n, resources, list)
+=09=09=09list_move_tail(&window->list, &host->windows);
+=09}
=20
I think we should assume that the correct resources are passed. You
could add a wrapper around this function to convert old platforms
though.
=20
OK, I will move these code out of pci_create_host_bridge, and add a wrapp=
er
to setup the default resources.
=20
quoted
=20
quoted
+EXPORT_SYMBOL(pci_create_host_bridge);
=20
EXPORT_SYMBOL_GPL() maybe?
=20
OK, will update it.
=20
quoted
=20
quoted
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 8b11b38..daa7f40 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -402,7 +402,12 @@ struct pci_host_bridge_window {
 struct pci_host_bridge {
 =09struct device dev;
 =09struct pci_bus *bus;=09=09/* root bus */
+=09struct list_head list;
 =09struct list_head windows;=09/* pci_host_bridge_windows */
+=09int busnum;
=20
The busnum should already be implied through the bus resource.
=20
Yes, I will consider remove it and introduce a helper function to get the=
 root bus number, thanks!
=20
Thanks!
Yijing.
=20
quoted
=20
=09Arnd
=20
.
=20
=20
=20
--=20
Thanks!
Yijing
=20
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
=20
--=20
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    =C2=AF\_(=E3=83=84)_/=C2=AF

Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()

From: Liviu Dudau <Liviu.Dudau@arm.com>
Date: 2014-11-18 15:30:30

On Mon, Nov 17, 2014 at 10:21:41AM +0000, Yijing Wang wrote:
There are some common PCI infos like domain, msi_controller, these
infos are saved in arch PCI sysdata, and lots arch specific functions
like pci_domain_nr() and pcibios_msi_controller() required.
We could separate pci_host_bridge creation out of pci_create_root_bus(),
then we could put the common infos in, then we could eliminate
the arch specifc functions.
=20
Please Cc: Yinghai Lu and Jiang Liu on future versions.

More comments on the conversion of pci_create_root_bus():
Signed-off-by: Yijing Wang <redacted>
---
 drivers/pci/host-bridge.c |   99 +++++++++++++++++++++++++++++++++
 drivers/pci/probe.c       |  134 ++++++++++++++++-----------------------=
-----
quoted hunk
 include/linux/pci.h       |   11 +++-
 3 files changed, 158 insertions(+), 86 deletions(-)
=20
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 0e5f3c9..e31604f 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -8,6 +8,105 @@
=20
 #include "pci.h"
=20
+LIST_HEAD(pci_host_bridge_list);
+DECLARE_RWSEM(pci_host_bridge_sem);
+
+static struct resource busn_resource =3D {
+       .name   =3D "PCI busn",
+       .start  =3D 0,
+       .end    =3D 255,
+       .flags  =3D IORESOURCE_BUS,
+};
+
+static void pci_release_host_bridge_dev(struct device *dev)
+{
+       struct pci_host_bridge *bridge =3D to_pci_host_bridge(dev);
+
+       if (bridge->release_fn)
+               bridge->release_fn(bridge);
+       pci_free_resource_list(&bridge->windows);
+       kfree(bridge);
+}
+
+struct pci_host_bridge *pci_create_host_bridge(
+               struct device *parent, u32 db,
+               struct pci_ops *ops, void *sysdata,
I don't thinks it is worth moving the buses' pci_ops into pci_host_bridge. =
It
might be more useful to have pci_host_bridge specific ops here.
quoted hunk
+               struct list_head *resources)
+{
+       int error;
+       struct pci_bus *b;
+       struct pci_host_bridge *host, *h;
+       struct pci_host_bridge_window *window, *n;
+
+       down_read(&pci_host_bridge_sem);
+       list_for_each_entry(h, &pci_host_bridge_list, list) {
+               if (h->domain =3D=3D PCI_DOMAIN(db) &&
+                               h->busnum =3D=3D PCI_BUSNUM(db)) {
+                       dev_dbg(&h->dev, "pci host bridge exist\n");
+                       up_read(&pci_host_bridge_sem);
+                       return NULL;
+               }
+       }
+       up_read(&pci_host_bridge_sem);
+
+       host =3D kzalloc(sizeof(*host), GFP_KERNEL);
+       if (!host)
+               return NULL;
+
+       host->sysdata =3D sysdata;
+       host->busnum =3D PCI_BUSNUM(db);
+       host->domain =3D PCI_DOMAIN(db);
+       host->ops =3D ops;
+       host->dev.parent =3D parent;
+       INIT_LIST_HEAD(&host->windows);
+       host->dev.release =3D pci_release_host_bridge_dev;
+
+       /* this is hack, just for build, will be removed later*/
+       b =3D kzalloc(sizeof(*b), GFP_KERNEL);
+       b->sysdata =3D sysdata;
+       pci_bus_assign_domain_nr(b, parent);
+       host->domain =3D pci_domain_nr(b);
+
+       if (!resources) {
+               /* Use default IO/MEM/BUS resources*/
+               pci_add_resource(&host->windows, &ioport_resource);
+               pci_add_resource(&host->windows, &iomem_resource);
+               pci_add_resource(&host->windows, &busn_resource);
+       } else {
+               list_for_each_entry_safe(window, n, resources, list)
+                       list_move_tail(&window->list, &host->windows);
+       }
+
+       dev_set_name(&host->dev, "pci%04x:%02x", host->domain,
+                       host->busnum);
+       error =3D pcibios_root_bridge_prepare(host);
+       if(error) {
+               kfree(host);
+               return NULL;
+       }
+
+       error =3D device_register(&host->dev);
+       if (error) {
+               put_device(&host->dev);
+               return NULL;
+       }
+
+       down_write(&pci_host_bridge_sem);
+       list_add_tail(&host->list, &pci_host_bridge_list);
+       up_write(&pci_host_bridge_sem);
+       return host;
+}
+EXPORT_SYMBOL(pci_create_host_bridge);
+
+void pci_free_host_bridge(struct pci_host_bridge *host)
+{
+       down_write(&pci_host_bridge_sem);
+       list_del(&host->list);
+       up_write(&pci_host_bridge_sem);
+
+       device_unregister(&host->dev);
+}
+
 static struct pci_bus *find_pci_root_bus(struct pci_bus *bus)
 {
        while (bus->parent)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index adf4d09..d472da4 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -17,13 +17,6 @@
 #define CARDBUS_LATENCY_TIMER  176     /* secondary latency timer */
 #define CARDBUS_RESERVE_BUSNR  3
=20
-static struct resource busn_resource =3D {
-       .name   =3D "PCI busn",
-       .start  =3D 0,
-       .end    =3D 255,
-       .flags  =3D IORESOURCE_BUS,
-};
-
 /* Ugh.  Need to stop exporting this to modules. */
 LIST_HEAD(pci_root_buses);
 EXPORT_SYMBOL(pci_root_buses);
@@ -508,31 +501,6 @@ static struct pci_bus *pci_alloc_bus(struct pci_bus =
*parent)
quoted hunk
        return b;
 }
=20
-static void pci_release_host_bridge_dev(struct device *dev)
-{
-       struct pci_host_bridge *bridge =3D to_pci_host_bridge(dev);
-
-       if (bridge->release_fn)
-               bridge->release_fn(bridge);
-
-       pci_free_resource_list(&bridge->windows);
-
-       kfree(bridge);
-}
-
-static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
-{
-       struct pci_host_bridge *bridge;
-
-       bridge =3D kzalloc(sizeof(*bridge), GFP_KERNEL);
-       if (!bridge)
-               return NULL;
-
-       INIT_LIST_HEAD(&bridge->windows);
-       bridge->bus =3D b;
-       return bridge;
-}
-
 static const unsigned char pcix_bus_speed[] =3D {
        PCI_SPEED_UNKNOWN,              /* 0 */
        PCI_SPEED_66MHz_PCIX,           /* 1 */
@@ -1895,52 +1863,33 @@ void __weak pcibios_remove_bus(struct pci_bus *bu=
s)
 {
 }
=20
-struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
-               struct pci_ops *ops, void *sysdata, struct list_head *res=
ources)
+struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *bridge)
 {
        int error;
-       struct pci_host_bridge *bridge;
        struct pci_bus *b, *b2;
-       struct pci_host_bridge_window *window, *n;
+       struct pci_host_bridge_window *window;
        struct resource *res;
        resource_size_t offset;
        char bus_addr[64];
        char *fmt;
-       u8      bus =3D PCI_BUSNUM(db);
+       struct device *parent =3D bridge->dev.parent;
=20
        b =3D pci_alloc_bus(NULL);
        if (!b)
                return NULL;
=20
-       b->sysdata =3D sysdata;
-       b->ops =3D ops;
-       b->number =3D b->busn_res.start =3D bus;
+       b->sysdata =3D bridge->sysdata;
I think bridge should be the b->sysdata here.=20
+       b->ops =3D bridge->ops;
See comment above why I don't think this is necessary.
quoted hunk
+       b->number =3D b->busn_res.start =3D bridge->busnum;
        pci_bus_assign_domain_nr(b, parent);
-       b2 =3D pci_find_bus(pci_domain_nr(b), bus);
+       bridge->domain =3D pci_domain_nr(b);
Do you really want to overwrite the bridge's domain with the one from a bus=
 that
could possibly be rejected a couple of lines further down?

As an asside: if we are doing the split of pci_host_bridge from root bus cr=
eation
it is worth in my opinion to move the domain setup in pci_create_host_bridg=
e()
and stop fiddling with it here.

Otherwise it looks to me like you are heading in the right direction.

Best regards,
Liviu
quoted hunk
+       b2 =3D pci_find_bus(pci_domain_nr(b), bridge->busnum);
        if (b2) {
                /* If we already got to this bus through a different brid=
ge, ignore it */
                dev_dbg(&b2->dev, "bus already known\n");
                goto err_out;
        }
=20
-       bridge =3D pci_alloc_host_bridge(b);
-       if (!bridge)
-               goto err_out;
-
-       bridge->dev.parent =3D parent;
-       bridge->dev.release =3D pci_release_host_bridge_dev;
-       dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus)=
;
quoted hunk
-       error =3D pcibios_root_bridge_prepare(bridge);
-       if (error) {
-               kfree(bridge);
-               goto err_out;
-       }
-
-       error =3D device_register(&bridge->dev);
-       if (error) {
-               put_device(&bridge->dev);
-               goto err_out;
-       }
        b->bridge =3D get_device(&bridge->dev);
        device_enable_async_suspend(b->bridge);
        pci_set_bus_of_node(b);
@@ -1950,7 +1899,7 @@ struct pci_bus *pci_create_root_bus(struct device *=
parent, u32 db,
quoted hunk
=20
        b->dev.class =3D &pcibus_class;
        b->dev.parent =3D b->bridge;
-       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
+       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), b->number);
        error =3D device_register(&b->dev);
        if (error)
                goto class_dev_reg_err;
@@ -1966,12 +1915,11 @@ struct pci_bus *pci_create_root_bus(struct device=
 *parent, u32 db,
                printk(KERN_INFO "PCI host bridge to bus %s\n", dev_name(=
&b->dev));
quoted hunk
=20
        /* Add initial resources to the bus */
-       list_for_each_entry_safe(window, n, resources, list) {
-               list_move_tail(&window->list, &bridge->windows);
+       list_for_each_entry(window, &bridge->windows, list) {
                res =3D window->res;
                offset =3D window->offset;
                if (res->flags & IORESOURCE_BUS)
-                       pci_bus_insert_busn_res(b, bus, res->end);
+                       pci_bus_insert_busn_res(b, b->number, res->end);
                else
                        pci_bus_add_resource(b, res, 0);
                if (offset) {
@@ -2001,6 +1949,25 @@ err_out:
        return NULL;
 }
=20
+struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
+               struct pci_ops *ops, void *sysdata, struct list_head *res=
ources)
quoted hunk
+{
+       struct pci_host_bridge *host;
+
+       host =3D pci_create_host_bridge(parent, bus, ops,
+                       sysdata ,resources);
+       if (!host)
+               return NULL;
+
+       host->bus =3D __pci_create_root_bus(host);
+       if (!host->bus) {
+               pci_free_host_bridge(host);
+               return NULL;
+       }
+
+       return host->bus;
+}
+
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
 {
        struct resource *res =3D &b->busn_res;
@@ -2069,40 +2036,37 @@ struct pci_bus *pci_scan_root_bus(struct device *=
parent, u32 db,
 {
        struct pci_host_bridge_window *window;
        bool found =3D false;
-       struct pci_bus *b;
-       LIST_HEAD(default_res);
+       struct pci_host_bridge *host;
        int max;
=20
-       if (!resources) {
-               pci_add_resource(&default_res, &ioport_resource);
-               pci_add_resource(&default_res, &iomem_resource);
-               pci_add_resource(&default_res, &busn_resource);
-       } else {
-               list_for_each_entry(window, resources, list)
-                       if (window->res->flags & IORESOURCE_BUS) {
-                               found =3D true;
-                               break;
-                       }
-       }
+       host =3D pci_create_host_bridge(parent, db, ops, sysdata, resourc=
es);
+       if (!host)
+               return NULL;
=20
-       b =3D pci_create_root_bus(parent, db, ops, sysdata,
-                       resources ? resources : &default_res);
-       if (!b)
+       list_for_each_entry(window, &host->windows, list)
+               if (window->res->flags & IORESOURCE_BUS) {
+                       found =3D true;
+                       break;
+               }
+
+       host->bus =3D __pci_create_root_bus(host);
+       if (!host->bus) {
+               pci_free_host_bridge(host);
                return NULL;
+       }
=20
        if (!found) {
-               dev_info(&b->dev,
+               dev_info(&host->bus->dev,
                 "No busn resource found for root bus, will use [bus %02x=
-ff]\n",
quoted hunk
                        PCI_BUSNUM(db));
-               pci_bus_insert_busn_res(b, PCI_BUSNUM(db), 255);
+               pci_bus_insert_busn_res(host->bus, PCI_BUSNUM(db), 255);
        }
=20
-       max =3D pci_scan_child_bus(b);
-
+       max =3D pci_scan_child_bus(host->bus);
        if (!found)
-               pci_bus_update_busn_res_end(b, max);
+               pci_bus_update_busn_res_end(host->bus, max);
=20
-       return b;
+       return host->bus;
 }
 EXPORT_SYMBOL(pci_scan_root_bus);
=20
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 8b11b38..daa7f40 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -402,7 +402,12 @@ struct pci_host_bridge_window {
 struct pci_host_bridge {
        struct device dev;
        struct pci_bus *bus;            /* root bus */
+       struct list_head list;
        struct list_head windows;       /* pci_host_bridge_windows */
+       int busnum;
+       int domain;
+       void *sysdata;
+       struct pci_ops *ops;
        void (*release_fn)(struct pci_host_bridge *);
        void *release_data;
 };
@@ -413,7 +418,9 @@ void pci_set_host_bridge_release(struct pci_host_brid=
ge *bridge,
                     void *release_data);
=20
 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
-
+struct pci_host_bridge *pci_create_host_bridge(
+               struct device *parent, u32 db, struct pci_ops *ops,
+               void *sys, struct list_head *resources);
 /*
  * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that corre=
spond
  * to P2P or CardBus bridge windows) go in a table.  Additional ones (fo=
r
quoted hunk
@@ -770,6 +777,8 @@ void pci_bus_add_devices(const struct pci_bus *bus);
 struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
                                    struct pci_ops *ops, void *sysdata,
                                    struct list_head *resources);
+struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *host);
+void pci_free_host_bridge(struct pci_host_bridge *host);
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
 int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
 void pci_bus_release_busn_res(struct pci_bus *b);
--
1.7.1
=20
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
=20
--=20
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    =C2=AF\_(=E3=83=84)_/=C2=AF

Re: [RFC PATCH 08/16] PCI: Introduce pci_scan_host_bridge() and pci_host_info

From: Liviu Dudau <Liviu.Dudau@arm.com>
Date: 2014-11-18 15:42:49

On Mon, Nov 17, 2014 at 10:21:42AM +0000, Yijing Wang wrote:
From: Yijing Wang <redacted>
=20
Now pci_host_bridge has been ripped out from pci root
bus creation. Currently pci_scan_root_bus() lacks
scalability, so platform host drivers have no proper
way to configure pci_host_bridge. E.g we should assign
msi_controller to pci_host_bridge, add argument for
pci_scan_root_bus() is not a good idea, it has already
five, so introudce struct pci_host_info to make
pci scan interfaces more scalable. Because almost
all host drivers need to configure host resources,
so we put .init_res() in it first, and add other
hooks when need.
=20
Signed-off-by: Yijing Wang <redacted>
---
 drivers/pci/host-bridge.c |   27 +++++++++-------
 drivers/pci/probe.c       |   73 +++++++++++++++++++++++++++++++++++++++=
+++--
quoted hunk
 include/linux/pci.h       |   20 ++++++++++++-
 3 files changed, 103 insertions(+), 17 deletions(-)
=20
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index e31604f..49b6c21 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -8,9 +8,6 @@
=20
 #include "pci.h"
=20
-LIST_HEAD(pci_host_bridge_list);
-DECLARE_RWSEM(pci_host_bridge_sem);
-
 static struct resource busn_resource =3D {
 =09.name=09=3D "PCI busn",
 =09.start=09=3D 0,
@@ -18,6 +15,9 @@ static struct resource busn_resource =3D {
 =09.flags=09=3D IORESOURCE_BUS,
 };
=20
+LIST_HEAD(pci_host_bridge_list);
+DECLARE_RWSEM(pci_host_bridge_sem);
+
 static void pci_release_host_bridge_dev(struct device *dev)
 {
 =09struct pci_host_bridge *bridge =3D to_pci_host_bridge(dev);
@@ -29,14 +29,12 @@ static void pci_release_host_bridge_dev(struct device=
 *dev)
quoted hunk
 }
=20
 struct pci_host_bridge *pci_create_host_bridge(
-=09=09struct device *parent, u32 db,=20
-=09=09struct pci_ops *ops, void *sysdata,=20
-=09=09struct list_head *resources)
+=09=09struct device *parent, u32 db, struct pci_ops *ops,=20
+=09=09struct pci_host_info *info)
 {
 =09int error;
 =09struct pci_bus *b;
 =09struct pci_host_bridge *host, *h;
-=09struct pci_host_bridge_window *window, *n;
=20
 =09down_read(&pci_host_bridge_sem);
 =09list_for_each_entry(h, &pci_host_bridge_list, list) {
@@ -53,7 +51,7 @@ struct pci_host_bridge *pci_create_host_bridge(
 =09if (!host)
 =09=09return NULL;
=20
-=09host->sysdata =3D sysdata;
+=09host->sysdata =3D info->arg;
 =09host->busnum =3D PCI_BUSNUM(db);
 =09host->domain =3D PCI_DOMAIN(db);
 =09host->ops =3D ops;
@@ -63,18 +61,23 @@ struct pci_host_bridge *pci_create_host_bridge(
=20
 =09/* this is hack, just for build, will be removed later*/
Why do you need this hack? Just for calling pci_domain_nr() ?
quoted hunk
 =09b =3D kzalloc(sizeof(*b), GFP_KERNEL);
-=09b->sysdata =3D sysdata;
+=09b->sysdata =3D host->sysdata;
 =09pci_bus_assign_domain_nr(b, parent);
 =09host->domain =3D pci_domain_nr(b);
+=09kfree(b);
=20
-=09if (!resources) {
+=09if (info->res_type =3D=3D PCI_HOST_RES_DEFAULT) {
 =09=09/* Use default IO/MEM/BUS resources*/
 =09=09pci_add_resource(&host->windows, &ioport_resource);
 =09=09pci_add_resource(&host->windows, &iomem_resource);
 =09=09pci_add_resource(&host->windows, &busn_resource);
 =09} else {
-=09=09list_for_each_entry_safe(window, n, resources, list)
-=09=09=09list_move_tail(&window->list, &host->windows);
+=09=09if (!info->init_res || info->init_res(host, info)) {
+=09=09=09pr_err("pci host %04x:%02x init resources fail\n",
+=09=09=09=09=09host->domain, host->busnum);
+=09=09=09kfree(host);
+=09=09=09return NULL;
+=09=09}
 =09}
=20
 =09dev_set_name(&host->dev, "pci%04x:%02x", host->domain,=20
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index d472da4..42158fd 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1863,6 +1863,21 @@ void __weak pcibios_remove_bus(struct pci_bus *bus=
)
 {
 }
=20
+static int pci_default_init_res(struct pci_host_bridge *host,
+=09=09struct pci_host_info *info)
+{
+=09struct pci_host_bridge_window *window, *n;
+
+=09if (info->res_type !=3D PCI_HOST_RES_DEFAULT)=20
+=09=09list_for_each_entry_safe(window, n, info->resources,
+=09=09=09=09list)
+=09=09=09list_move_tail(&window->list, &host->windows);
+=09else
+=09=09info->res_type =3D PCI_HOST_RES_DEFAULT;
I'm confused about this assignment. Isn't this a nop as the else part
means info->res_type *is* PCI_HOST_RES_DEFAULT?
quoted hunk
+
+=09return 0;
+}
+
 struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *bridge)
 {
 =09int error;
@@ -1949,13 +1964,17 @@ err_out:
 =09return NULL;
 }
=20
-struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
+struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
 =09=09struct pci_ops *ops, void *sysdata, struct list_head *resources)
 {
 =09struct pci_host_bridge *host;
+=09struct pci_host_info info;
+=09
+=09info.arg=3D sysdata;
+=09info.resources =3D resources;
+=09info.init_res =3D pci_default_init_res;
=20
-=09host =3D pci_create_host_bridge(parent, bus, ops,=20
-=09=09=09sysdata ,resources);
+=09host =3D pci_create_host_bridge(parent, db, ops, &info);
 =09if (!host)
 =09=09return NULL;
=20
@@ -2038,8 +2057,13 @@ struct pci_bus *pci_scan_root_bus(struct device *p=
arent, u32 db,
quoted hunk
 =09bool found =3D false;
 =09struct pci_host_bridge *host;
 =09int max;
+=09struct pci_host_info info;
+=09
+=09info.arg =3D sysdata;
+=09info.resources =3D resources;
+=09info.init_res =3D pci_default_init_res;
I have mixed feelings about this patch. While it is heading in the right di=
rection
of moving pci_host_bridge relevant information towards the right user, I do=
n't think
you picked up the right set to move. The resource list is going to be copie=
d into
internal pci_host_bridge list anyway, keeping another copy is not helpful *=
and*
you have increased the code size.

I think for now we should aim to get the *missing* data into pci_host_bridg=
e: MSI
controllers and PCI domain/segment. Then we can do more cleanup.
quoted hunk
=20
-=09host =3D pci_create_host_bridge(parent, db, ops, sysdata, resources);
+=09host =3D pci_create_host_bridge(parent, db, ops, &info);
 =09if (!host)
 =09=09return NULL;
=20
@@ -2070,6 +2094,47 @@ struct pci_bus *pci_scan_root_bus(struct device *p=
arent, u32 db,
quoted hunk
 }
 EXPORT_SYMBOL(pci_scan_root_bus);
=20
+struct pci_host_bridge *pci_scan_host_bridge(
+=09=09struct device *parent, u32 db, struct pci_ops *ops,
+=09=09struct pci_host_info *info)
+{
+=09struct pci_host_bridge_window *window;
+=09bool found =3D false;
+=09struct pci_host_bridge *host;
+=09int max;
+
+=09host =3D pci_create_host_bridge(parent, db, ops, info);
+=09if (!host)
+=09=09return NULL;
+
+=09list_for_each_entry(window, &host->windows, list)
+=09=09if (window->res->flags & IORESOURCE_BUS) {
+=09=09=09found =3D true;
+=09=09=09break;
+=09=09}
+
+=09host->bus =3D __pci_create_root_bus(host);
+=09if (!host->bus) {
+=09=09pci_free_host_bridge(host);
+=09=09return NULL;
+=09}
+
+=09if (!found) {
+=09=09dev_info(&host->bus->dev,
+=09=09 "No busn resource found for root bus, will use [bus %02x-ff]\n",
+=09=09=09host->busnum);
+=09=09pci_bus_insert_busn_res(host->bus, host->busnum, 255);
+=09}
+
+=09max =3D pci_scan_child_bus(host->bus);
+=09if (!found)
+=09=09pci_bus_update_busn_res_end(host->bus, max);
+
+=09return host;
+
+}
+EXPORT_SYMBOL(pci_scan_host_bridge);
+
 /**
  * pci_rescan_bus_bridge_resize - scan a PCI bus for devices.
  * @bridge: PCI bridge for the bus to scan
diff --git a/include/linux/pci.h b/include/linux/pci.h
index daa7f40..a51f5f5 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -412,6 +412,21 @@ struct pci_host_bridge {
 =09void *release_data;
 };
=20
+struct pci_host_info {
+=09u8 res_type;
+=09void *arg;
+=09struct list_head *resources; /*just for build, will clean up later */
+=09int (*init_res)(struct pci_host_bridge *host,=20
+=09=09=09struct pci_host_info *info);
+};
+
+static inline void init_pci_host_info(struct pci_host_info *info)
+{
+=09memset(info, 0 , sizeof(*info));
+}
Where is this used?
quoted hunk
+
+#define PCI_HOST_RES_DEFAULT=090x2
+
Magic number?

Best regards,
Liviu
 #define=09to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, =
dev)
quoted hunk
 void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
 =09=09     void (*release_fn)(struct pci_host_bridge *),
@@ -420,7 +435,7 @@ void pci_set_host_bridge_release(struct pci_host_brid=
ge *bridge,
quoted hunk
 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
 struct pci_host_bridge *pci_create_host_bridge(
 =09=09struct device *parent, u32 db, struct pci_ops *ops,=20
-=09=09void *sys, struct list_head *resources);
+=09=09struct pci_host_info *info);
 /*
  * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that corre=
spond
  * to P2P or CardBus bridge windows) go in a table.  Additional ones (fo=
r
quoted hunk
@@ -785,6 +800,9 @@ void pci_bus_release_busn_res(struct pci_bus *b);
 struct pci_bus *pci_scan_root_bus(struct device *parent, u32 bus,
 =09=09=09=09=09     struct pci_ops *ops, void *sysdata,
 =09=09=09=09=09     struct list_head *resources);
+struct pci_host_bridge *pci_scan_host_bridge(struct device *parent,
+=09=09u32 db, struct pci_ops *ops,
+=09=09struct pci_host_info *info);
 struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *=
dev,
 =09=09=09=09int busnr);
 void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);
--=20
1.7.1
=20
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
=20
--=20
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    =C2=AF\_(=E3=83=84)_/=C2=AF

Re: [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources

From: Yijing Wang <hidden>
Date: 2014-11-19 01:16:15

On 2014/11/18 22:23, Liviu Dudau wrote:
On Tue, Nov 18, 2014 at 11:46:06AM +0000, Yijing Wang wrote:
quoted
On 2014/11/18 17:36, Arnd Bergmann wrote:
quoted
On Tuesday 18 November 2014 15:44:23 Yijing Wang wrote:
quoted
On 2014/11/17 18:08, Arnd Bergmann wrote:
quoted
On Monday 17 November 2014 18:21:35 Yijing Wang wrote:
quoted
-       list_for_each_entry(window, resources, list)
-               if (window->res->flags & IORESOURCE_BUS) {
-                       found = true;
-                       break;
-               }
+       if (!resources) {
+               pci_add_resource(&default_res, &ioport_resource);
+               pci_add_resource(&default_res, &iomem_resource);
+               pci_add_resource(&default_res, &busn_resource);
+       } else {
Isn't it almost always wrong to do this? You are adding all of the
I/O ports and memory to the host bridge, which will prevent you from
adding another host bridge, and the iomem_resource normally
includes a lot of addresses that are not accessible by the PCI host.
Hi Arnd, pci host bridge windows are the ranges allow child devices to setup
from. Add all of IO/MEM here just a limit to child devices, no request for these
resources, so it won't hurt another host bridge. Some platforms have no dts or ACPI
report host bridge resources, in this case, we directly assign ioport/iomem_resources
as the root resources of PCI devices.
But it would be wrong to allow hosts to allocate a device BAR that is not
visible through the host bridge. I think we need to keep these separate
from the general case: if you call any of the modern interfaces you have
to provide the resources and a device. I notice that there is only one
caller of pci_scan_bus_parented(), we should probably change that over to
pci_scan_root_bus() or your new interface and remove the old one, but
keep pci_scan_bus() as the only entry point for all of the legacy users
that do not know about the resources.
Ok, I will move this out of the generic interface.
My suggestion would actually be to trigger a warning/error if you detect that the resources
are missing. That way we can force the drivers to clean up.
It make sense to me, thanks.
Best regards,
Liviu
quoted
Thanks!
Yijing.
quoted
	Arnd

.

-- 
Thanks!
Yijing

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Thanks!
Yijing

Re: [RFC PATCH 02/16] PCI: Use pci_scan_root_bus() instead of pci_scan_bus()

From: Yijing Wang <hidden>
Date: 2014-11-19 01:19:44

On 2014/11/18 22:28, Liviu Dudau wrote:
On Mon, Nov 17, 2014 at 10:21:36AM +0000, Yijing Wang wrote:
quoted
From: Yijing Wang <redacted>

Now we could use pci_scan_root_bus() instead of
pci_scan_bus(), pass NULL resources means use the default
io/mem.
Actually, I think this patch goes in the wrong direction. You are adding
two additional parameters that are NULL for every call you replace.
pci_scan_bus() was actually intended as a "shortcut with defaults" kind
of call so that you don't have to pass a value for parameters you don't
care about.

My suggestion would be to keep the function as is and replace the call
to pci_create_root_bus() inside with the appropriate sequence.
Hmmm, maybe you are right, provide a simple pci scan interfaces
(which don't care parent and resources) is better than use a complex
one with several NULL arguments. :)

Best regards,
Liviu
quoted
Signed-off-by: Yijing Wang <redacted>
---
 arch/alpha/include/asm/pci.h      |    2 +-
 arch/alpha/kernel/sys_nautilus.c  |    2 +-
 arch/cris/include/asm/pci.h       |    2 +-
 arch/ia64/include/asm/pci.h       |    2 +-
 arch/m68k/coldfire/pci.c          |    2 +-
 arch/mips/include/asm/pci.h       |    2 +-
 arch/mn10300/include/asm/pci.h    |    2 +-
 arch/sh/include/asm/pci.h         |    2 +-
 arch/sparc/include/asm/pci_32.h   |    2 +-
 arch/sparc/include/asm/pci_64.h   |    2 +-
 arch/sparc/kernel/pcic.c          |    3 ++-
 arch/unicore32/kernel/pci.c       |    2 +-
 arch/x86/include/asm/pci.h        |    2 +-
 arch/x86/pci/amd_bus.c            |    2 +-
 arch/xtensa/include/asm/pci.h     |    2 +-
 drivers/parisc/dino.c             |    4 ++--
 drivers/pci/hotplug/ibmphp_core.c |    2 +-
 17 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/arch/alpha/include/asm/pci.h b/arch/alpha/include/asm/pci.h
index f7f680f..157925a 100644
--- a/arch/alpha/include/asm/pci.h
+++ b/arch/alpha/include/asm/pci.h
@@ -49,7 +49,7 @@ struct pci_controller {
 	void *sysdata;
 };
 
-/* Override the logic in pci_scan_bus for skipping already-configured
+/* Override the logic in pci_scan_root_bus for skipping already-configured
    bus numbers.  */
 
 #define pcibios_assign_all_busses()	1
diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
index 837c0fa..1047ab3 100644
--- a/arch/alpha/kernel/sys_nautilus.c
+++ b/arch/alpha/kernel/sys_nautilus.c
@@ -206,7 +206,7 @@ nautilus_init_pci(void)
 	unsigned long memtop = max_low_pfn << PAGE_SHIFT;
 
 	/* Scan our single hose.  */
-	bus = pci_scan_bus(0, alpha_mv.pci_ops, hose);
+	bus = pci_scan_root_bus(NULL, 0, alpha_mv.pci_ops, hose, NULL);
 	hose->bus = bus;
 	pcibios_claim_one_bus(bus);
 
diff --git a/arch/cris/include/asm/pci.h b/arch/cris/include/asm/pci.h
index cc2399c..96b33a6 100644
--- a/arch/cris/include/asm/pci.h
+++ b/arch/cris/include/asm/pci.h
@@ -5,7 +5,7 @@
 #ifdef __KERNEL__
 #include <linux/mm.h>		/* for struct page */
 
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
    already-configured bus numbers - to be used for buggy BIOSes
    or architectures with incomplete PCI setup by the loader */
 
diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h
index 52af5ed..64b34d6 100644
--- a/arch/ia64/include/asm/pci.h
+++ b/arch/ia64/include/asm/pci.h
@@ -20,7 +20,7 @@ struct pci_vector_struct {
 };
 
 /*
- * Can be used to override the logic in pci_scan_bus for skipping already-configured bus
+ * Can be used to override the logic in pci_scan_root_bus for skipping already-configured bus
  * numbers - to be used for buggy BIOSes or architectures with incomplete PCI setup by the
  * loader.
  */
diff --git a/arch/m68k/coldfire/pci.c b/arch/m68k/coldfire/pci.c
index df96792..4d242fb 100644
--- a/arch/m68k/coldfire/pci.c
+++ b/arch/m68k/coldfire/pci.c
@@ -312,7 +312,7 @@ static int __init mcf_pci_init(void)
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(msecs_to_jiffies(200));
 
-	rootbus = pci_scan_bus(0, &mcf_pci_ops, NULL);
+	rootbus = pci_scan_root_bus(NULL, 0, &mcf_pci_ops, NULL, NULL);
 	rootbus->resource[0] = &mcf_pci_io;
 	rootbus->resource[1] = &mcf_pci_mem;
 
diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h
index 974b0e3..212030a 100644
--- a/arch/mips/include/asm/pci.h
+++ b/arch/mips/include/asm/pci.h
@@ -60,7 +60,7 @@ extern void register_pci_controller(struct pci_controller *hose);
 extern int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
 
 
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
    already-configured bus numbers - to be used for buggy BIOSes
    or architectures with incomplete PCI setup by the loader */
 
diff --git a/arch/mn10300/include/asm/pci.h b/arch/mn10300/include/asm/pci.h
index 5f70af2..6305f14 100644
--- a/arch/mn10300/include/asm/pci.h
+++ b/arch/mn10300/include/asm/pci.h
@@ -33,7 +33,7 @@ do {							\
 #define __pcidebug(FMT, BUS, DEVFN, WHERE, ...)	do {} while (0)
 #endif
 
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
  * already-configured bus numbers - to be used for buggy BIOSes or
  * architectures with incomplete PCI setup by the loader */
 
diff --git a/arch/sh/include/asm/pci.h b/arch/sh/include/asm/pci.h
index 5b45115..69bcb78 100644
--- a/arch/sh/include/asm/pci.h
+++ b/arch/sh/include/asm/pci.h
@@ -3,7 +3,7 @@
 
 #ifdef __KERNEL__
 
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
    already-configured bus numbers - to be used for buggy BIOSes
    or architectures with incomplete PCI setup by the loader */
 
diff --git a/arch/sparc/include/asm/pci_32.h b/arch/sparc/include/asm/pci_32.h
index 53e9b49..4ef6064 100644
--- a/arch/sparc/include/asm/pci_32.h
+++ b/arch/sparc/include/asm/pci_32.h
@@ -5,7 +5,7 @@
 
 #include <linux/dma-mapping.h>
 
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
  * already-configured bus numbers - to be used for buggy BIOSes
  * or architectures with incomplete PCI setup by the loader.
  */
diff --git a/arch/sparc/include/asm/pci_64.h b/arch/sparc/include/asm/pci_64.h
index bd00a62..6e017f9 100644
--- a/arch/sparc/include/asm/pci_64.h
+++ b/arch/sparc/include/asm/pci_64.h
@@ -5,7 +5,7 @@
 
 #include <linux/dma-mapping.h>
 
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
  * already-configured bus numbers - to be used for buggy BIOSes
  * or architectures with incomplete PCI setup by the loader.
  */
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 6cc78c2..64aafac 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -390,7 +390,8 @@ static void __init pcic_pbm_scan_bus(struct linux_pcic *pcic)
 {
 	struct linux_pbm_info *pbm = &pcic->pbm;
 
-	pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, &pcic_ops, pbm);
+	pbm->pci_bus = pci_scan_root_bus(NULL, pbm->pci_first_busno, 
+			&pcic_ops, pbm, NULL);
 #if 0 /* deadwood transplanted from sparc64 */
 	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
 	pci_record_assignments(pbm, pbm->pci_bus);
diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
index 374a055..be0f261 100644
--- a/arch/unicore32/kernel/pci.c
+++ b/arch/unicore32/kernel/pci.c
@@ -258,7 +258,7 @@ static int __init pci_common_init(void)
 
 	pci_puv3_preinit();
 
-	puv3_bus = pci_scan_bus(0, &pci_puv3_ops, NULL);
+	puv3_bus = pci_scan_root_bus(NULL, 0, &pci_puv3_ops, NULL, NULL);
 
 	if (!puv3_bus)
 		panic("PCI: unable to scan bus!");
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 0892ea0..0540ff7 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -41,7 +41,7 @@ static inline int pci_proc_domain(struct pci_bus *bus)
 }
 #endif
 
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
    already-configured bus numbers - to be used for buggy BIOSes
    or architectures with incomplete PCI setup by the loader */
 
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index c20d2cc..baf6209 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -52,7 +52,7 @@ static struct pci_root_info __init *find_pci_root_info(int node, int link)
 
 /**
  * early_root_info_init()
- * called before pcibios_scan_root and pci_scan_bus
+ * called before pcibios_scan_root and pci_scan_root_bus
  * fills the mp_bus_to_cpumask array based according
  * to the LDT Bus Number Registers found in the northbridge.
  */
diff --git a/arch/xtensa/include/asm/pci.h b/arch/xtensa/include/asm/pci.h
index 5d52dc4..377fae9 100644
--- a/arch/xtensa/include/asm/pci.h
+++ b/arch/xtensa/include/asm/pci.h
@@ -13,7 +13,7 @@
 
 #ifdef __KERNEL__
 
-/* Can be used to override the logic in pci_scan_bus for skipping
+/* Can be used to override the logic in pci_scan_root_bus for skipping
  * already-configured bus numbers - to be used for buggy BIOSes
  * or architectures with incomplete PCI setup by the loader
  */
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index a0580af..67c31bd 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -74,7 +74,7 @@
 ** assigned a PCI bus number based on "when" it's discovered.
 **
 ** The "secondary" bus number is set to this before calling
-** pci_scan_bus(). If any PPB's are present, the scan will
+** pci_scan_root_bus(). If any PPB's are present, the scan will
 ** discover them and update the "secondary" and "subordinate"
 ** fields in Dino's pci_bus structure.
 **
@@ -787,7 +787,7 @@ static int __init dino_common_init(struct parisc_device *dev,
 
 	pcibios_register_hba(&dino_dev->hba);
 
-	pci_bios = &dino_bios_ops;   /* used by pci_scan_bus() */
+	pci_bios = &dino_bios_ops;   
 	pci_port = &dino_port_ops;
 
 	/*
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index 3efaf4c..b486432 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -767,7 +767,7 @@ static u8 bus_structure_fixup(u8 busno)
 					(l != 0x0000) && (l != 0xffff)) {
 			debug("%s - Inside bus_structure_fixup()\n",
 							__func__);
-			pci_scan_bus(busno, ibmphp_pci_bus->ops, NULL);
+			pci_scan_root_bus(NULL, busno, ibmphp_pci_bus->ops, NULL, NULL);
 			break;
 		}
 	}
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Thanks!
Yijing

Re: [RFC PATCH 04/16] PCI: Rip out pci_bus_add_devices() from pci_scan_root_bus()

From: Yijing Wang <hidden>
Date: 2014-11-19 01:21:49

On 2014/11/18 22:34, Liviu Dudau wrote:
On Mon, Nov 17, 2014 at 10:21:38AM +0000, Yijing Wang wrote:
quoted
Rip out pci_bus_add_devices() from pci_scan_root_bus()
for following reasons.
1. pci_scan_root_bus() means we only do the scan, we should
not add pci busses.
2. A lots of drviers which use pci_scan_root_bus() call
pci_bus_size_bridges(), pci_bus_assign_resources() after
pci_scan_root_bus(). But strictly speaking pci_bus_add_devices()
should be called after the resources assignment.
This looks like a nice cleanup! Can we split this patch out
of the series and start the ball running on getting ACKs
for it? You are touching a lot of drivers here, you probably
don't want the whole series to wait on approvals for this.
OK, I will separately this one out of this series.
Best regards,
Liviu
quoted
Signed-off-by: Yijing Wang <redacted>
---
 arch/alpha/kernel/pci.c           |    1 +
 arch/alpha/kernel/sys_nautilus.c  |    1 +
 arch/frv/mb93090-mb00/pci-vdk.c   |    8 +++++---
 arch/ia64/sn/kernel/io_init.c     |    2 ++
 arch/m68k/coldfire/pci.c          |    1 +
 arch/microblaze/pci/pci-common.c  |    2 +-
 arch/mips/pci/pci.c               |    1 +
 arch/mn10300/unit-asb2305/pci.c   |    7 +++++--
 arch/s390/pci/pci.c               |    2 +-
 arch/sh/drivers/pci/pci.c         |    1 +
 arch/sparc/kernel/leon_pci.c      |    1 +
 arch/sparc/kernel/pcic.c          |    2 ++
 arch/tile/kernel/pci.c            |    3 ++-
 arch/tile/kernel/pci_gx.c         |    3 ++-
 arch/unicore32/kernel/pci.c       |    2 +-
 arch/x86/pci/common.c             |   10 ++++++----
 arch/xtensa/kernel/pci.c          |    1 +
 drivers/pci/host/pci-xgene.c      |    2 +-
 drivers/pci/hotplug/ibmphp_core.c |    6 ++++--
 drivers/pci/probe.c               |    1 -
 20 files changed, 39 insertions(+), 18 deletions(-)
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 076c35c..81251a5 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -349,6 +349,7 @@ common_init_pci(void)

        pci_assign_unassigned_resources();
        pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
+       pci_bus_add_devices(bus);
 }

diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
index 1047ab3..60fbd77 100644
--- a/arch/alpha/kernel/sys_nautilus.c
+++ b/arch/alpha/kernel/sys_nautilus.c
@@ -253,6 +253,7 @@ nautilus_init_pci(void)
           for the root bus, so just clear it. */
        bus->self = NULL;
        pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
+       pci_bus_add_devices(bus);
 }

 /*
diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c
index efa5d65..85f87dc 100644
--- a/arch/frv/mb93090-mb00/pci-vdk.c
+++ b/arch/frv/mb93090-mb00/pci-vdk.c
@@ -316,6 +316,7 @@ void pcibios_fixup_bus(struct pci_bus *bus)

 int __init pcibios_init(void)
 {
+       struct pci_bus *bus = NULL;
        struct pci_ops *dir = NULL;
        LIST_HEAD(resources);
@@ -383,12 +384,13 @@ int __init pcibios_init(void)
        printk("PCI: Probing PCI hardware\n");
        pci_add_resource(&resources, &pci_ioport_resource);
        pci_add_resource(&resources, &pci_iomem_resource);
-       pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources);
-
+       bus = pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources);
+       if (!bus)
+               return -ENXIO;
        pcibios_irq_init();
        pcibios_fixup_irqs();
        pcibios_resource_survey();
-
+       pci_bus_add_devices(bus);
        return 0;
 }
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index 0b5ce82..1be65eb 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -271,7 +271,9 @@ sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
        if (bus == NULL) {
                kfree(res);
                kfree(controller);
+               return;
        }
+       pci_bus_add_devices(bus);
 }

 /*
diff --git a/arch/m68k/coldfire/pci.c b/arch/m68k/coldfire/pci.c
index 4d242fb..840a431 100644
--- a/arch/m68k/coldfire/pci.c
+++ b/arch/m68k/coldfire/pci.c
@@ -319,6 +319,7 @@ static int __init mcf_pci_init(void)
        pci_fixup_irqs(pci_common_swizzle, mcf_pci_map_irq);
        pci_bus_size_bridges(rootbus);
        pci_bus_assign_resources(rootbus);
+       pci_bus_add_devices(rootbus);
        return 0;
 }
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index 9037914..9ca7e3f 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -1344,8 +1344,8 @@ static void pcibios_scan_phb(struct pci_controller *hose)
        }
        bus->busn_res.start = hose->first_busno;
        hose->bus = bus;
-
        hose->last_busno = bus->busn_res.end;
+       pci_bus_add_devices(bus);
 }

 static int __init pcibios_init(void)
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 1bf60b1..f083688 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -113,6 +113,7 @@ static void pcibios_scanbus(struct pci_controller *hose)
                if (!pci_has_flag(PCI_PROBE_ONLY)) {
                        pci_bus_size_bridges(bus);
                        pci_bus_assign_resources(bus);
+                       pci_bus_add_devices(bus);
                }
        }
 }
diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c
index 6b4339f..011af54 100644
--- a/arch/mn10300/unit-asb2305/pci.c
+++ b/arch/mn10300/unit-asb2305/pci.c
@@ -345,6 +345,7 @@ void pcibios_fixup_bus(struct pci_bus *bus)
  */
 static int __init pcibios_init(void)
 {
+       struct pci_bus *bus;
        resource_size_t io_offset, mem_offset;
        LIST_HEAD(resources);
@@ -376,11 +377,13 @@ static int __init pcibios_init(void)

        pci_add_resource_offset(&resources, &pci_ioport_resource, io_offset);
        pci_add_resource_offset(&resources, &pci_iomem_resource, mem_offset);
-       pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources);
-
+       bus = pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources);
+       if (!bus)
+               return 0;
        pcibios_irq_init();
        pcibios_fixup_irqs();
        pcibios_resource_survey();
+       pci_bus_add_devices(bus);
        return 0;
 }
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 2fa7b14..016ea48 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -755,7 +755,7 @@ static int zpci_scan_bus(struct zpci_dev *zdev)
                zpci_cleanup_bus_resources(zdev);
                return -EIO;
        }
-
+       pci_bus_add_devices(zdev->bus);
        zdev->bus->max_bus_speed = zdev->max_bus_speed;
        return 0;
 }
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index 1bc09ee..efc1051 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -69,6 +69,7 @@ static void pcibios_scanbus(struct pci_channel *hose)

                pci_bus_size_bridges(bus);
                pci_bus_assign_resources(bus);
+               pci_bus_add_devices(bus);
        } else {
                pci_free_resource_list(&resources);
        }
diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c
index 899b720..2971076 100644
--- a/arch/sparc/kernel/leon_pci.c
+++ b/arch/sparc/kernel/leon_pci.c
@@ -40,6 +40,7 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)

                /* Assign devices with resources */
                pci_assign_unassigned_resources();
+               pci_bus_add_devices(root_bus);
        } else {
                pci_free_resource_list(&resources);
        }
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 64aafac..5457814 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -392,6 +392,8 @@ static void __init pcic_pbm_scan_bus(struct linux_pcic *pcic)

        pbm->pci_bus = pci_scan_root_bus(NULL, pbm->pci_first_busno,
                        &pcic_ops, pbm, NULL);
+       if (pbm->pci_bus)
+               pci_bus_add_devices(pbm->pci_bus);
 #if 0 /* deadwood transplanted from sparc64 */
        pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
        pci_record_assignments(pbm, pbm->pci_bus);
diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c
index 1f80a88..268423e 100644
--- a/arch/tile/kernel/pci.c
+++ b/arch/tile/kernel/pci.c
@@ -326,7 +326,8 @@ int __init pcibios_init(void)

        /* Configure the max_read_size and max_payload_size values. */
        fixup_read_and_payload_sizes();
-
+       if (bus)
+               pci_bus_add_devices(bus);
        /* Record the I/O resources in the PCI controller structure. */
        for (i = 0; i < TILE_NUM_PCIE; i++) {
                /*
diff --git a/arch/tile/kernel/pci_gx.c b/arch/tile/kernel/pci_gx.c
index e39f9c5..5f05a9a 100644
--- a/arch/tile/kernel/pci_gx.c
+++ b/arch/tile/kernel/pci_gx.c
@@ -903,7 +903,8 @@ int __init pcibios_init(void)
         * associated with the devices read in above.
         */
        pci_assign_unassigned_resources();
-
+       if (bus)
+               pci_bus_add_devices(bus);
        /* Record the I/O resources in the PCI controller structure. */
        for (i = 0; i < num_rc_controllers; i++) {
                struct pci_controller *controller = &pci_controllers[i];
diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
index be0f261..0d4c563 100644
--- a/arch/unicore32/kernel/pci.c
+++ b/arch/unicore32/kernel/pci.c
@@ -270,11 +270,11 @@ static int __init pci_common_init(void)
                 * Size the bridge windows.
                 */
                pci_bus_size_bridges(puv3_bus);
-
                /*
                 * Assign resources.
                 */
                pci_bus_assign_resources(puv3_bus);
+               pci_bus_add_devices(puv3_bus);
        }

        return 0;
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 7b20bcc..b16632b 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -471,10 +471,12 @@ void pcibios_scan_root(int busnum)
        x86_pci_root_bus_resources(busnum, &resources);
        printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
        bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, sd, &resources);
-       if (!bus) {
-               pci_free_resource_list(&resources);
-               kfree(sd);
-       }
+       if (bus) {
+               pci_bus_add_devices(bus);
+               return;
+       }
+       pci_free_resource_list(&resources);
+       kfree(sd);
 }

 void __init pcibios_set_cache_line_size(void)
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
index 5b34033..c4b5b5d 100644
--- a/arch/xtensa/kernel/pci.c
+++ b/arch/xtensa/kernel/pci.c
@@ -185,6 +185,7 @@ static int __init pcibios_init(void)
                pci_controller_apertures(pci_ctrl, &resources);
                bus = pci_scan_root_bus(NULL, pci_ctrl->first_busno,
                                        pci_ctrl->ops, pci_ctrl, &resources);
+               pci_bus_add_devices(bus);
                pci_ctrl->bus = bus;
                pci_ctrl->last_busno = bus->busn_res.end;
                if (next_busno <= pci_ctrl->last_busno)
diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c
index 9ecabfa..e7a4f66 100644
--- a/drivers/pci/host/pci-xgene.c
+++ b/drivers/pci/host/pci-xgene.c
@@ -634,7 +634,7 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev)
        bus = pci_scan_root_bus(&pdev->dev, 0, &xgene_pcie_ops, port, &res);
        if (!bus)
                return -ENOMEM;
-
+       pci_bus_add_devices(bus);
        platform_set_drvdata(pdev, port);
        return 0;
 }
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index b486432..76ce157 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -740,7 +740,7 @@ static void ibm_unconfigure_device(struct pci_func *func)
  */
 static u8 bus_structure_fixup(u8 busno)
 {
-       struct pci_bus *bus;
+       struct pci_bus *bus, *b;
        struct pci_dev *dev;
        u16 l;
@@ -767,7 +767,9 @@ static u8 bus_structure_fixup(u8 busno)
                                        (l != 0x0000) && (l != 0xffff)) {
                        debug("%s - Inside bus_structure_fixup()\n",
                                                        __func__);
-                       pci_scan_root_bus(NULL, busno, ibmphp_pci_bus->ops, NULL, NULL);
+                       b = pci_scan_root_bus(NULL, busno, ibmphp_pci_bus->ops, NULL, NULL);
+                       if (b)
+                               pci_bus_add_devices(b);
                        break;
                }
        }
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 0a02fc2..97711f3 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2101,7 +2101,6 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
        if (!found)
                pci_bus_update_busn_res_end(b, max);

-       pci_bus_add_devices(b);
        return b;
 }
 EXPORT_SYMBOL(pci_scan_root_bus);
--
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Thanks!
Yijing

Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()

From: Yijing Wang <hidden>
Date: 2014-11-19 01:45:18

On 2014/11/18 23:30, Liviu Dudau wrote:
On Mon, Nov 17, 2014 at 10:21:41AM +0000, Yijing Wang wrote:
quoted
There are some common PCI infos like domain, msi_controller, these
infos are saved in arch PCI sysdata, and lots arch specific functions
like pci_domain_nr() and pcibios_msi_controller() required.
We could separate pci_host_bridge creation out of pci_create_root_bus(),
then we could put the common infos in, then we could eliminate
the arch specifc functions.
Please Cc: Yinghai Lu and Jiang Liu on future versions.

More comments on the conversion of pci_create_root_bus():
That's my mistake, will add CC Yinghai and Jiang in next version.
quoted
Signed-off-by: Yijing Wang <redacted>
---
...
quoted
+
+static void pci_release_host_bridge_dev(struct device *dev)
+{
+       struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
+
+       if (bridge->release_fn)
+               bridge->release_fn(bridge);
+       pci_free_resource_list(&bridge->windows);
+       kfree(bridge);
+}
+
+struct pci_host_bridge *pci_create_host_bridge(
+               struct device *parent, u32 db,
+               struct pci_ops *ops, void *sysdata,
I don't thinks it is worth moving the buses' pci_ops into pci_host_bridge. It
might be more useful to have pci_host_bridge specific ops here.
Because we want to create pci_host_bridge before pci root bus creation,
so when we scan the root bus and child buses, we use pci_host_bridge as
the only argument, and another pci_host_info will be addes in later patch,
which one support carry the pci_host_bridge ops.
quoted
+               struct list_head *resources)
+{
+       int error;
+       struct pci_bus *b;
+       struct pci_host_bridge *host, *h;
...
quoted
-struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
-               struct pci_ops *ops, void *sysdata, struct list_head *resources)
+struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *bridge)
 {
        int error;
-       struct pci_host_bridge *bridge;
        struct pci_bus *b, *b2;
-       struct pci_host_bridge_window *window, *n;
+       struct pci_host_bridge_window *window;
        struct resource *res;
        resource_size_t offset;
        char bus_addr[64];
        char *fmt;
-       u8      bus = PCI_BUSNUM(db);
+       struct device *parent = bridge->dev.parent;

        b = pci_alloc_bus(NULL);
        if (!b)
                return NULL;

-       b->sysdata = sysdata;
-       b->ops = ops;
-       b->number = b->busn_res.start = bus;
+       b->sysdata = bridge->sysdata;
I think bridge should be the b->sysdata here. 
? what's the meaning?
quoted
+       b->ops = bridge->ops;
See comment above why I don't think this is necessary.
quoted
+       b->number = b->busn_res.start = bridge->busnum;
        pci_bus_assign_domain_nr(b, parent);
-       b2 = pci_find_bus(pci_domain_nr(b), bus);
+       bridge->domain = pci_domain_nr(b);
Do you really want to overwrite the bridge's domain with the one from a bus that
could possibly be rejected a couple of lines further down?

As an asside: if we are doing the split of pci_host_bridge from root bus creation
it is worth in my opinion to move the domain setup in pci_create_host_bridge()
and stop fiddling with it here.

Hi Liviu, these lines just temporary, I will remove it after all host drivers
save its domain in pci_host_bridge.

Otherwise it looks to me like you are heading in the right direction.
Thanks!
Yijing.
Best regards,
Liviu
quoted
+       b2 = pci_find_bus(pci_domain_nr(b), bridge->busnum);
        if (b2) {
                /* If we already got to this bus through a different bridge, ignore it */
                dev_dbg(&b2->dev, "bus already known\n");
                goto err_out;
        }

-       bridge = pci_alloc_host_bridge(b);
-       if (!bridge)
-               goto err_out;
-
-       bridge->dev.parent = parent;
-       bridge->dev.release = pci_release_host_bridge_dev;
-       dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
-       error = pcibios_root_bridge_prepare(bridge);
-       if (error) {
-               kfree(bridge);
-               goto err_out;
-       }
-
-       error = device_register(&bridge->dev);
-       if (error) {
-               put_device(&bridge->dev);
-               goto err_out;
-       }
        b->bridge = get_device(&bridge->dev);
        device_enable_async_suspend(b->bridge);
        pci_set_bus_of_node(b);
@@ -1950,7 +1899,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,

        b->dev.class = &pcibus_class;
        b->dev.parent = b->bridge;
-       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
+       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), b->number);
        error = device_register(&b->dev);
        if (error)
                goto class_dev_reg_err;
@@ -1966,12 +1915,11 @@ struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
                printk(KERN_INFO "PCI host bridge to bus %s\n", dev_name(&b->dev));

        /* Add initial resources to the bus */
-       list_for_each_entry_safe(window, n, resources, list) {
-               list_move_tail(&window->list, &bridge->windows);
+       list_for_each_entry(window, &bridge->windows, list) {
                res = window->res;
                offset = window->offset;
                if (res->flags & IORESOURCE_BUS)
-                       pci_bus_insert_busn_res(b, bus, res->end);
+                       pci_bus_insert_busn_res(b, b->number, res->end);
                else
                        pci_bus_add_resource(b, res, 0);
                if (offset) {
@@ -2001,6 +1949,25 @@ err_out:
        return NULL;
 }

+struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
+               struct pci_ops *ops, void *sysdata, struct list_head *resources)
+{
+       struct pci_host_bridge *host;
+
+       host = pci_create_host_bridge(parent, bus, ops,
+                       sysdata ,resources);
+       if (!host)
+               return NULL;
+
+       host->bus = __pci_create_root_bus(host);
+       if (!host->bus) {
+               pci_free_host_bridge(host);
+               return NULL;
+       }
+
+       return host->bus;
+}
+
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
 {
        struct resource *res = &b->busn_res;
@@ -2069,40 +2036,37 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
 {
        struct pci_host_bridge_window *window;
        bool found = false;
-       struct pci_bus *b;
-       LIST_HEAD(default_res);
+       struct pci_host_bridge *host;
        int max;

-       if (!resources) {
-               pci_add_resource(&default_res, &ioport_resource);
-               pci_add_resource(&default_res, &iomem_resource);
-               pci_add_resource(&default_res, &busn_resource);
-       } else {
-               list_for_each_entry(window, resources, list)
-                       if (window->res->flags & IORESOURCE_BUS) {
-                               found = true;
-                               break;
-                       }
-       }
+       host = pci_create_host_bridge(parent, db, ops, sysdata, resources);
+       if (!host)
+               return NULL;

-       b = pci_create_root_bus(parent, db, ops, sysdata,
-                       resources ? resources : &default_res);
-       if (!b)
+       list_for_each_entry(window, &host->windows, list)
+               if (window->res->flags & IORESOURCE_BUS) {
+                       found = true;
+                       break;
+               }
+
+       host->bus = __pci_create_root_bus(host);
+       if (!host->bus) {
+               pci_free_host_bridge(host);
                return NULL;
+       }

        if (!found) {
-               dev_info(&b->dev,
+               dev_info(&host->bus->dev,
                 "No busn resource found for root bus, will use [bus %02x-ff]\n",
                        PCI_BUSNUM(db));
-               pci_bus_insert_busn_res(b, PCI_BUSNUM(db), 255);
+               pci_bus_insert_busn_res(host->bus, PCI_BUSNUM(db), 255);
        }

-       max = pci_scan_child_bus(b);
-
+       max = pci_scan_child_bus(host->bus);
        if (!found)
-               pci_bus_update_busn_res_end(b, max);
+               pci_bus_update_busn_res_end(host->bus, max);

-       return b;
+       return host->bus;
 }
 EXPORT_SYMBOL(pci_scan_root_bus);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 8b11b38..daa7f40 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -402,7 +402,12 @@ struct pci_host_bridge_window {
 struct pci_host_bridge {
        struct device dev;
        struct pci_bus *bus;            /* root bus */
+       struct list_head list;
        struct list_head windows;       /* pci_host_bridge_windows */
+       int busnum;
+       int domain;
+       void *sysdata;
+       struct pci_ops *ops;
        void (*release_fn)(struct pci_host_bridge *);
        void *release_data;
 };
@@ -413,7 +418,9 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
                     void *release_data);

 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
-
+struct pci_host_bridge *pci_create_host_bridge(
+               struct device *parent, u32 db, struct pci_ops *ops,
+               void *sys, struct list_head *resources);
 /*
  * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
  * to P2P or CardBus bridge windows) go in a table.  Additional ones (for
@@ -770,6 +777,8 @@ void pci_bus_add_devices(const struct pci_bus *bus);
 struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
                                    struct pci_ops *ops, void *sysdata,
                                    struct list_head *resources);
+struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *host);
+void pci_free_host_bridge(struct pci_host_bridge *host);
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
 int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
 void pci_bus_release_busn_res(struct pci_bus *b);
--
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Thanks!
Yijing

Re: [RFC PATCH 08/16] PCI: Introduce pci_scan_host_bridge() and pci_host_info

From: Yijing Wang <hidden>
Date: 2014-11-19 02:10:15

quoted
 struct pci_host_bridge *pci_create_host_bridge(
-		struct device *parent, u32 db, 
-		struct pci_ops *ops, void *sysdata, 
-		struct list_head *resources)
+		struct device *parent, u32 db, struct pci_ops *ops, 
+		struct pci_host_info *info)
 {
 	int error;
 	struct pci_bus *b;
 	struct pci_host_bridge *host, *h;
-	struct pci_host_bridge_window *window, *n;
 
 	down_read(&pci_host_bridge_sem);
 	list_for_each_entry(h, &pci_host_bridge_list, list) {
@@ -53,7 +51,7 @@ struct pci_host_bridge *pci_create_host_bridge(
 	if (!host)
 		return NULL;
 
-	host->sysdata = sysdata;
+	host->sysdata = info->arg;
 	host->busnum = PCI_BUSNUM(db);
 	host->domain = PCI_DOMAIN(db);
 	host->ops = ops;
@@ -63,18 +61,23 @@ struct pci_host_bridge *pci_create_host_bridge(
 
 	/* this is hack, just for build, will be removed later*/
Why do you need this hack? Just for calling pci_domain_nr() ?
Yes, it's temporary code, we need domain number here for pci host bridge register.
quoted
 	b = kzalloc(sizeof(*b), GFP_KERNEL);
-	b->sysdata = sysdata;
+	b->sysdata = host->sysdata;
 	pci_bus_assign_domain_nr(b, parent);
 	host->domain = pci_domain_nr(b);
+	kfree(b);
 
...
quoted
+static int pci_default_init_res(struct pci_host_bridge *host,
+		struct pci_host_info *info)
+{
+	struct pci_host_bridge_window *window, *n;
+
+	if (info->res_type != PCI_HOST_RES_DEFAULT) 
+		list_for_each_entry_safe(window, n, info->resources,
+				list)
+			list_move_tail(&window->list, &host->windows);
+	else
+		info->res_type = PCI_HOST_RES_DEFAULT;
I'm confused about this assignment. Isn't this a nop as the else part
means info->res_type *is* PCI_HOST_RES_DEFAULT?
No, in this patch, host drivers pass a pci host bridge resources init hook
in pci_host_info *info, and we call this info->init_res() in pci_create_host_bridge().

+struct pci_host_info {
+	u8 res_type;
+	void *arg;
+	struct list_head *resources; /*just for build, will clean up later */
+	int (*init_res)(struct pci_host_bridge *host,
+			struct pci_host_info *info);
+};
+
quoted
+
+	return 0;
+}
...
quoted
@@ -2038,8 +2057,13 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
 	bool found = false;
 	struct pci_host_bridge *host;
 	int max;
+	struct pci_host_info info;
+	
+	info.arg = sysdata;
+	info.resources = resources;
+	info.init_res = pci_default_init_res;
I have mixed feelings about this patch. While it is heading in the right direction
of moving pci_host_bridge relevant information towards the right user, I don't think
you picked up the right set to move. The resource list is going to be copied into
internal pci_host_bridge list anyway, keeping another copy is not helpful *and*
you have increased the code size.

I think for now we should aim to get the *missing* data into pci_host_bridge: MSI
controllers and PCI domain/segment. Then we can do more cleanup.
Hi Liviu, I agree with you here, the changes to resources stuff seems not a perfect
solution. In my patch 6, we could pass pci domain nr by u32 PCI_DOMBUS(domain, bus) argument,
and store it in pci_host_bridge. For msi controller, we couldn't save the msi_controller
in pci_host_bridge. Before we assume one pci host bridge only had one msi_controller,
but now something changes, Jiang introduce hierarchy irq domain in x86, and now
one pci host bridge may has more than one msi_controller. So I prefer to add a
function to pci_host_bridge something like

struct msi_controller *pci_get_msi_controller(struct pci_dev *dev)
quoted
 
-	host = pci_create_host_bridge(parent, db, ops, sysdata, resources);
+	host = pci_create_host_bridge(parent, db, ops, &info);
 	if (!host)
 		return NULL;
 
@@ -2070,6 +2094,47 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
 }
 EXPORT_SYMBOL(pci_scan_root_bus);
 
+struct pci_host_bridge *pci_scan_host_bridge(
+		struct device *parent, u32 db, struct pci_ops *ops,
+		struct pci_host_info *info)
+{
+	struct pci_host_bridge_window *window;
+	bool found = false;
+	struct pci_host_bridge *host;
+	int max;
+
+	host = pci_create_host_bridge(parent, db, ops, info);
+	if (!host)
+		return NULL;
+
+	list_for_each_entry(window, &host->windows, list)
+		if (window->res->flags & IORESOURCE_BUS) {
+			found = true;
+			break;
+		}
+
+	host->bus = __pci_create_root_bus(host);
+	if (!host->bus) {
+		pci_free_host_bridge(host);
+		return NULL;
+	}
+
+	if (!found) {
+		dev_info(&host->bus->dev,
+		 "No busn resource found for root bus, will use [bus %02x-ff]\n",
+			host->busnum);
+		pci_bus_insert_busn_res(host->bus, host->busnum, 255);
+	}
+
+	max = pci_scan_child_bus(host->bus);
+	if (!found)
+		pci_bus_update_busn_res_end(host->bus, max);
+
+	return host;
+
+}
+EXPORT_SYMBOL(pci_scan_host_bridge);
+
 /**
  * pci_rescan_bus_bridge_resize - scan a PCI bus for devices.
  * @bridge: PCI bridge for the bus to scan
diff --git a/include/linux/pci.h b/include/linux/pci.h
index daa7f40..a51f5f5 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -412,6 +412,21 @@ struct pci_host_bridge {
 	void *release_data;
 };
 
+struct pci_host_info {
+	u8 res_type;
+	void *arg;
+	struct list_head *resources; /*just for build, will clean up later */
+	int (*init_res)(struct pci_host_bridge *host, 
+			struct pci_host_info *info);
+};
+
+static inline void init_pci_host_info(struct pci_host_info *info)
+{
+	memset(info, 0 , sizeof(*info));
+}
Where is this used?
Host driver uses it to init pci_host_info.
quoted
+
+#define PCI_HOST_RES_DEFAULT	0x2
+
Magic number?
Hmmm, I will rework pci host bridge resources stuff.
Best regards,
Liviu
quoted
 #define	to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)
 void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
 		     void (*release_fn)(struct pci_host_bridge *),
@@ -420,7 +435,7 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
 struct pci_host_bridge *pci_create_host_bridge(
 		struct device *parent, u32 db, struct pci_ops *ops, 
-		void *sys, struct list_head *resources);
+		struct pci_host_info *info);
 /*
  * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
  * to P2P or CardBus bridge windows) go in a table.  Additional ones (for
@@ -785,6 +800,9 @@ void pci_bus_release_busn_res(struct pci_bus *b);
 struct pci_bus *pci_scan_root_bus(struct device *parent, u32 bus,
 					     struct pci_ops *ops, void *sysdata,
 					     struct list_head *resources);
+struct pci_host_bridge *pci_scan_host_bridge(struct device *parent,
+		u32 db, struct pci_ops *ops,
+		struct pci_host_info *info);
 struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
 				int busnr);
 void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Thanks!
Yijing

Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()

From: Yijing Wang <hidden>
Date: 2014-11-19 02:25:22

quoted
We need, some platforms pass NULL pointer as host bridge parent.
Yijing,

May I suggest a different approach here? Rather than having to pass an opaque
pointer that gets converted by the host bridge driver back to the private
structure, what about promoting a new style of usage, that is similar to the
way device drivers work? Lets try to promote the embedding of the generic
pci_host_bridge structure in the host bridge specific structure! Then we can
access the private data doing container_of().

Something like this:

struct pci_controller {
	struct pci_host_bridge bridge;
	/* private host bridge data here */
	.....
};

#define PCI_CONTROLLER(bus)	({
	struct pci_host_bridge *hb = to_pci_host_bridge(bus->bridge); \
	container_of(hb, struct pci_controller, bridge); })


Then we can retrieve the host bridge structure from everywhere we have a device.
Hi Liviu, it looks good to me, because this change will involve lots platforms,
I would think more about it. Thanks for your suggestion very much! :)


Thanks!
Yijing.
Best regards,
Liviu
quoted
quoted
quoted
+	host = kzalloc(sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return NULL;
devm_kzalloc maybe?
I don't know much detail about devm_kzalloc(), but we have no pci host driver
here, and I found no devm_kzalloc() uses in core PCI code before.
quoted
quoted
+	if (!resources) {
+		/* Use default IO/MEM/BUS resources*/
+		pci_add_resource(&host->windows, &ioport_resource);
+		pci_add_resource(&host->windows, &iomem_resource);
+		pci_add_resource(&host->windows, &busn_resource);
+	} else {
+		list_for_each_entry_safe(window, n, resources, list)
+			list_move_tail(&window->list, &host->windows);
+	}
I think we should assume that the correct resources are passed. You
could add a wrapper around this function to convert old platforms
though.
OK, I will move these code out of pci_create_host_bridge, and add a wrapper
to setup the default resources.
quoted
quoted
+EXPORT_SYMBOL(pci_create_host_bridge);
EXPORT_SYMBOL_GPL() maybe?
OK, will update it.
quoted
quoted
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 8b11b38..daa7f40 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -402,7 +402,12 @@ struct pci_host_bridge_window {
 struct pci_host_bridge {
 	struct device dev;
 	struct pci_bus *bus;		/* root bus */
+	struct list_head list;
 	struct list_head windows;	/* pci_host_bridge_windows */
+	int busnum;
The busnum should already be implied through the bus resource.
Yes, I will consider remove it and introduce a helper function to get the root bus number, thanks!

Thanks!
Yijing.
quoted
	Arnd

.

-- 
Thanks!
Yijing

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Thanks!
Yijing

Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()

From: Liviu Dudau <hidden>
Date: 2014-11-19 16:37:26

On Wed, Nov 19, 2014 at 10:24:52AM +0800, Yijing Wang wrote:
quoted
quoted
We need, some platforms pass NULL pointer as host bridge parent.
Yijing,

May I suggest a different approach here? Rather than having to pass an opaque
pointer that gets converted by the host bridge driver back to the private
structure, what about promoting a new style of usage, that is similar to the
way device drivers work? Lets try to promote the embedding of the generic
pci_host_bridge structure in the host bridge specific structure! Then we can
access the private data doing container_of().

Something like this:

struct pci_controller {
	struct pci_host_bridge bridge;
	/* private host bridge data here */
	.....
};

#define PCI_CONTROLLER(bus)	({
	struct pci_host_bridge *hb = to_pci_host_bridge(bus->bridge); \
	container_of(hb, struct pci_controller, bridge); })


Then we can retrieve the host bridge structure from everywhere we have a device.
Hi Liviu, it looks good to me, because this change will involve lots platforms,
I would think more about it. Thanks for your suggestion very much! :)
Given that I also look at this area maybe we should join forces and divide the problem?

Best regards,
Liviu

Thanks!
Yijing.
quoted
Best regards,
Liviu
quoted
quoted
quoted
+	host = kzalloc(sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return NULL;
devm_kzalloc maybe?
I don't know much detail about devm_kzalloc(), but we have no pci host driver
here, and I found no devm_kzalloc() uses in core PCI code before.
quoted
quoted
+	if (!resources) {
+		/* Use default IO/MEM/BUS resources*/
+		pci_add_resource(&host->windows, &ioport_resource);
+		pci_add_resource(&host->windows, &iomem_resource);
+		pci_add_resource(&host->windows, &busn_resource);
+	} else {
+		list_for_each_entry_safe(window, n, resources, list)
+			list_move_tail(&window->list, &host->windows);
+	}
I think we should assume that the correct resources are passed. You
could add a wrapper around this function to convert old platforms
though.
OK, I will move these code out of pci_create_host_bridge, and add a wrapper
to setup the default resources.
quoted
quoted
+EXPORT_SYMBOL(pci_create_host_bridge);
EXPORT_SYMBOL_GPL() maybe?
OK, will update it.
quoted
quoted
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 8b11b38..daa7f40 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -402,7 +402,12 @@ struct pci_host_bridge_window {
 struct pci_host_bridge {
 	struct device dev;
 	struct pci_bus *bus;		/* root bus */
+	struct list_head list;
 	struct list_head windows;	/* pci_host_bridge_windows */
+	int busnum;
The busnum should already be implied through the bus resource.
Yes, I will consider remove it and introduce a helper function to get the root bus number, thanks!

Thanks!
Yijing.
quoted
	Arnd

.

-- 
Thanks!
Yijing

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Thanks!
Yijing

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
-- 
-------------------
   .oooO
   (   )
    \ (  Oooo.
     \_) (   )
          ) /
         (_/

 One small step
   for me ...

Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()

From: Liviu Dudau <Liviu.Dudau@arm.com>
Date: 2014-11-19 16:37:39

On Wed, Nov 19, 2014 at 01:42:52AM +0000, Yijing Wang wrote:
On 2014/11/18 23:30, Liviu Dudau wrote:
quoted
On Mon, Nov 17, 2014 at 10:21:41AM +0000, Yijing Wang wrote:
quoted
There are some common PCI infos like domain, msi_controller, these
infos are saved in arch PCI sysdata, and lots arch specific functions
like pci_domain_nr() and pcibios_msi_controller() required.
We could separate pci_host_bridge creation out of pci_create_root_bus(=
),
quoted
quoted
then we could put the common infos in, then we could eliminate
the arch specifc functions.
Please Cc: Yinghai Lu and Jiang Liu on future versions.

More comments on the conversion of pci_create_root_bus():
=20
That's my mistake, will add CC Yinghai and Jiang in next version.
=20
quoted
quoted
Signed-off-by: Yijing Wang <redacted>
---
...
quoted
quoted
+
+static void pci_release_host_bridge_dev(struct device *dev)
+{
+       struct pci_host_bridge *bridge =3D to_pci_host_bridge(dev);
+
+       if (bridge->release_fn)
+               bridge->release_fn(bridge);
+       pci_free_resource_list(&bridge->windows);
+       kfree(bridge);
+}
+
+struct pci_host_bridge *pci_create_host_bridge(
+               struct device *parent, u32 db,
+               struct pci_ops *ops, void *sysdata,
I don't thinks it is worth moving the buses' pci_ops into pci_host_brid=
ge. It
quoted
might be more useful to have pci_host_bridge specific ops here.
=20
Because we want to create pci_host_bridge before pci root bus creation,
so when we scan the root bus and child buses, we use pci_host_bridge as
the only argument, and another pci_host_info will be addes in later patch=
,
which one support carry the pci_host_bridge ops.
But pci_create_root_bus() already has a pci_ops argument, I don't see the r=
eason
to drop that.

pci_create_host_bridge() can get pci_host_bridge ops while pci_create_root_=
bus() gets
the bus ops. For find out the MSI controller, the domain number and any oth=
er HB
specific stuff, you use the HB ops. For config R/W acceses you use bus ops.
=20
quoted
quoted
+               struct list_head *resources)
+{
+       int error;
+       struct pci_bus *b;
+       struct pci_host_bridge *host, *h;
...
quoted
quoted
-struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
-               struct pci_ops *ops, void *sysdata, struct list_head *=
resources)
quoted
quoted
+struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *bridge)
 {
        int error;
-       struct pci_host_bridge *bridge;
        struct pci_bus *b, *b2;
-       struct pci_host_bridge_window *window, *n;
+       struct pci_host_bridge_window *window;
        struct resource *res;
        resource_size_t offset;
        char bus_addr[64];
        char *fmt;
-       u8      bus =3D PCI_BUSNUM(db);
+       struct device *parent =3D bridge->dev.parent;

        b =3D pci_alloc_bus(NULL);
        if (!b)
                return NULL;

-       b->sysdata =3D sysdata;
-       b->ops =3D ops;
-       b->number =3D b->busn_res.start =3D bus;
+       b->sysdata =3D bridge->sysdata;
I think bridge should be the b->sysdata here.
=20
? what's the meaning?
Currently, bus->sysdata holds a pointer to the arch/driver host bridge stru=
cture, as passed
in pci_create_root_bus(). If you agree with my idea of wrapping the host br=
idge driver
structure around the pci_host_bridge, then we will always have a way of ret=
rieving that
information; but for backwards compatibility we could set bus->sysdata to b=
e the bridge.
Then existing macros that convert sysdata to pci_controller can be reused a=
fter being
updated.

Best regards,
Liviu
=20
quoted
quoted
+       b->ops =3D bridge->ops;
See comment above why I don't think this is necessary.
quoted
+       b->number =3D b->busn_res.start =3D bridge->busnum;
        pci_bus_assign_domain_nr(b, parent);
-       b2 =3D pci_find_bus(pci_domain_nr(b), bus);
+       bridge->domain =3D pci_domain_nr(b);
Do you really want to overwrite the bridge's domain with the one from a=
 bus that
quoted
could possibly be rejected a couple of lines further down?

As an asside: if we are doing the split of pci_host_bridge from root bu=
s creation
quoted
it is worth in my opinion to move the domain setup in pci_create_host_b=
ridge()
quoted
and stop fiddling with it here.
=20
=20
Hi Liviu, these lines just temporary, I will remove it after all host dri=
vers
save its domain in pci_host_bridge.
=20
=20
quoted
Otherwise it looks to me like you are heading in the right direction.
=20
Thanks!
Yijing.
=20
quoted
Best regards,
Liviu
quoted
+       b2 =3D pci_find_bus(pci_domain_nr(b), bridge->busnum);
        if (b2) {
                /* If we already got to this bus through a different b=
ridge, ignore it */
quoted
quoted
                dev_dbg(&b2->dev, "bus already known\n");
                goto err_out;
        }

-       bridge =3D pci_alloc_host_bridge(b);
-       if (!bridge)
-               goto err_out;
-
-       bridge->dev.parent =3D parent;
-       bridge->dev.release =3D pci_release_host_bridge_dev;
-       dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), b=
us);
quoted
quoted
-       error =3D pcibios_root_bridge_prepare(bridge);
-       if (error) {
-               kfree(bridge);
-               goto err_out;
-       }
-
-       error =3D device_register(&bridge->dev);
-       if (error) {
-               put_device(&bridge->dev);
-               goto err_out;
-       }
        b->bridge =3D get_device(&bridge->dev);
        device_enable_async_suspend(b->bridge);
        pci_set_bus_of_node(b);
@@ -1950,7 +1899,7 @@ struct pci_bus *pci_create_root_bus(struct devic=
e *parent, u32 db,
quoted
quoted

        b->dev.class =3D &pcibus_class;
        b->dev.parent =3D b->bridge;
-       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
+       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), b->number=
);
quoted
quoted
        error =3D device_register(&b->dev);
        if (error)
                goto class_dev_reg_err;
@@ -1966,12 +1915,11 @@ struct pci_bus *pci_create_root_bus(struct dev=
ice *parent, u32 db,
quoted
quoted
                printk(KERN_INFO "PCI host bridge to bus %s\n", dev_na=
me(&b->dev));
quoted
quoted

        /* Add initial resources to the bus */
-       list_for_each_entry_safe(window, n, resources, list) {
-               list_move_tail(&window->list, &bridge->windows);
+       list_for_each_entry(window, &bridge->windows, list) {
                res =3D window->res;
                offset =3D window->offset;
                if (res->flags & IORESOURCE_BUS)
-                       pci_bus_insert_busn_res(b, bus, res->end);
+                       pci_bus_insert_busn_res(b, b->number, res->end=
);
quoted
quoted
                else
                        pci_bus_add_resource(b, res, 0);
                if (offset) {
@@ -2001,6 +1949,25 @@ err_out:
        return NULL;
 }

+struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
+               struct pci_ops *ops, void *sysdata, struct list_head *=
resources)
quoted
quoted
+{
+       struct pci_host_bridge *host;
+
+       host =3D pci_create_host_bridge(parent, bus, ops,
+                       sysdata ,resources);
+       if (!host)
+               return NULL;
+
+       host->bus =3D __pci_create_root_bus(host);
+       if (!host->bus) {
+               pci_free_host_bridge(host);
+               return NULL;
+       }
+
+       return host->bus;
+}
+
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
 {
        struct resource *res =3D &b->busn_res;
@@ -2069,40 +2036,37 @@ struct pci_bus *pci_scan_root_bus(struct devic=
e *parent, u32 db,
quoted
quoted
 {
        struct pci_host_bridge_window *window;
        bool found =3D false;
-       struct pci_bus *b;
-       LIST_HEAD(default_res);
+       struct pci_host_bridge *host;
        int max;

-       if (!resources) {
-               pci_add_resource(&default_res, &ioport_resource);
-               pci_add_resource(&default_res, &iomem_resource);
-               pci_add_resource(&default_res, &busn_resource);
-       } else {
-               list_for_each_entry(window, resources, list)
-                       if (window->res->flags & IORESOURCE_BUS) {
-                               found =3D true;
-                               break;
-                       }
-       }
+       host =3D pci_create_host_bridge(parent, db, ops, sysdata, reso=
urces);
quoted
quoted
+       if (!host)
+               return NULL;

-       b =3D pci_create_root_bus(parent, db, ops, sysdata,
-                       resources ? resources : &default_res);
-       if (!b)
+       list_for_each_entry(window, &host->windows, list)
+               if (window->res->flags & IORESOURCE_BUS) {
+                       found =3D true;
+                       break;
+               }
+
+       host->bus =3D __pci_create_root_bus(host);
+       if (!host->bus) {
+               pci_free_host_bridge(host);
                return NULL;
+       }

        if (!found) {
-               dev_info(&b->dev,
+               dev_info(&host->bus->dev,
                 "No busn resource found for root bus, will use [bus %=
02x-ff]\n",
quoted
quoted
                        PCI_BUSNUM(db));
-               pci_bus_insert_busn_res(b, PCI_BUSNUM(db), 255);
+               pci_bus_insert_busn_res(host->bus, PCI_BUSNUM(db), 255=
);
quoted
quoted
        }

-       max =3D pci_scan_child_bus(b);
-
+       max =3D pci_scan_child_bus(host->bus);
        if (!found)
-               pci_bus_update_busn_res_end(b, max);
+               pci_bus_update_busn_res_end(host->bus, max);

-       return b;
+       return host->bus;
 }
 EXPORT_SYMBOL(pci_scan_root_bus);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 8b11b38..daa7f40 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -402,7 +402,12 @@ struct pci_host_bridge_window {
 struct pci_host_bridge {
        struct device dev;
        struct pci_bus *bus;            /* root bus */
+       struct list_head list;
        struct list_head windows;       /* pci_host_bridge_windows */
+       int busnum;
+       int domain;
+       void *sysdata;
+       struct pci_ops *ops;
        void (*release_fn)(struct pci_host_bridge *);
        void *release_data;
 };
@@ -413,7 +418,9 @@ void pci_set_host_bridge_release(struct pci_host_b=
ridge *bridge,
quoted
quoted
                     void *release_data);

 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
-
+struct pci_host_bridge *pci_create_host_bridge(
+               struct device *parent, u32 db, struct pci_ops *ops,
+               void *sys, struct list_head *resources);
 /*
  * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that co=
rrespond
quoted
quoted
  * to P2P or CardBus bridge windows) go in a table.  Additional ones =
(for
quoted
quoted
@@ -770,6 +777,8 @@ void pci_bus_add_devices(const struct pci_bus *bus=
);
quoted
quoted
 struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
                                    struct pci_ops *ops, void *sysdata=
,
quoted
quoted
                                    struct list_head *resources);
+struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *host);
+void pci_free_host_bridge(struct pci_host_bridge *host);
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
 int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
 void pci_bus_release_busn_res(struct pci_bus *b);
--
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" i=
n
quoted
quoted
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
=20
=20
--
Thanks!
Yijing
=20
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
=20
--=20
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    =C2=AF\_(=E3=83=84)_/=C2=AF

Re: [RFC PATCH 08/16] PCI: Introduce pci_scan_host_bridge() and pci_host_info

From: Liviu Dudau <Liviu.Dudau@arm.com>
Date: 2014-11-19 16:41:36

On Wed, Nov 19, 2014 at 02:09:12AM +0000, Yijing Wang wrote:
quoted
quoted
 struct pci_host_bridge *pci_create_host_bridge(
-=09=09struct device *parent, u32 db,=20
-=09=09struct pci_ops *ops, void *sysdata,=20
-=09=09struct list_head *resources)
+=09=09struct device *parent, u32 db, struct pci_ops *ops,=20
+=09=09struct pci_host_info *info)
 {
 =09int error;
 =09struct pci_bus *b;
 =09struct pci_host_bridge *host, *h;
-=09struct pci_host_bridge_window *window, *n;
=20
 =09down_read(&pci_host_bridge_sem);
 =09list_for_each_entry(h, &pci_host_bridge_list, list) {
@@ -53,7 +51,7 @@ struct pci_host_bridge *pci_create_host_bridge(
 =09if (!host)
 =09=09return NULL;
=20
-=09host->sysdata =3D sysdata;
+=09host->sysdata =3D info->arg;
 =09host->busnum =3D PCI_BUSNUM(db);
 =09host->domain =3D PCI_DOMAIN(db);
 =09host->ops =3D ops;
@@ -63,18 +61,23 @@ struct pci_host_bridge *pci_create_host_bridge(
=20
 =09/* this is hack, just for build, will be removed later*/
=20
Why do you need this hack? Just for calling pci_domain_nr() ?
=20
Yes, it's temporary code, we need domain number here for pci host bridge =
register.
=20
quoted
=20
quoted
 =09b =3D kzalloc(sizeof(*b), GFP_KERNEL);
-=09b->sysdata =3D sysdata;
+=09b->sysdata =3D host->sysdata;
 =09pci_bus_assign_domain_nr(b, parent);
 =09host->domain =3D pci_domain_nr(b);
+=09kfree(b);
=20
...
quoted
quoted
+static int pci_default_init_res(struct pci_host_bridge *host,
+=09=09struct pci_host_info *info)
+{
+=09struct pci_host_bridge_window *window, *n;
+
+=09if (info->res_type !=3D PCI_HOST_RES_DEFAULT)=20
+=09=09list_for_each_entry_safe(window, n, info->resources,
+=09=09=09=09list)
+=09=09=09list_move_tail(&window->list, &host->windows);
+=09else
+=09=09info->res_type =3D PCI_HOST_RES_DEFAULT;
=20
I'm confused about this assignment. Isn't this a nop as the else part
means info->res_type *is* PCI_HOST_RES_DEFAULT?
=20
No, in this patch, host drivers pass a pci host bridge resources init hoo=
k
in pci_host_info *info, and we call this info->init_res() in pci_create_h=
ost_bridge().
=20
+struct pci_host_info {
+=09u8 res_type;
+=09void *arg;
+=09struct list_head *resources; /*just for build, will clean up later */
+=09int (*init_res)(struct pci_host_bridge *host,
+=09=09=09struct pci_host_info *info);
+};
+
That's not what I've asked! Your code does:

=09if (info->res_type !=3D PCI_HOST_RES_DEFAULT)
=09=09....
=09else /* info->res_type =3D=3D PCI_HOST_RES_DEFAULT)
=09=09info->res_type =3D PCI_HOST_RES_DEFAULT;

info->res_type is already =3D=3D PCI_HOST_RES_DEFAULT in the else side, ass=
ignment is a NOP?

=20
quoted
=20
quoted
+
+=09return 0;
+}
...
quoted
quoted
@@ -2038,8 +2057,13 @@ struct pci_bus *pci_scan_root_bus(struct device=
 *parent, u32 db,
quoted
quoted
 =09bool found =3D false;
 =09struct pci_host_bridge *host;
 =09int max;
+=09struct pci_host_info info;
+=09
+=09info.arg =3D sysdata;
+=09info.resources =3D resources;
+=09info.init_res =3D pci_default_init_res;
=20
I have mixed feelings about this patch. While it is heading in the righ=
t direction
quoted
of moving pci_host_bridge relevant information towards the right user, =
I don't think
quoted
you picked up the right set to move. The resource list is going to be c=
opied into
quoted
internal pci_host_bridge list anyway, keeping another copy is not helpf=
ul *and*
quoted
you have increased the code size.
=20
I think for now we should aim to get the *missing* data into pci_host_b=
ridge: MSI
quoted
controllers and PCI domain/segment. Then we can do more cleanup.
=20
Hi Liviu, I agree with you here, the changes to resources stuff seems not=
 a perfect
solution. In my patch 6, we could pass pci domain nr by u32 PCI_DOMBUS(do=
main, bus) argument,
and store it in pci_host_bridge. For msi controller, we couldn't save the=
 msi_controller
in pci_host_bridge. Before we assume one pci host bridge only had one msi=
_controller,
but now something changes, Jiang introduce hierarchy irq domain in x86, a=
nd now
one pci host bridge may has more than one msi_controller. So I prefer to =
add a
function to pci_host_bridge something like
=20
struct msi_controller *pci_get_msi_controller(struct pci_dev *dev)
Yes, good idea.
=20
quoted
=20
quoted
=20
-=09host =3D pci_create_host_bridge(parent, db, ops, sysdata, resource=
s);
quoted
quoted
+=09host =3D pci_create_host_bridge(parent, db, ops, &info);
 =09if (!host)
 =09=09return NULL;
=20
@@ -2070,6 +2094,47 @@ struct pci_bus *pci_scan_root_bus(struct device=
 *parent, u32 db,
quoted
quoted
 }
 EXPORT_SYMBOL(pci_scan_root_bus);
=20
+struct pci_host_bridge *pci_scan_host_bridge(
+=09=09struct device *parent, u32 db, struct pci_ops *ops,
+=09=09struct pci_host_info *info)
+{
+=09struct pci_host_bridge_window *window;
+=09bool found =3D false;
+=09struct pci_host_bridge *host;
+=09int max;
+
+=09host =3D pci_create_host_bridge(parent, db, ops, info);
+=09if (!host)
+=09=09return NULL;
+
+=09list_for_each_entry(window, &host->windows, list)
+=09=09if (window->res->flags & IORESOURCE_BUS) {
+=09=09=09found =3D true;
+=09=09=09break;
+=09=09}
+
+=09host->bus =3D __pci_create_root_bus(host);
+=09if (!host->bus) {
+=09=09pci_free_host_bridge(host);
+=09=09return NULL;
+=09}
+
+=09if (!found) {
+=09=09dev_info(&host->bus->dev,
+=09=09 "No busn resource found for root bus, will use [bus %02x-ff]\n=
",
quoted
quoted
+=09=09=09host->busnum);
+=09=09pci_bus_insert_busn_res(host->bus, host->busnum, 255);
+=09}
+
+=09max =3D pci_scan_child_bus(host->bus);
+=09if (!found)
+=09=09pci_bus_update_busn_res_end(host->bus, max);
+
+=09return host;
+
+}
+EXPORT_SYMBOL(pci_scan_host_bridge);
+
 /**
  * pci_rescan_bus_bridge_resize - scan a PCI bus for devices.
  * @bridge: PCI bridge for the bus to scan
diff --git a/include/linux/pci.h b/include/linux/pci.h
index daa7f40..a51f5f5 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -412,6 +412,21 @@ struct pci_host_bridge {
 =09void *release_data;
 };
=20
+struct pci_host_info {
+=09u8 res_type;
+=09void *arg;
+=09struct list_head *resources; /*just for build, will clean up later=
 */
quoted
quoted
+=09int (*init_res)(struct pci_host_bridge *host,=20
+=09=09=09struct pci_host_info *info);
+};
+
+static inline void init_pci_host_info(struct pci_host_info *info)
+{
+=09memset(info, 0 , sizeof(*info));
+}
=20
Where is this used?
=20
Host driver uses it to init pci_host_info.
Might be worth adding it that patch rather than here.

Best regards,
Liviu
=20
quoted
=20
quoted
+
+#define PCI_HOST_RES_DEFAULT=090x2
+
=20
Magic number?
=20
Hmmm, I will rework pci host bridge resources stuff.
=20
quoted
=20
Best regards,
Liviu
=20
quoted
 #define=09to_pci_host_bridge(n) container_of(n, struct pci_host_bridg=
e, dev)
quoted
quoted
 void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
 =09=09     void (*release_fn)(struct pci_host_bridge *),
@@ -420,7 +435,7 @@ void pci_set_host_bridge_release(struct pci_host_b=
ridge *bridge,
quoted
quoted
 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
 struct pci_host_bridge *pci_create_host_bridge(
 =09=09struct device *parent, u32 db, struct pci_ops *ops,=20
-=09=09void *sys, struct list_head *resources);
+=09=09struct pci_host_info *info);
 /*
  * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that co=
rrespond
quoted
quoted
  * to P2P or CardBus bridge windows) go in a table.  Additional ones =
(for
quoted
quoted
@@ -785,6 +800,9 @@ void pci_bus_release_busn_res(struct pci_bus *b);
 struct pci_bus *pci_scan_root_bus(struct device *parent, u32 bus,
 =09=09=09=09=09     struct pci_ops *ops, void *sysdata,
 =09=09=09=09=09     struct list_head *resources);
+struct pci_host_bridge *pci_scan_host_bridge(struct device *parent,
+=09=09u32 db, struct pci_ops *ops,
+=09=09struct pci_host_info *info);
 struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_de=
v *dev,
quoted
quoted
 =09=09=09=09int busnr);
 void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);
--=20
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" i=
n
quoted
quoted
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
=20
=20
=20
--=20
Thanks!
Yijing
=20
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
=20
--=20
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    =C2=AF\_(=E3=83=84)_/=C2=AF

Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()

From: Yijing Wang <hidden>
Date: 2014-11-20 02:01:23

quoted
quoted
Something like this:

struct pci_controller {
	struct pci_host_bridge bridge;
	/* private host bridge data here */
	.....
};

#define PCI_CONTROLLER(bus)	({
	struct pci_host_bridge *hb = to_pci_host_bridge(bus->bridge); \
	container_of(hb, struct pci_controller, bridge); })


Then we can retrieve the host bridge structure from everywhere we have a device.
Hi Liviu, it looks good to me, because this change will involve lots platforms,
I would think more about it. Thanks for your suggestion very much! :)
Given that I also look at this area maybe we should join forces and divide the problem?
That's better, we could cooperate to do this. :)
Best regards,
Liviu
quoted

Thanks!
Yijing.
quoted
Best regards,
Liviu
quoted
quoted
quoted
+	host = kzalloc(sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return NULL;
devm_kzalloc maybe?
I don't know much detail about devm_kzalloc(), but we have no pci host driver
here, and I found no devm_kzalloc() uses in core PCI code before.
quoted
quoted
+	if (!resources) {
+		/* Use default IO/MEM/BUS resources*/
+		pci_add_resource(&host->windows, &ioport_resource);
+		pci_add_resource(&host->windows, &iomem_resource);
+		pci_add_resource(&host->windows, &busn_resource);
+	} else {
+		list_for_each_entry_safe(window, n, resources, list)
+			list_move_tail(&window->list, &host->windows);
+	}
I think we should assume that the correct resources are passed. You
could add a wrapper around this function to convert old platforms
though.
OK, I will move these code out of pci_create_host_bridge, and add a wrapper
to setup the default resources.
quoted
quoted
+EXPORT_SYMBOL(pci_create_host_bridge);
EXPORT_SYMBOL_GPL() maybe?
OK, will update it.
quoted
quoted
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 8b11b38..daa7f40 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -402,7 +402,12 @@ struct pci_host_bridge_window {
 struct pci_host_bridge {
 	struct device dev;
 	struct pci_bus *bus;		/* root bus */
+	struct list_head list;
 	struct list_head windows;	/* pci_host_bridge_windows */
+	int busnum;
The busnum should already be implied through the bus resource.
Yes, I will consider remove it and introduce a helper function to get the root bus number, thanks!

Thanks!
Yijing.
quoted
	Arnd

.

-- 
Thanks!
Yijing

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Thanks!
Yijing

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

-- 
Thanks!
Yijing

Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()

From: Yijing Wang <hidden>
Date: 2014-11-20 02:48:00

quoted
quoted
quoted
+static void pci_release_host_bridge_dev(struct device *dev)
+{
+       struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
+
+       if (bridge->release_fn)
+               bridge->release_fn(bridge);
+       pci_free_resource_list(&bridge->windows);
+       kfree(bridge);
+}
+
+struct pci_host_bridge *pci_create_host_bridge(
+               struct device *parent, u32 db,
+               struct pci_ops *ops, void *sysdata,
I don't thinks it is worth moving the buses' pci_ops into pci_host_bridge. It
might be more useful to have pci_host_bridge specific ops here.
Because we want to create pci_host_bridge before pci root bus creation,
so when we scan the root bus and child buses, we use pci_host_bridge as
the only argument, and another pci_host_info will be addes in later patch,
which one support carry the pci_host_bridge ops.
But pci_create_root_bus() already has a pci_ops argument, I don't see the reason
to drop that.

pci_create_host_bridge() can get pci_host_bridge ops while pci_create_root_bus() gets
the bus ops. For find out the MSI controller, the domain number and any other HB
specific stuff, you use the HB ops. For config R/W acceses you use bus ops.
I want to unexport pci_create_root_bus() if we have pci_create_host_bridge().

quoted
quoted
quoted
-struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
-               struct pci_ops *ops, void *sysdata, struct list_head *resources)
+struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *bridge)
 {
        int error;
-       struct pci_host_bridge *bridge;
        struct pci_bus *b, *b2;
-       struct pci_host_bridge_window *window, *n;
+       struct pci_host_bridge_window *window;
        struct resource *res;
        resource_size_t offset;
        char bus_addr[64];
        char *fmt;
-       u8      bus = PCI_BUSNUM(db);
+       struct device *parent = bridge->dev.parent;

        b = pci_alloc_bus(NULL);
        if (!b)
                return NULL;

-       b->sysdata = sysdata;
-       b->ops = ops;
-       b->number = b->busn_res.start = bus;
+       b->sysdata = bridge->sysdata;
I think bridge should be the b->sysdata here.
? what's the meaning?
Currently, bus->sysdata holds a pointer to the arch/driver host bridge structure, as passed
in pci_create_root_bus(). If you agree with my idea of wrapping the host bridge driver
structure around the pci_host_bridge, then we will always have a way of retrieving that
information; but for backwards compatibility we could set bus->sysdata to be the bridge.
Then existing macros that convert sysdata to pci_controller can be reused after being
updated.
I think wrapping the host bridge driver structure around the pci_host_bridge could help
us to find the private pci_controller, but in this case, pci_host_bridge is not a pointer
so we put all pci_host_bridge init stuff in host drivers ? And if we still use arch spec
macros convert ssydata to pci_controller, so what's the greatest advantage ?

If we move domain and msi_chip out of sysdata, what's other things in sysdata still need us
to convert in PCI core ?


Best regards,
Liviu
quoted
quoted
quoted
+       b->ops = bridge->ops;
See comment above why I don't think this is necessary.
quoted
+       b->number = b->busn_res.start = bridge->busnum;
        pci_bus_assign_domain_nr(b, parent);
-       b2 = pci_find_bus(pci_domain_nr(b), bus);
+       bridge->domain = pci_domain_nr(b);
Do you really want to overwrite the bridge's domain with the one from a bus that
could possibly be rejected a couple of lines further down?

As an asside: if we are doing the split of pci_host_bridge from root bus creation
it is worth in my opinion to move the domain setup in pci_create_host_bridge()
and stop fiddling with it here.

Hi Liviu, these lines just temporary, I will remove it after all host drivers
save its domain in pci_host_bridge.

quoted
Otherwise it looks to me like you are heading in the right direction.
Thanks!
Yijing.
quoted
Best regards,
Liviu
quoted
+       b2 = pci_find_bus(pci_domain_nr(b), bridge->busnum);
        if (b2) {
                /* If we already got to this bus through a different bridge, ignore it */
                dev_dbg(&b2->dev, "bus already known\n");
                goto err_out;
        }

-       bridge = pci_alloc_host_bridge(b);
-       if (!bridge)
-               goto err_out;
-
-       bridge->dev.parent = parent;
-       bridge->dev.release = pci_release_host_bridge_dev;
-       dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
-       error = pcibios_root_bridge_prepare(bridge);
-       if (error) {
-               kfree(bridge);
-               goto err_out;
-       }
-
-       error = device_register(&bridge->dev);
-       if (error) {
-               put_device(&bridge->dev);
-               goto err_out;
-       }
        b->bridge = get_device(&bridge->dev);
        device_enable_async_suspend(b->bridge);
        pci_set_bus_of_node(b);
@@ -1950,7 +1899,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,

        b->dev.class = &pcibus_class;
        b->dev.parent = b->bridge;
-       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
+       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), b->number);
        error = device_register(&b->dev);
        if (error)
                goto class_dev_reg_err;
@@ -1966,12 +1915,11 @@ struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
                printk(KERN_INFO "PCI host bridge to bus %s\n", dev_name(&b->dev));

        /* Add initial resources to the bus */
-       list_for_each_entry_safe(window, n, resources, list) {
-               list_move_tail(&window->list, &bridge->windows);
+       list_for_each_entry(window, &bridge->windows, list) {
                res = window->res;
                offset = window->offset;
                if (res->flags & IORESOURCE_BUS)
-                       pci_bus_insert_busn_res(b, bus, res->end);
+                       pci_bus_insert_busn_res(b, b->number, res->end);
                else
                        pci_bus_add_resource(b, res, 0);
                if (offset) {
@@ -2001,6 +1949,25 @@ err_out:
        return NULL;
 }

+struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
+               struct pci_ops *ops, void *sysdata, struct list_head *resources)
+{
+       struct pci_host_bridge *host;
+
+       host = pci_create_host_bridge(parent, bus, ops,
+                       sysdata ,resources);
+       if (!host)
+               return NULL;
+
+       host->bus = __pci_create_root_bus(host);
+       if (!host->bus) {
+               pci_free_host_bridge(host);
+               return NULL;
+       }
+
+       return host->bus;
+}
+
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
 {
        struct resource *res = &b->busn_res;
@@ -2069,40 +2036,37 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
 {
        struct pci_host_bridge_window *window;
        bool found = false;
-       struct pci_bus *b;
-       LIST_HEAD(default_res);
+       struct pci_host_bridge *host;
        int max;

-       if (!resources) {
-               pci_add_resource(&default_res, &ioport_resource);
-               pci_add_resource(&default_res, &iomem_resource);
-               pci_add_resource(&default_res, &busn_resource);
-       } else {
-               list_for_each_entry(window, resources, list)
-                       if (window->res->flags & IORESOURCE_BUS) {
-                               found = true;
-                               break;
-                       }
-       }
+       host = pci_create_host_bridge(parent, db, ops, sysdata, resources);
+       if (!host)
+               return NULL;

-       b = pci_create_root_bus(parent, db, ops, sysdata,
-                       resources ? resources : &default_res);
-       if (!b)
+       list_for_each_entry(window, &host->windows, list)
+               if (window->res->flags & IORESOURCE_BUS) {
+                       found = true;
+                       break;
+               }
+
+       host->bus = __pci_create_root_bus(host);
+       if (!host->bus) {
+               pci_free_host_bridge(host);
                return NULL;
+       }

        if (!found) {
-               dev_info(&b->dev,
+               dev_info(&host->bus->dev,
                 "No busn resource found for root bus, will use [bus %02x-ff]\n",
                        PCI_BUSNUM(db));
-               pci_bus_insert_busn_res(b, PCI_BUSNUM(db), 255);
+               pci_bus_insert_busn_res(host->bus, PCI_BUSNUM(db), 255);
        }

-       max = pci_scan_child_bus(b);
-
+       max = pci_scan_child_bus(host->bus);
        if (!found)
-               pci_bus_update_busn_res_end(b, max);
+               pci_bus_update_busn_res_end(host->bus, max);

-       return b;
+       return host->bus;
 }
 EXPORT_SYMBOL(pci_scan_root_bus);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 8b11b38..daa7f40 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -402,7 +402,12 @@ struct pci_host_bridge_window {
 struct pci_host_bridge {
        struct device dev;
        struct pci_bus *bus;            /* root bus */
+       struct list_head list;
        struct list_head windows;       /* pci_host_bridge_windows */
+       int busnum;
+       int domain;
+       void *sysdata;
+       struct pci_ops *ops;
        void (*release_fn)(struct pci_host_bridge *);
        void *release_data;
 };
@@ -413,7 +418,9 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
                     void *release_data);

 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
-
+struct pci_host_bridge *pci_create_host_bridge(
+               struct device *parent, u32 db, struct pci_ops *ops,
+               void *sys, struct list_head *resources);
 /*
  * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
  * to P2P or CardBus bridge windows) go in a table.  Additional ones (for
@@ -770,6 +777,8 @@ void pci_bus_add_devices(const struct pci_bus *bus);
 struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
                                    struct pci_ops *ops, void *sysdata,
                                    struct list_head *resources);
+struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *host);
+void pci_free_host_bridge(struct pci_host_bridge *host);
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
 int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
 void pci_bus_release_busn_res(struct pci_bus *b);
--
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
Thanks!
Yijing

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Thanks!
Yijing

Re: [RFC PATCH 08/16] PCI: Introduce pci_scan_host_bridge() and pci_host_info

From: Yijing Wang <hidden>
Date: 2014-11-20 02:54:34

quoted
No, in this patch, host drivers pass a pci host bridge resources init hook
in pci_host_info *info, and we call this info->init_res() in pci_create_host_bridge().

+struct pci_host_info {
+	u8 res_type;
+	void *arg;
+	struct list_head *resources; /*just for build, will clean up later */
+	int (*init_res)(struct pci_host_bridge *host,
+			struct pci_host_info *info);
+};
+
That's not what I've asked! Your code does:

	if (info->res_type != PCI_HOST_RES_DEFAULT)
		....
	else /* info->res_type == PCI_HOST_RES_DEFAULT)
		info->res_type = PCI_HOST_RES_DEFAULT;

info->res_type is already == PCI_HOST_RES_DEFAULT in the else side, assignment is a NOP?
Hmmm, I wanted pci_create_host_bridge() to process the default res later(add default res),
It's ugly code, I will rework it.
quoted
quoted
quoted
+
+	return 0;
+}
...
quoted
quoted
@@ -2038,8 +2057,13 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
 	bool found = false;
 	struct pci_host_bridge *host;
 	int max;
+	struct pci_host_info info;
+	
+	info.arg = sysdata;
+	info.resources = resources;
+	info.init_res = pci_default_init_res;
I have mixed feelings about this patch. While it is heading in the right direction
of moving pci_host_bridge relevant information towards the right user, I don't think
you picked up the right set to move. The resource list is going to be copied into
internal pci_host_bridge list anyway, keeping another copy is not helpful *and*
you have increased the code size.

I think for now we should aim to get the *missing* data into pci_host_bridge: MSI
controllers and PCI domain/segment. Then we can do more cleanup.
Hi Liviu, I agree with you here, the changes to resources stuff seems not a perfect
solution. In my patch 6, we could pass pci domain nr by u32 PCI_DOMBUS(domain, bus) argument,
and store it in pci_host_bridge. For msi controller, we couldn't save the msi_controller
in pci_host_bridge. Before we assume one pci host bridge only had one msi_controller,
but now something changes, Jiang introduce hierarchy irq domain in x86, and now
one pci host bridge may has more than one msi_controller. So I prefer to add a
function to pci_host_bridge something like

struct msi_controller *pci_get_msi_controller(struct pci_dev *dev)
Yes, good idea.
quoted
quoted
quoted
 
-	host = pci_create_host_bridge(parent, db, ops, sysdata, resources);
+	host = pci_create_host_bridge(parent, db, ops, &info);
 	if (!host)
 		return NULL;
 
@@ -2070,6 +2094,47 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
 }
 EXPORT_SYMBOL(pci_scan_root_bus);
 
+struct pci_host_bridge *pci_scan_host_bridge(
+		struct device *parent, u32 db, struct pci_ops *ops,
+		struct pci_host_info *info)
+{
+	struct pci_host_bridge_window *window;
+	bool found = false;
+	struct pci_host_bridge *host;
+	int max;
+
+	host = pci_create_host_bridge(parent, db, ops, info);
+	if (!host)
+		return NULL;
+
+	list_for_each_entry(window, &host->windows, list)
+		if (window->res->flags & IORESOURCE_BUS) {
+			found = true;
+			break;
+		}
+
+	host->bus = __pci_create_root_bus(host);
+	if (!host->bus) {
+		pci_free_host_bridge(host);
+		return NULL;
+	}
+
+	if (!found) {
+		dev_info(&host->bus->dev,
+		 "No busn resource found for root bus, will use [bus %02x-ff]\n",
+			host->busnum);
+		pci_bus_insert_busn_res(host->bus, host->busnum, 255);
+	}
+
+	max = pci_scan_child_bus(host->bus);
+	if (!found)
+		pci_bus_update_busn_res_end(host->bus, max);
+
+	return host;
+
+}
+EXPORT_SYMBOL(pci_scan_host_bridge);
+
 /**
  * pci_rescan_bus_bridge_resize - scan a PCI bus for devices.
  * @bridge: PCI bridge for the bus to scan
diff --git a/include/linux/pci.h b/include/linux/pci.h
index daa7f40..a51f5f5 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -412,6 +412,21 @@ struct pci_host_bridge {
 	void *release_data;
 };
 
+struct pci_host_info {
+	u8 res_type;
+	void *arg;
+	struct list_head *resources; /*just for build, will clean up later */
+	int (*init_res)(struct pci_host_bridge *host, 
+			struct pci_host_info *info);
+};
+
+static inline void init_pci_host_info(struct pci_host_info *info)
+{
+	memset(info, 0 , sizeof(*info));
+}
Where is this used?
Host driver uses it to init pci_host_info.
Might be worth adding it that patch rather than here.
OK
Best regards,
Liviu
quoted
quoted
quoted
+
+#define PCI_HOST_RES_DEFAULT	0x2
+
Magic number?
Hmmm, I will rework pci host bridge resources stuff.
quoted
Best regards,
Liviu
quoted
 #define	to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)
 void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
 		     void (*release_fn)(struct pci_host_bridge *),
@@ -420,7 +435,7 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
 struct pci_host_bridge *pci_create_host_bridge(
 		struct device *parent, u32 db, struct pci_ops *ops, 
-		void *sys, struct list_head *resources);
+		struct pci_host_info *info);
 /*
  * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
  * to P2P or CardBus bridge windows) go in a table.  Additional ones (for
@@ -785,6 +800,9 @@ void pci_bus_release_busn_res(struct pci_bus *b);
 struct pci_bus *pci_scan_root_bus(struct device *parent, u32 bus,
 					     struct pci_ops *ops, void *sysdata,
 					     struct list_head *resources);
+struct pci_host_bridge *pci_scan_host_bridge(struct device *parent,
+		u32 db, struct pci_ops *ops,
+		struct pci_host_info *info);
 struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
 				int busnr);
 void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Thanks!
Yijing

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Thanks!
Yijing

Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()

From: Liviu Dudau <Liviu.Dudau@arm.com>
Date: 2014-11-20 09:48:17

On Thu, Nov 20, 2014 at 02:47:35AM +0000, Yijing Wang wrote:
quoted
quoted
quoted
quoted
+static void pci_release_host_bridge_dev(struct device *dev)
+{
+       struct pci_host_bridge *bridge =3D to_pci_host_bridge(dev);
+
+       if (bridge->release_fn)
+               bridge->release_fn(bridge);
+       pci_free_resource_list(&bridge->windows);
+       kfree(bridge);
+}
+
+struct pci_host_bridge *pci_create_host_bridge(
+               struct device *parent, u32 db,
+               struct pci_ops *ops, void *sysdata,
I don't thinks it is worth moving the buses' pci_ops into pci_host_br=
idge. It
quoted
quoted
quoted
might be more useful to have pci_host_bridge specific ops here.
Because we want to create pci_host_bridge before pci root bus creation=
,
quoted
quoted
so when we scan the root bus and child buses, we use pci_host_bridge a=
s
quoted
quoted
the only argument, and another pci_host_info will be addes in later pa=
tch,
quoted
quoted
which one support carry the pci_host_bridge ops.
But pci_create_root_bus() already has a pci_ops argument, I don't see t=
he reason
quoted
to drop that.

pci_create_host_bridge() can get pci_host_bridge ops while pci_create_r=
oot_bus() gets
quoted
the bus ops. For find out the MSI controller, the domain number and any=
 other HB
quoted
specific stuff, you use the HB ops. For config R/W acceses you use bus =
ops.
quoted
=20
I want to unexport pci_create_root_bus() if we have pci_create_host_bridg=
e().

That's fine, but the function signature doesn't change, right? And I think =
we should keep
pci_scan_root_bus() with the current signature as well (except change sysda=
ta into a
struct pci_host_bridge *). We create the host bridge in one step, stuff it =
with all the
data that we need for scanning the root and associated busses, and then cal=
l pci_scan_root_bus().
pci_host_bridge has the ops from pci_create_host_bridge() and the root bus =
from pci_scan_root_bus().

Hope this makes sense.
=20
=20
quoted
quoted
quoted
quoted
-struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
-               struct pci_ops *ops, void *sysdata, struct list_head=
 *resources)
quoted
quoted
quoted
quoted
+struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *bridg=
e)
quoted
quoted
quoted
quoted
 {
        int error;
-       struct pci_host_bridge *bridge;
        struct pci_bus *b, *b2;
-       struct pci_host_bridge_window *window, *n;
+       struct pci_host_bridge_window *window;
        struct resource *res;
        resource_size_t offset;
        char bus_addr[64];
        char *fmt;
-       u8      bus =3D PCI_BUSNUM(db);
+       struct device *parent =3D bridge->dev.parent;

        b =3D pci_alloc_bus(NULL);
        if (!b)
                return NULL;

-       b->sysdata =3D sysdata;
-       b->ops =3D ops;
-       b->number =3D b->busn_res.start =3D bus;
+       b->sysdata =3D bridge->sysdata;
I think bridge should be the b->sysdata here.
? what's the meaning?
Currently, bus->sysdata holds a pointer to the arch/driver host bridge =
structure, as passed
quoted
in pci_create_root_bus(). If you agree with my idea of wrapping the hos=
t bridge driver
quoted
structure around the pci_host_bridge, then we will always have a way of=
 retrieving that
quoted
information; but for backwards compatibility we could set bus->sysdata =
to be the bridge.
quoted
Then existing macros that convert sysdata to pci_controller can be reus=
ed after being
quoted
updated.
=20
I think wrapping the host bridge driver structure around the pci_host_bri=
dge could help
us to find the private pci_controller, but in this case, pci_host_bridge =
is not a pointer
so we put all pci_host_bridge init stuff in host drivers ?=20
Of course we put pci_host_bridge init *calls* in the host drivers because w=
e need to do host
driver specific initialisation there anyway.=20
And if we still use arch spec
macros convert ssydata to pci_controller, so what's the greatest advantag=
e ?

Agree, the macro is not useful unless we have a common pci_controller struc=
ture. Sorry about
the noise.
=20
If we move domain and msi_chip out of sysdata, what's other things in sys=
data still need us
to convert in PCI core ?
I've never said we need to keep sysdata. From my discussion with Bjorn a ye=
ar ago the idea was
to put the sysdata members into pci_host_bridge structure and remove sysdat=
a member from pci_bus.
pci_scan_root_bus() can still get a parameter called sysdata if we want, bu=
t it will be a
struct pci_host_bridge * type.

Best regards,
Liviu
=20
=20
=20
quoted
Best regards,
Liviu
quoted
quoted
quoted
+       b->ops =3D bridge->ops;
See comment above why I don't think this is necessary.
quoted
+       b->number =3D b->busn_res.start =3D bridge->busnum;
        pci_bus_assign_domain_nr(b, parent);
-       b2 =3D pci_find_bus(pci_domain_nr(b), bus);
+       bridge->domain =3D pci_domain_nr(b);
Do you really want to overwrite the bridge's domain with the one from=
 a bus that
quoted
quoted
quoted
could possibly be rejected a couple of lines further down?

As an asside: if we are doing the split of pci_host_bridge from root =
bus creation
quoted
quoted
quoted
it is worth in my opinion to move the domain setup in pci_create_host=
_bridge()
quoted
quoted
quoted
and stop fiddling with it here.

Hi Liviu, these lines just temporary, I will remove it after all host =
drivers
quoted
quoted
save its domain in pci_host_bridge.

quoted
Otherwise it looks to me like you are heading in the right direction.
Thanks!
Yijing.
quoted
Best regards,
Liviu
quoted
+       b2 =3D pci_find_bus(pci_domain_nr(b), bridge->busnum);
        if (b2) {
                /* If we already got to this bus through a different=
 bridge, ignore it */
quoted
quoted
quoted
quoted
                dev_dbg(&b2->dev, "bus already known\n");
                goto err_out;
        }

-       bridge =3D pci_alloc_host_bridge(b);
-       if (!bridge)
-               goto err_out;
-
-       bridge->dev.parent =3D parent;
-       bridge->dev.release =3D pci_release_host_bridge_dev;
-       dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b),=
 bus);
quoted
quoted
quoted
quoted
-       error =3D pcibios_root_bridge_prepare(bridge);
-       if (error) {
-               kfree(bridge);
-               goto err_out;
-       }
-
-       error =3D device_register(&bridge->dev);
-       if (error) {
-               put_device(&bridge->dev);
-               goto err_out;
-       }
        b->bridge =3D get_device(&bridge->dev);
        device_enable_async_suspend(b->bridge);
        pci_set_bus_of_node(b);
@@ -1950,7 +1899,7 @@ struct pci_bus *pci_create_root_bus(struct dev=
ice *parent, u32 db,
quoted
quoted
quoted
quoted

        b->dev.class =3D &pcibus_class;
        b->dev.parent =3D b->bridge;
-       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
+       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), b->numb=
er);
quoted
quoted
quoted
quoted
        error =3D device_register(&b->dev);
        if (error)
                goto class_dev_reg_err;
@@ -1966,12 +1915,11 @@ struct pci_bus *pci_create_root_bus(struct d=
evice *parent, u32 db,
quoted
quoted
quoted
quoted
                printk(KERN_INFO "PCI host bridge to bus %s\n", dev_=
name(&b->dev));
quoted
quoted
quoted
quoted

        /* Add initial resources to the bus */
-       list_for_each_entry_safe(window, n, resources, list) {
-               list_move_tail(&window->list, &bridge->windows);
+       list_for_each_entry(window, &bridge->windows, list) {
                res =3D window->res;
                offset =3D window->offset;
                if (res->flags & IORESOURCE_BUS)
-                       pci_bus_insert_busn_res(b, bus, res->end);
+                       pci_bus_insert_busn_res(b, b->number, res->e=
nd);
quoted
quoted
quoted
quoted
                else
                        pci_bus_add_resource(b, res, 0);
                if (offset) {
@@ -2001,6 +1949,25 @@ err_out:
        return NULL;
 }

+struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
+               struct pci_ops *ops, void *sysdata, struct list_head=
 *resources)
quoted
quoted
quoted
quoted
+{
+       struct pci_host_bridge *host;
+
+       host =3D pci_create_host_bridge(parent, bus, ops,
+                       sysdata ,resources);
+       if (!host)
+               return NULL;
+
+       host->bus =3D __pci_create_root_bus(host);
+       if (!host->bus) {
+               pci_free_host_bridge(host);
+               return NULL;
+       }
+
+       return host->bus;
+}
+
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max=
)
quoted
quoted
quoted
quoted
 {
        struct resource *res =3D &b->busn_res;
@@ -2069,40 +2036,37 @@ struct pci_bus *pci_scan_root_bus(struct dev=
ice *parent, u32 db,
quoted
quoted
quoted
quoted
 {
        struct pci_host_bridge_window *window;
        bool found =3D false;
-       struct pci_bus *b;
-       LIST_HEAD(default_res);
+       struct pci_host_bridge *host;
        int max;

-       if (!resources) {
-               pci_add_resource(&default_res, &ioport_resource);
-               pci_add_resource(&default_res, &iomem_resource);
-               pci_add_resource(&default_res, &busn_resource);
-       } else {
-               list_for_each_entry(window, resources, list)
-                       if (window->res->flags & IORESOURCE_BUS) {
-                               found =3D true;
-                               break;
-                       }
-       }
+       host =3D pci_create_host_bridge(parent, db, ops, sysdata, re=
sources);
quoted
quoted
quoted
quoted
+       if (!host)
+               return NULL;

-       b =3D pci_create_root_bus(parent, db, ops, sysdata,
-                       resources ? resources : &default_res);
-       if (!b)
+       list_for_each_entry(window, &host->windows, list)
+               if (window->res->flags & IORESOURCE_BUS) {
+                       found =3D true;
+                       break;
+               }
+
+       host->bus =3D __pci_create_root_bus(host);
+       if (!host->bus) {
+               pci_free_host_bridge(host);
                return NULL;
+       }

        if (!found) {
-               dev_info(&b->dev,
+               dev_info(&host->bus->dev,
                 "No busn resource found for root bus, will use [bus=
 %02x-ff]\n",
quoted
quoted
quoted
quoted
                        PCI_BUSNUM(db));
-               pci_bus_insert_busn_res(b, PCI_BUSNUM(db), 255);
+               pci_bus_insert_busn_res(host->bus, PCI_BUSNUM(db), 2=
55);
quoted
quoted
quoted
quoted
        }

-       max =3D pci_scan_child_bus(b);
-
+       max =3D pci_scan_child_bus(host->bus);
        if (!found)
-               pci_bus_update_busn_res_end(b, max);
+               pci_bus_update_busn_res_end(host->bus, max);

-       return b;
+       return host->bus;
 }
 EXPORT_SYMBOL(pci_scan_root_bus);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 8b11b38..daa7f40 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -402,7 +402,12 @@ struct pci_host_bridge_window {
 struct pci_host_bridge {
        struct device dev;
        struct pci_bus *bus;            /* root bus */
+       struct list_head list;
        struct list_head windows;       /* pci_host_bridge_windows *=
/
quoted
quoted
quoted
quoted
+       int busnum;
+       int domain;
+       void *sysdata;
+       struct pci_ops *ops;
        void (*release_fn)(struct pci_host_bridge *);
        void *release_data;
 };
@@ -413,7 +418,9 @@ void pci_set_host_bridge_release(struct pci_host=
_bridge *bridge,
quoted
quoted
quoted
quoted
                     void *release_data);

 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
-
+struct pci_host_bridge *pci_create_host_bridge(
+               struct device *parent, u32 db, struct pci_ops *ops,
+               void *sys, struct list_head *resources);
 /*
  * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that =
correspond
quoted
quoted
quoted
quoted
  * to P2P or CardBus bridge windows) go in a table.  Additional one=
s (for
quoted
quoted
quoted
quoted
@@ -770,6 +777,8 @@ void pci_bus_add_devices(const struct pci_bus *b=
us);
quoted
quoted
quoted
quoted
 struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
                                    struct pci_ops *ops, void *sysda=
ta,
quoted
quoted
quoted
quoted
                                    struct list_head *resources);
+struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *host)=
;
quoted
quoted
quoted
quoted
+void pci_free_host_bridge(struct pci_host_bridge *host);
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax)=
;
quoted
quoted
quoted
quoted
 int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
 void pci_bus_release_busn_res(struct pci_bus *b);
--
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-pci"=
 in
quoted
quoted
quoted
quoted
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
Thanks!
Yijing

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" i=
n
quoted
quoted
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
=20
=20
--
Thanks!
Yijing
=20
=20
--=20
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    =C2=AF\_(=E3=83=84)_/=C2=AF

Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces

From: Tomasz Nowicki <hidden>
Date: 2014-11-20 11:54:58

On 17.11.2014 15:13, Arnd Bergmann wrote:
On Monday 17 November 2014 18:21:34 Yijing Wang wrote:
quoted
This series is based Linux 3.18-rc1 and Lorenzo Pieralisi's
arm PCI domain cleanup patches, link:
https://patchwork.ozlabs.org/patch/407585/

Current pci scan interfaces like pci_scan_root_bus() and directly
call pci_create_root_bus()/pci_scan_child_bus() lack flexiblity.
Some platform infos like PCI domain and msi_chip have to be
associated to PCI bus by some arch specific function.
We want to make a generic pci_host_bridge, and make it hold
the platform infos or hook. Then we could eliminate the lots
of arch pci_domain_nr, also we could associate some platform
ops something like pci_get_msi_chip(struct pci_dev *dev)
with pci_host_bridge to avoid introduce arch weak functions.

This RFC version not for all platforms, just applied the new
scan interface in x86/arm/powerpc/ia64, I will refresh other
platforms after the core pci scan interfaces are ok.
I think overall this is a good direction to take, in particular
moving more things into struct pci_host_bridge so we can
slim down the architecture specific code.

I don't particularly like the way you use the 'pci_host_info'
to pass callback pointers and some of the generic information.
This duplicates some of the issues we are currently trying
to untangle in the arm32 code to make drivers easier to share
between architectures.

As a general approach, I'd rather see generic helper functions
being exported by the PCI core that a driver may or may not
call.
The way you split the interface between things that happen
before scanning the buses (pci_create_host_bridge) and
the actual scanning (__pci_create_root_bus, pci_scan_child_bus)
seems very helpful and I think we can expand that concept further:

- The normal pci_create_host_bridge() function can contain
   all of the DT scanning functions (finding bus/mem/io resources,
   finding the msi-parent), while drivers that don't depend on DT
   for this information can call the same function and fill the
   same things after they have the pci_host_bridge pointer.
How about finding PCI domain number (in the DT way) within pci_create_host_bridge() too ?

Tomasz

Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces

From: Tomasz Nowicki <hidden>
Date: 2014-11-20 12:01:15

On 18.11.2014 13:27, Arnd Bergmann wrote:
On Tuesday 18 November 2014 20:17:57 Yijing Wang wrote:
quoted
quoted
quoted
I hope platforms with ACPI or DT could both use pci_create_host_bridge().
Why we need to use two different ways to process it ?
These are completely different use cases:

a) For DT, we want loadable device drivers that start by probing a host
    bridge device which was added through the DT platform code. The
    driver is self-contained, and eventually we want to be able to unload
    it. We have lots of different per-soc drivers that require different
    quirks

b) For ACPI, the interface is defined in the ACPI spec across architectures
    and SoCs, we don't have host bridge drivers and the code that initializes
    the PCI is required early during boot and called from architecture
    code. There is no parent device, as ACPI sees PCI as a fundamental building
    block by itself, and there are no drivers because the firmware does
    the initial hardware setup, so we only have to access the config space.
Hmmm, I'm a little confused, so why you think ACPI host driver should not use
pci_create_host_bridge(), because ACPI PCI driver has no parent device ?
It's one of the difference. Having a parent device can certainly make your
life simpler, since you have devm_kzalloc(), dev_info(), etc. Coming from
the other end, I think ACPI needs PCI to be available during early boot,
at a time where we might not want pci_create_host_bridge() to do the
right thing.
Device pointer is not required for ACPI, struct acpi_device is all we need to get all that info. If pci_create_host_bridge() would be DT specific, it would be nice to have sth similar for ACPI but that is out of this patch set scope.

Tomasz

Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces

From: Liviu Dudau <hidden>
Date: 2014-11-20 12:09:01

On Thu, Nov 20, 2014 at 12:54:48PM +0100, Tomasz Nowicki wrote:
On 17.11.2014 15:13, Arnd Bergmann wrote:
quoted
On Monday 17 November 2014 18:21:34 Yijing Wang wrote:
quoted
This series is based Linux 3.18-rc1 and Lorenzo Pieralisi's
arm PCI domain cleanup patches, link:
https://patchwork.ozlabs.org/patch/407585/

Current pci scan interfaces like pci_scan_root_bus() and directly
call pci_create_root_bus()/pci_scan_child_bus() lack flexiblity.
Some platform infos like PCI domain and msi_chip have to be
associated to PCI bus by some arch specific function.
We want to make a generic pci_host_bridge, and make it hold
the platform infos or hook. Then we could eliminate the lots
of arch pci_domain_nr, also we could associate some platform
ops something like pci_get_msi_chip(struct pci_dev *dev)
with pci_host_bridge to avoid introduce arch weak functions.

This RFC version not for all platforms, just applied the new
scan interface in x86/arm/powerpc/ia64, I will refresh other
platforms after the core pci scan interfaces are ok.
I think overall this is a good direction to take, in particular
moving more things into struct pci_host_bridge so we can
slim down the architecture specific code.

I don't particularly like the way you use the 'pci_host_info'
to pass callback pointers and some of the generic information.
This duplicates some of the issues we are currently trying
to untangle in the arm32 code to make drivers easier to share
between architectures.

As a general approach, I'd rather see generic helper functions
being exported by the PCI core that a driver may or may not
call.
The way you split the interface between things that happen
before scanning the buses (pci_create_host_bridge) and
the actual scanning (__pci_create_root_bus, pci_scan_child_bus)
seems very helpful and I think we can expand that concept further:

- The normal pci_create_host_bridge() function can contain
  all of the DT scanning functions (finding bus/mem/io resources,
  finding the msi-parent), while drivers that don't depend on DT
  for this information can call the same function and fill the
  same things after they have the pci_host_bridge pointer.
How about finding PCI domain number (in the DT way) within
pci_create_host_bridge() too ?
It is an idea worth pursuing for the 99% of the cases. I would like
to understand the 1% of the time when we want a domain number to be
shared between two host bridges or the time when we want more than
one domain per bridge.

Is that possible? Is it useful? Is it already in practice?

Best regards,
Liviu
Tomasz
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
-- 
-------------------
   .oooO
   (   )
    \ (  Oooo.
     \_) (   )
          ) /
         (_/

 One small step
   for me ...

Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces

From: Tomasz Nowicki <hidden>
Date: 2014-11-20 12:53:55

On 20.11.2014 13:08, Liviu Dudau wrote:
On Thu, Nov 20, 2014 at 12:54:48PM +0100, Tomasz Nowicki wrote:
quoted
On 17.11.2014 15:13, Arnd Bergmann wrote:
quoted
On Monday 17 November 2014 18:21:34 Yijing Wang wrote:
quoted
This series is based Linux 3.18-rc1 and Lorenzo Pieralisi's
arm PCI domain cleanup patches, link:
https://patchwork.ozlabs.org/patch/407585/

Current pci scan interfaces like pci_scan_root_bus() and directly
call pci_create_root_bus()/pci_scan_child_bus() lack flexiblity.
Some platform infos like PCI domain and msi_chip have to be
associated to PCI bus by some arch specific function.
We want to make a generic pci_host_bridge, and make it hold
the platform infos or hook. Then we could eliminate the lots
of arch pci_domain_nr, also we could associate some platform
ops something like pci_get_msi_chip(struct pci_dev *dev)
with pci_host_bridge to avoid introduce arch weak functions.

This RFC version not for all platforms, just applied the new
scan interface in x86/arm/powerpc/ia64, I will refresh other
platforms after the core pci scan interfaces are ok.
I think overall this is a good direction to take, in particular
moving more things into struct pci_host_bridge so we can
slim down the architecture specific code.

I don't particularly like the way you use the 'pci_host_info'
to pass callback pointers and some of the generic information.
This duplicates some of the issues we are currently trying
to untangle in the arm32 code to make drivers easier to share
between architectures.

As a general approach, I'd rather see generic helper functions
being exported by the PCI core that a driver may or may not
call.
The way you split the interface between things that happen
before scanning the buses (pci_create_host_bridge) and
the actual scanning (__pci_create_root_bus, pci_scan_child_bus)
seems very helpful and I think we can expand that concept further:

- The normal pci_create_host_bridge() function can contain
   all of the DT scanning functions (finding bus/mem/io resources,
   finding the msi-parent), while drivers that don't depend on DT
   for this information can call the same function and fill the
   same things after they have the pci_host_bridge pointer.
How about finding PCI domain number (in the DT way) within
pci_create_host_bridge() too ?
It is an idea worth pursuing for the 99% of the cases. I would like
to understand the 1% of the time when we want a domain number to be
shared between two host bridges or the time when we want more than
one domain per bridge.
Even though we have shared domain, this should be resolved via DT calls, do I miss something ?
Is that possible? Is it useful? Is it already in practice?
This is good question... IMO:
1. Two host bridges can shared domain number if they are children of the same parent host bridge.
2. But I can not find good explanation for more than one domain per bridge.

Tomasz

Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces

From: Arnd Bergmann <arnd@arndb.de>
Date: 2014-11-20 13:15:50

On Thursday 20 November 2014 13:01:08 Tomasz Nowicki wrote:
On 18.11.2014 13:27, Arnd Bergmann wrote:
quoted
On Tuesday 18 November 2014 20:17:57 Yijing Wang wrote:
quoted
quoted
quoted
I hope platforms with ACPI or DT could both use pci_create_host_bridge().
Why we need to use two different ways to process it ?
These are completely different use cases:

a) For DT, we want loadable device drivers that start by probing a host
    bridge device which was added through the DT platform code. The
    driver is self-contained, and eventually we want to be able to unload
    it. We have lots of different per-soc drivers that require different
    quirks

b) For ACPI, the interface is defined in the ACPI spec across architectures
    and SoCs, we don't have host bridge drivers and the code that initializes
    the PCI is required early during boot and called from architecture
    code. There is no parent device, as ACPI sees PCI as a fundamental building
    block by itself, and there are no drivers because the firmware does
    the initial hardware setup, so we only have to access the config space.
Hmmm, I'm a little confused, so why you think ACPI host driver should not use
pci_create_host_bridge(), because ACPI PCI driver has no parent device ?
It's one of the difference. Having a parent device can certainly make your
life simpler, since you have devm_kzalloc(), dev_info(), etc. Coming from
the other end, I think ACPI needs PCI to be available during early boot,
at a time where we might not want pci_create_host_bridge() to do the
right thing.
Device pointer is not required for ACPI, struct acpi_device is all we 
need to get all that info. If pci_create_host_bridge() would be DT 
specific, it would be nice to have sth similar for ACPI but that is out 
of this patch set scope.
My point was more that we don't need to have something like it for ACPI,
since we don't get random drivers that need to be probed that way,
just one common implementation that calls into the PCI core. We should
of course share the common bits with pci_create_host_bridge() in some
form, but that can be done by moving the x86 pci_acpi_scan_root
function and/or acpi_pci_root_add() to a common place in drivers/pci
and then refactoring the internals.

	Arnd

Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces

From: Liviu Dudau <hidden>
Date: 2014-11-20 16:39:29

On Thu, Nov 20, 2014 at 01:53:48PM +0100, Tomasz Nowicki wrote:
On 20.11.2014 13:08, Liviu Dudau wrote:
quoted
On Thu, Nov 20, 2014 at 12:54:48PM +0100, Tomasz Nowicki wrote:
quoted
On 17.11.2014 15:13, Arnd Bergmann wrote:
quoted
On Monday 17 November 2014 18:21:34 Yijing Wang wrote:
quoted
This series is based Linux 3.18-rc1 and Lorenzo Pieralisi's
arm PCI domain cleanup patches, link:
https://patchwork.ozlabs.org/patch/407585/

Current pci scan interfaces like pci_scan_root_bus() and directly
call pci_create_root_bus()/pci_scan_child_bus() lack flexiblity.
Some platform infos like PCI domain and msi_chip have to be
associated to PCI bus by some arch specific function.
We want to make a generic pci_host_bridge, and make it hold
the platform infos or hook. Then we could eliminate the lots
of arch pci_domain_nr, also we could associate some platform
ops something like pci_get_msi_chip(struct pci_dev *dev)
with pci_host_bridge to avoid introduce arch weak functions.

This RFC version not for all platforms, just applied the new
scan interface in x86/arm/powerpc/ia64, I will refresh other
platforms after the core pci scan interfaces are ok.
I think overall this is a good direction to take, in particular
moving more things into struct pci_host_bridge so we can
slim down the architecture specific code.

I don't particularly like the way you use the 'pci_host_info'
to pass callback pointers and some of the generic information.
This duplicates some of the issues we are currently trying
to untangle in the arm32 code to make drivers easier to share
between architectures.

As a general approach, I'd rather see generic helper functions
being exported by the PCI core that a driver may or may not
call.
The way you split the interface between things that happen
before scanning the buses (pci_create_host_bridge) and
the actual scanning (__pci_create_root_bus, pci_scan_child_bus)
seems very helpful and I think we can expand that concept further:

- The normal pci_create_host_bridge() function can contain
  all of the DT scanning functions (finding bus/mem/io resources,
  finding the msi-parent), while drivers that don't depend on DT
  for this information can call the same function and fill the
  same things after they have the pci_host_bridge pointer.
How about finding PCI domain number (in the DT way) within
pci_create_host_bridge() too ?
It is an idea worth pursuing for the 99% of the cases. I would like
to understand the 1% of the time when we want a domain number to be
shared between two host bridges or the time when we want more than
one domain per bridge.
Even though we have shared domain, this should be resolved via DT calls, do
I miss something ?
If we only going to hold one domain number per host bridge, then no, you're
not missing anything.
quoted
Is that possible? Is it useful? Is it already in practice?
This is good question... IMO:
1. Two host bridges can shared domain number if they are children of the
same parent host bridge.
2. But I can not find good explanation for more than one domain per bridge.
Splitting a root bus into two or more "segments" ?

Best regards,
Liviu
Tomasz
-- 
-------------------
   .oooO
   (   )
    \ (  Oooo.
     \_) (   )
          ) /
         (_/

 One small step
   for me ...

Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()

From: Yijing Wang <hidden>
Date: 2014-11-21 02:55:56

quoted
quoted
pci_create_host_bridge() can get pci_host_bridge ops while pci_create_root_bus() gets
the bus ops. For find out the MSI controller, the domain number and any other HB
specific stuff, you use the HB ops. For config R/W acceses you use bus ops.
I want to unexport pci_create_root_bus() if we have pci_create_host_bridge().
That's fine, but the function signature doesn't change, right? And I think we should keep
pci_scan_root_bus() with the current signature as well (except change sysdata into a
struct pci_host_bridge *). We create the host bridge in one step, stuff it with all the
data that we need for scanning the root and associated busses, and then call pci_scan_root_bus().
pci_host_bridge has the ops from pci_create_host_bridge() and the root bus from pci_scan_root_bus().
Liviu, could you have some draft patches about replace sysdata with pci_host_bridge, so we could
discuss the details base it. :)
Hope this makes sense.
quoted
quoted
quoted
quoted
quoted
-struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
-               struct pci_ops *ops, void *sysdata, struct list_head *resources)
+struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *bridge)
 {
        int error;
-       struct pci_host_bridge *bridge;
        struct pci_bus *b, *b2;
-       struct pci_host_bridge_window *window, *n;
+       struct pci_host_bridge_window *window;
        struct resource *res;
        resource_size_t offset;
        char bus_addr[64];
        char *fmt;
-       u8      bus = PCI_BUSNUM(db);
+       struct device *parent = bridge->dev.parent;

        b = pci_alloc_bus(NULL);
        if (!b)
                return NULL;

-       b->sysdata = sysdata;
-       b->ops = ops;
-       b->number = b->busn_res.start = bus;
+       b->sysdata = bridge->sysdata;
I think bridge should be the b->sysdata here.
? what's the meaning?
Currently, bus->sysdata holds a pointer to the arch/driver host bridge structure, as passed
in pci_create_root_bus(). If you agree with my idea of wrapping the host bridge driver
structure around the pci_host_bridge, then we will always have a way of retrieving that
information; but for backwards compatibility we could set bus->sysdata to be the bridge.
Then existing macros that convert sysdata to pci_controller can be reused after being
updated.
I think wrapping the host bridge driver structure around the pci_host_bridge could help
us to find the private pci_controller, but in this case, pci_host_bridge is not a pointer
so we put all pci_host_bridge init stuff in host drivers ? 
Of course we put pci_host_bridge init *calls* in the host drivers because we need to do host
driver specific initialisation there anyway. 
quoted
And if we still use arch spec
macros convert ssydata to pci_controller, so what's the greatest advantage ?
Agree, the macro is not useful unless we have a common pci_controller structure. Sorry about
the noise.
quoted
If we move domain and msi_chip out of sysdata, what's other things in sysdata still need us
to convert in PCI core ?
I've never said we need to keep sysdata. From my discussion with Bjorn a year ago the idea was
to put the sysdata members into pci_host_bridge structure and remove sysdata member from pci_bus.
pci_scan_root_bus() can still get a parameter called sysdata if we want, but it will be a
struct pci_host_bridge * type.
Fine.
Best regards,
Liviu
quoted

quoted
Best regards,
Liviu
quoted
quoted
quoted
+       b->ops = bridge->ops;
See comment above why I don't think this is necessary.
quoted
+       b->number = b->busn_res.start = bridge->busnum;
        pci_bus_assign_domain_nr(b, parent);
-       b2 = pci_find_bus(pci_domain_nr(b), bus);
+       bridge->domain = pci_domain_nr(b);
Do you really want to overwrite the bridge's domain with the one from a bus that
could possibly be rejected a couple of lines further down?

As an asside: if we are doing the split of pci_host_bridge from root bus creation
it is worth in my opinion to move the domain setup in pci_create_host_bridge()
and stop fiddling with it here.

Hi Liviu, these lines just temporary, I will remove it after all host drivers
save its domain in pci_host_bridge.

quoted
Otherwise it looks to me like you are heading in the right direction.
Thanks!
Yijing.
quoted
Best regards,
Liviu
quoted
+       b2 = pci_find_bus(pci_domain_nr(b), bridge->busnum);
        if (b2) {
                /* If we already got to this bus through a different bridge, ignore it */
                dev_dbg(&b2->dev, "bus already known\n");
                goto err_out;
        }

-       bridge = pci_alloc_host_bridge(b);
-       if (!bridge)
-               goto err_out;
-
-       bridge->dev.parent = parent;
-       bridge->dev.release = pci_release_host_bridge_dev;
-       dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
-       error = pcibios_root_bridge_prepare(bridge);
-       if (error) {
-               kfree(bridge);
-               goto err_out;
-       }
-
-       error = device_register(&bridge->dev);
-       if (error) {
-               put_device(&bridge->dev);
-               goto err_out;
-       }
        b->bridge = get_device(&bridge->dev);
        device_enable_async_suspend(b->bridge);
        pci_set_bus_of_node(b);
@@ -1950,7 +1899,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,

        b->dev.class = &pcibus_class;
        b->dev.parent = b->bridge;
-       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
+       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), b->number);
        error = device_register(&b->dev);
        if (error)
                goto class_dev_reg_err;
@@ -1966,12 +1915,11 @@ struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
                printk(KERN_INFO "PCI host bridge to bus %s\n", dev_name(&b->dev));

        /* Add initial resources to the bus */
-       list_for_each_entry_safe(window, n, resources, list) {
-               list_move_tail(&window->list, &bridge->windows);
+       list_for_each_entry(window, &bridge->windows, list) {
                res = window->res;
                offset = window->offset;
                if (res->flags & IORESOURCE_BUS)
-                       pci_bus_insert_busn_res(b, bus, res->end);
+                       pci_bus_insert_busn_res(b, b->number, res->end);
                else
                        pci_bus_add_resource(b, res, 0);
                if (offset) {
@@ -2001,6 +1949,25 @@ err_out:
        return NULL;
 }

+struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
+               struct pci_ops *ops, void *sysdata, struct list_head *resources)
+{
+       struct pci_host_bridge *host;
+
+       host = pci_create_host_bridge(parent, bus, ops,
+                       sysdata ,resources);
+       if (!host)
+               return NULL;
+
+       host->bus = __pci_create_root_bus(host);
+       if (!host->bus) {
+               pci_free_host_bridge(host);
+               return NULL;
+       }
+
+       return host->bus;
+}
+
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
 {
        struct resource *res = &b->busn_res;
@@ -2069,40 +2036,37 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
 {
        struct pci_host_bridge_window *window;
        bool found = false;
-       struct pci_bus *b;
-       LIST_HEAD(default_res);
+       struct pci_host_bridge *host;
        int max;

-       if (!resources) {
-               pci_add_resource(&default_res, &ioport_resource);
-               pci_add_resource(&default_res, &iomem_resource);
-               pci_add_resource(&default_res, &busn_resource);
-       } else {
-               list_for_each_entry(window, resources, list)
-                       if (window->res->flags & IORESOURCE_BUS) {
-                               found = true;
-                               break;
-                       }
-       }
+       host = pci_create_host_bridge(parent, db, ops, sysdata, resources);
+       if (!host)
+               return NULL;

-       b = pci_create_root_bus(parent, db, ops, sysdata,
-                       resources ? resources : &default_res);
-       if (!b)
+       list_for_each_entry(window, &host->windows, list)
+               if (window->res->flags & IORESOURCE_BUS) {
+                       found = true;
+                       break;
+               }
+
+       host->bus = __pci_create_root_bus(host);
+       if (!host->bus) {
+               pci_free_host_bridge(host);
                return NULL;
+       }

        if (!found) {
-               dev_info(&b->dev,
+               dev_info(&host->bus->dev,
                 "No busn resource found for root bus, will use [bus %02x-ff]\n",
                        PCI_BUSNUM(db));
-               pci_bus_insert_busn_res(b, PCI_BUSNUM(db), 255);
+               pci_bus_insert_busn_res(host->bus, PCI_BUSNUM(db), 255);
        }

-       max = pci_scan_child_bus(b);
-
+       max = pci_scan_child_bus(host->bus);
        if (!found)
-               pci_bus_update_busn_res_end(b, max);
+               pci_bus_update_busn_res_end(host->bus, max);

-       return b;
+       return host->bus;
 }
 EXPORT_SYMBOL(pci_scan_root_bus);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 8b11b38..daa7f40 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -402,7 +402,12 @@ struct pci_host_bridge_window {
 struct pci_host_bridge {
        struct device dev;
        struct pci_bus *bus;            /* root bus */
+       struct list_head list;
        struct list_head windows;       /* pci_host_bridge_windows */
+       int busnum;
+       int domain;
+       void *sysdata;
+       struct pci_ops *ops;
        void (*release_fn)(struct pci_host_bridge *);
        void *release_data;
 };
@@ -413,7 +418,9 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
                     void *release_data);

 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
-
+struct pci_host_bridge *pci_create_host_bridge(
+               struct device *parent, u32 db, struct pci_ops *ops,
+               void *sys, struct list_head *resources);
 /*
  * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
  * to P2P or CardBus bridge windows) go in a table.  Additional ones (for
@@ -770,6 +777,8 @@ void pci_bus_add_devices(const struct pci_bus *bus);
 struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
                                    struct pci_ops *ops, void *sysdata,
                                    struct list_head *resources);
+struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *host);
+void pci_free_host_bridge(struct pci_host_bridge *host);
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
 int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
 void pci_bus_release_busn_res(struct pci_bus *b);
--
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
Thanks!
Yijing

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
Thanks!
Yijing

-- 
Thanks!
Yijing

Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces

From: Yijing Wang <hidden>
Date: 2014-11-21 02:59:06

On 2014/11/21 0:39, Liviu Dudau wrote:
On Thu, Nov 20, 2014 at 01:53:48PM +0100, Tomasz Nowicki wrote:
quoted
On 20.11.2014 13:08, Liviu Dudau wrote:
quoted
On Thu, Nov 20, 2014 at 12:54:48PM +0100, Tomasz Nowicki wrote:
quoted
On 17.11.2014 15:13, Arnd Bergmann wrote:
quoted
On Monday 17 November 2014 18:21:34 Yijing Wang wrote:
quoted
This series is based Linux 3.18-rc1 and Lorenzo Pieralisi's
arm PCI domain cleanup patches, link:
https://patchwork.ozlabs.org/patch/407585/

Current pci scan interfaces like pci_scan_root_bus() and directly
call pci_create_root_bus()/pci_scan_child_bus() lack flexiblity.
Some platform infos like PCI domain and msi_chip have to be
associated to PCI bus by some arch specific function.
We want to make a generic pci_host_bridge, and make it hold
the platform infos or hook. Then we could eliminate the lots
of arch pci_domain_nr, also we could associate some platform
ops something like pci_get_msi_chip(struct pci_dev *dev)
with pci_host_bridge to avoid introduce arch weak functions.

This RFC version not for all platforms, just applied the new
scan interface in x86/arm/powerpc/ia64, I will refresh other
platforms after the core pci scan interfaces are ok.
I think overall this is a good direction to take, in particular
moving more things into struct pci_host_bridge so we can
slim down the architecture specific code.

I don't particularly like the way you use the 'pci_host_info'
to pass callback pointers and some of the generic information.
This duplicates some of the issues we are currently trying
to untangle in the arm32 code to make drivers easier to share
between architectures.

As a general approach, I'd rather see generic helper functions
being exported by the PCI core that a driver may or may not
call.
The way you split the interface between things that happen
before scanning the buses (pci_create_host_bridge) and
the actual scanning (__pci_create_root_bus, pci_scan_child_bus)
seems very helpful and I think we can expand that concept further:

- The normal pci_create_host_bridge() function can contain
  all of the DT scanning functions (finding bus/mem/io resources,
  finding the msi-parent), while drivers that don't depend on DT
  for this information can call the same function and fill the
  same things after they have the pci_host_bridge pointer.
How about finding PCI domain number (in the DT way) within
pci_create_host_bridge() too ?
It is an idea worth pursuing for the 99% of the cases. I would like
to understand the 1% of the time when we want a domain number to be
shared between two host bridges or the time when we want more than
one domain per bridge.
Even though we have shared domain, this should be resolved via DT calls, do
I miss something ?
If we only going to hold one domain number per host bridge, then no, you're
not missing anything.
quoted
quoted
Is that possible? Is it useful? Is it already in practice?
This is good question... IMO:
1. Two host bridges can shared domain number if they are children of the
same parent host bridge.
2. But I can not find good explanation for more than one domain per bridge.
Splitting a root bus into two or more "segments" ?
It seems impossible.
Best regards,
Liviu
quoted
Tomasz

-- 
Thanks!
Yijing

Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()

From: Liviu Dudau <Liviu.Dudau@arm.com>
Date: 2014-11-21 09:53:20

On Fri, Nov 21, 2014 at 02:53:01AM +0000, Yijing Wang wrote:
quoted
quoted
quoted
pci_create_host_bridge() can get pci_host_bridge ops while pci_create=
_root_bus() gets
quoted
quoted
quoted
the bus ops. For find out the MSI controller, the domain number and a=
ny other HB
quoted
quoted
quoted
specific stuff, you use the HB ops. For config R/W acceses you use bu=
s ops.
quoted
quoted
quoted
I want to unexport pci_create_root_bus() if we have pci_create_host_br=
idge().
quoted
That's fine, but the function signature doesn't change, right? And I th=
ink we should keep
quoted
pci_scan_root_bus() with the current signature as well (except change s=
ysdata into a
quoted
struct pci_host_bridge *). We create the host bridge in one step, stuff=
 it with all the
quoted
data that we need for scanning the root and associated busses, and then=
 call pci_scan_root_bus().
quoted
pci_host_bridge has the ops from pci_create_host_bridge() and the root =
bus from pci_scan_root_bus().
=20
Liviu, could you have some draft patches about replace sysdata with pci_h=
ost_bridge, so we could
discuss the details base it. :)
Sure, I'll try to send something soon.

Best regards,
Liviu
=20
quoted
Hope this makes sense.
quoted
quoted
quoted
quoted
quoted
-struct pci_bus *pci_create_root_bus(struct device *parent, u32 db=
,
quoted
quoted
quoted
quoted
quoted
quoted
-               struct pci_ops *ops, void *sysdata, struct list_he=
ad *resources)
quoted
quoted
quoted
quoted
quoted
quoted
+struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *bri=
dge)
quoted
quoted
quoted
quoted
quoted
quoted
 {
        int error;
-       struct pci_host_bridge *bridge;
        struct pci_bus *b, *b2;
-       struct pci_host_bridge_window *window, *n;
+       struct pci_host_bridge_window *window;
        struct resource *res;
        resource_size_t offset;
        char bus_addr[64];
        char *fmt;
-       u8      bus =3D PCI_BUSNUM(db);
+       struct device *parent =3D bridge->dev.parent;

        b =3D pci_alloc_bus(NULL);
        if (!b)
                return NULL;

-       b->sysdata =3D sysdata;
-       b->ops =3D ops;
-       b->number =3D b->busn_res.start =3D bus;
+       b->sysdata =3D bridge->sysdata;
I think bridge should be the b->sysdata here.
? what's the meaning?
Currently, bus->sysdata holds a pointer to the arch/driver host bridg=
e structure, as passed
quoted
quoted
quoted
in pci_create_root_bus(). If you agree with my idea of wrapping the h=
ost bridge driver
quoted
quoted
quoted
structure around the pci_host_bridge, then we will always have a way =
of retrieving that
quoted
quoted
quoted
information; but for backwards compatibility we could set bus->sysdat=
a to be the bridge.
quoted
quoted
quoted
Then existing macros that convert sysdata to pci_controller can be re=
used after being
quoted
quoted
quoted
updated.
I think wrapping the host bridge driver structure around the pci_host_=
bridge could help
quoted
quoted
us to find the private pci_controller, but in this case, pci_host_brid=
ge is not a pointer
quoted
quoted
so we put all pci_host_bridge init stuff in host drivers ?
Of course we put pci_host_bridge init *calls* in the host drivers becau=
se we need to do host
quoted
driver specific initialisation there anyway.
quoted
And if we still use arch spec
macros convert ssydata to pci_controller, so what's the greatest advan=
tage ?
quoted
Agree, the macro is not useful unless we have a common pci_controller s=
tructure. Sorry about
quoted
the noise.
quoted
If we move domain and msi_chip out of sysdata, what's other things in =
sysdata still need us
quoted
quoted
to convert in PCI core ?
I've never said we need to keep sysdata. From my discussion with Bjorn =
a year ago the idea was
quoted
to put the sysdata members into pci_host_bridge structure and remove sy=
sdata member from pci_bus.
quoted
pci_scan_root_bus() can still get a parameter called sysdata if we want=
, but it will be a
quoted
struct pci_host_bridge * type.
=20
Fine.
=20
quoted
Best regards,
Liviu
quoted

quoted
Best regards,
Liviu
quoted
quoted
quoted
+       b->ops =3D bridge->ops;
See comment above why I don't think this is necessary.
quoted
+       b->number =3D b->busn_res.start =3D bridge->busnum;
        pci_bus_assign_domain_nr(b, parent);
-       b2 =3D pci_find_bus(pci_domain_nr(b), bus);
+       bridge->domain =3D pci_domain_nr(b);
Do you really want to overwrite the bridge's domain with the one fr=
om a bus that
quoted
quoted
quoted
quoted
quoted
could possibly be rejected a couple of lines further down?

As an asside: if we are doing the split of pci_host_bridge from roo=
t bus creation
quoted
quoted
quoted
quoted
quoted
it is worth in my opinion to move the domain setup in pci_create_ho=
st_bridge()
quoted
quoted
quoted
quoted
quoted
and stop fiddling with it here.

Hi Liviu, these lines just temporary, I will remove it after all hos=
t drivers
quoted
quoted
quoted
quoted
save its domain in pci_host_bridge.

quoted
Otherwise it looks to me like you are heading in the right directio=
n.
quoted
quoted
quoted
quoted
Thanks!
Yijing.
quoted
Best regards,
Liviu
quoted
+       b2 =3D pci_find_bus(pci_domain_nr(b), bridge->busnum);
        if (b2) {
                /* If we already got to this bus through a differe=
nt bridge, ignore it */
quoted
quoted
quoted
quoted
quoted
quoted
                dev_dbg(&b2->dev, "bus already known\n");
                goto err_out;
        }

-       bridge =3D pci_alloc_host_bridge(b);
-       if (!bridge)
-               goto err_out;
-
-       bridge->dev.parent =3D parent;
-       bridge->dev.release =3D pci_release_host_bridge_dev;
-       dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b=
), bus);
quoted
quoted
quoted
quoted
quoted
quoted
-       error =3D pcibios_root_bridge_prepare(bridge);
-       if (error) {
-               kfree(bridge);
-               goto err_out;
-       }
-
-       error =3D device_register(&bridge->dev);
-       if (error) {
-               put_device(&bridge->dev);
-               goto err_out;
-       }
        b->bridge =3D get_device(&bridge->dev);
        device_enable_async_suspend(b->bridge);
        pci_set_bus_of_node(b);
@@ -1950,7 +1899,7 @@ struct pci_bus *pci_create_root_bus(struct d=
evice *parent, u32 db,
quoted
quoted
quoted
quoted
quoted
quoted

        b->dev.class =3D &pcibus_class;
        b->dev.parent =3D b->bridge;
-       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
+       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), b->nu=
mber);
quoted
quoted
quoted
quoted
quoted
quoted
        error =3D device_register(&b->dev);
        if (error)
                goto class_dev_reg_err;
@@ -1966,12 +1915,11 @@ struct pci_bus *pci_create_root_bus(struct=
 device *parent, u32 db,
quoted
quoted
quoted
quoted
quoted
quoted
                printk(KERN_INFO "PCI host bridge to bus %s\n", de=
v_name(&b->dev));
quoted
quoted
quoted
quoted
quoted
quoted

        /* Add initial resources to the bus */
-       list_for_each_entry_safe(window, n, resources, list) {
-               list_move_tail(&window->list, &bridge->windows);
+       list_for_each_entry(window, &bridge->windows, list) {
                res =3D window->res;
                offset =3D window->offset;
                if (res->flags & IORESOURCE_BUS)
-                       pci_bus_insert_busn_res(b, bus, res->end);
+                       pci_bus_insert_busn_res(b, b->number, res-=
end);
quoted
quoted
quoted
quoted
quoted
quoted
                else
                        pci_bus_add_resource(b, res, 0);
                if (offset) {
@@ -2001,6 +1949,25 @@ err_out:
        return NULL;
 }

+struct pci_bus *pci_create_root_bus(struct device *parent, u32 bu=
s,
quoted
quoted
quoted
quoted
quoted
quoted
+               struct pci_ops *ops, void *sysdata, struct list_he=
ad *resources)
quoted
quoted
quoted
quoted
quoted
quoted
+{
+       struct pci_host_bridge *host;
+
+       host =3D pci_create_host_bridge(parent, bus, ops,
+                       sysdata ,resources);
+       if (!host)
+               return NULL;
+
+       host->bus =3D __pci_create_root_bus(host);
+       if (!host->bus) {
+               pci_free_host_bridge(host);
+               return NULL;
+       }
+
+       return host->bus;
+}
+
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_m=
ax)
quoted
quoted
quoted
quoted
quoted
quoted
 {
        struct resource *res =3D &b->busn_res;
@@ -2069,40 +2036,37 @@ struct pci_bus *pci_scan_root_bus(struct d=
evice *parent, u32 db,
quoted
quoted
quoted
quoted
quoted
quoted
 {
        struct pci_host_bridge_window *window;
        bool found =3D false;
-       struct pci_bus *b;
-       LIST_HEAD(default_res);
+       struct pci_host_bridge *host;
        int max;

-       if (!resources) {
-               pci_add_resource(&default_res, &ioport_resource);
-               pci_add_resource(&default_res, &iomem_resource);
-               pci_add_resource(&default_res, &busn_resource);
-       } else {
-               list_for_each_entry(window, resources, list)
-                       if (window->res->flags & IORESOURCE_BUS) {
-                               found =3D true;
-                               break;
-                       }
-       }
+       host =3D pci_create_host_bridge(parent, db, ops, sysdata, =
resources);
quoted
quoted
quoted
quoted
quoted
quoted
+       if (!host)
+               return NULL;

-       b =3D pci_create_root_bus(parent, db, ops, sysdata,
-                       resources ? resources : &default_res);
-       if (!b)
+       list_for_each_entry(window, &host->windows, list)
+               if (window->res->flags & IORESOURCE_BUS) {
+                       found =3D true;
+                       break;
+               }
+
+       host->bus =3D __pci_create_root_bus(host);
+       if (!host->bus) {
+               pci_free_host_bridge(host);
                return NULL;
+       }

        if (!found) {
-               dev_info(&b->dev,
+               dev_info(&host->bus->dev,
                 "No busn resource found for root bus, will use [b=
us %02x-ff]\n",
quoted
quoted
quoted
quoted
quoted
quoted
                        PCI_BUSNUM(db));
-               pci_bus_insert_busn_res(b, PCI_BUSNUM(db), 255);
+               pci_bus_insert_busn_res(host->bus, PCI_BUSNUM(db),=
 255);
quoted
quoted
quoted
quoted
quoted
quoted
        }

-       max =3D pci_scan_child_bus(b);
-
+       max =3D pci_scan_child_bus(host->bus);
        if (!found)
-               pci_bus_update_busn_res_end(b, max);
+               pci_bus_update_busn_res_end(host->bus, max);

-       return b;
+       return host->bus;
 }
 EXPORT_SYMBOL(pci_scan_root_bus);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 8b11b38..daa7f40 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -402,7 +402,12 @@ struct pci_host_bridge_window {
 struct pci_host_bridge {
        struct device dev;
        struct pci_bus *bus;            /* root bus */
+       struct list_head list;
        struct list_head windows;       /* pci_host_bridge_windows=
 */
quoted
quoted
quoted
quoted
quoted
quoted
+       int busnum;
+       int domain;
+       void *sysdata;
+       struct pci_ops *ops;
        void (*release_fn)(struct pci_host_bridge *);
        void *release_data;
 };
@@ -413,7 +418,9 @@ void pci_set_host_bridge_release(struct pci_ho=
st_bridge *bridge,
quoted
quoted
quoted
quoted
quoted
quoted
                     void *release_data);

 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
-
+struct pci_host_bridge *pci_create_host_bridge(
+               struct device *parent, u32 db, struct pci_ops *ops=
,
quoted
quoted
quoted
quoted
quoted
quoted
+               void *sys, struct list_head *resources);
 /*
  * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those tha=
t correspond
quoted
quoted
quoted
quoted
quoted
quoted
  * to P2P or CardBus bridge windows) go in a table.  Additional o=
nes (for
quoted
quoted
quoted
quoted
quoted
quoted
@@ -770,6 +777,8 @@ void pci_bus_add_devices(const struct pci_bus =
*bus);
quoted
quoted
quoted
quoted
quoted
quoted
 struct pci_bus *pci_create_root_bus(struct device *parent, u32 bu=
s,
quoted
quoted
quoted
quoted
quoted
quoted
                                    struct pci_ops *ops, void *sys=
data,
quoted
quoted
quoted
quoted
quoted
quoted
                                    struct list_head *resources);
+struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *hos=
t);
quoted
quoted
quoted
quoted
quoted
quoted
+void pci_free_host_bridge(struct pci_host_bridge *host);
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busma=
x);
quoted
quoted
quoted
quoted
quoted
quoted
 int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
 void pci_bus_release_busn_res(struct pci_bus *b);
--
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-pc=
i" in
quoted
quoted
quoted
quoted
quoted
quoted
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
Thanks!
Yijing

--
To unsubscribe from this list: send the line "unsubscribe linux-pci"=
 in
quoted
quoted
quoted
quoted
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
Thanks!
Yijing
=20
=20
--
Thanks!
Yijing
=20
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
=20
--=20
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    =C2=AF\_(=E3=83=84)_/=C2=AF
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help