LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Thierry Reding, Yijing Wang,
	Suravee.Suthikulpanit, Yijing Wang, linux-ia64, Thomas Gleixner,
	Wuyun, linuxppc-dev, linux-arm-kernel
In-Reply-To: <1416219710-26088-1-git-send-email-wangyijing@huawei.com>

From: Yijing Wang <wangyijing0307@gmail.com>

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 <wangyijing@huawei.com>
---
 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

^ permalink raw reply related

* [RFC PATCH 09/16] PCI: Associate .get_msi_ctrl() with pci_host_bridge
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Thierry Reding, Yijing Wang,
	Suravee.Suthikulpanit, Yijing Wang, linux-ia64, Thomas Gleixner,
	Wuyun, linuxppc-dev, linux-arm-kernel
In-Reply-To: <1416219710-26088-1-git-send-email-wangyijing@huawei.com>

From: Yijing Wang <wangyijing0307@gmail.com>

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 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

^ permalink raw reply related

* [RFC PATCH 02/16] PCI: Use pci_scan_root_bus() instead of pci_scan_bus()
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Thierry Reding, Yijing Wang,
	Suravee.Suthikulpanit, Yijing Wang, linux-ia64, Thomas Gleixner,
	Wuyun, linuxppc-dev, linux-arm-kernel
In-Reply-To: <1416219710-26088-1-git-send-email-wangyijing@huawei.com>

From: Yijing Wang <wangyijing0307@gmail.com>

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 <wangyijing@huawei.com>
---
 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

^ permalink raw reply related

* [RFC PATCH 10/16] PCI: Add of_scan_bus() to pci_host_info
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Thierry Reding, Suravee.Suthikulpanit,
	Yijing Wang, linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev,
	linux-arm-kernel
In-Reply-To: <1416219710-26088-1-git-send-email-wangyijing@huawei.com>

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

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 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

^ permalink raw reply related

* [RFC PATCH 08/16] PCI: Introduce pci_scan_host_bridge() and pci_host_info
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Thierry Reding, Yijing Wang,
	Suravee.Suthikulpanit, Yijing Wang, linux-ia64, Thomas Gleixner,
	Wuyun, linuxppc-dev, linux-arm-kernel
In-Reply-To: <1416219710-26088-1-git-send-email-wangyijing@huawei.com>

From: Yijing Wang <wangyijing0307@gmail.com>

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 <wangyijing@huawei.com>
---
 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

^ permalink raw reply related

* [RFC PATCH 03/16] PCI: Clean up pci_scan_bus()
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Thierry Reding, Suravee.Suthikulpanit,
	Yijing Wang, linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev,
	linux-arm-kernel
In-Reply-To: <1416219710-26088-1-git-send-email-wangyijing@huawei.com>

No one uses it, clean up.

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 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

^ permalink raw reply related

* [RFC PATCH 05/16] PCI: Use pci_scan_root_bus() instead of pci_scan_bus_parented()
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Thierry Reding, Suravee.Suthikulpanit,
	Yijing Wang, linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev,
	linux-arm-kernel
In-Reply-To: <1416219710-26088-1-git-send-email-wangyijing@huawei.com>

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

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 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

^ permalink raw reply related

* [RFC PATCH 12/16] ia64/PCI: Remove the redundant bus variable
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Thierry Reding, Suravee.Suthikulpanit,
	Yijing Wang, linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev,
	linux-arm-kernel
In-Reply-To: <1416219710-26088-1-git-send-email-wangyijing@huawei.com>

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 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

^ permalink raw reply related

* [RFC PATCH 06/16] PCI: Use u32 type to combine PCI domain and bus number
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Thierry Reding, Suravee.Suthikulpanit,
	Yijing Wang, linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev,
	linux-arm-kernel
In-Reply-To: <1416219710-26088-1-git-send-email-wangyijing@huawei.com>

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 <wangyijing@huawei.com>
---
 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

^ permalink raw reply related

* [RFC PATCH 11/16] x86/PCI: Use pci_scan_host_bridge() instead of pci_create_root_bus()
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Thierry Reding, Suravee.Suthikulpanit,
	Yijing Wang, linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev,
	linux-arm-kernel
In-Reply-To: <1416219710-26088-1-git-send-email-wangyijing@huawei.com>

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

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 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

^ permalink raw reply related

* [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Thierry Reding, Suravee.Suthikulpanit,
	Yijing Wang, linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev,
	linux-arm-kernel
In-Reply-To: <1416219710-26088-1-git-send-email-wangyijing@huawei.com>

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 <wangyijing@huawei.com>
---
 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

^ permalink raw reply related

* [RFC PATCH 04/16] PCI: Rip out pci_bus_add_devices() from pci_scan_root_bus()
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Thierry Reding, Suravee.Suthikulpanit,
	Yijing Wang, linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev,
	linux-arm-kernel
In-Reply-To: <1416219710-26088-1-git-send-email-wangyijing@huawei.com>

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 <wangyijing@huawei.com>
---
 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

^ permalink raw reply related

* [RFC PATCH 15/16] arm/PCI: Use pci_scan_host_bridge() instead of pci_scan_root_bus()
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Thierry Reding, Suravee.Suthikulpanit,
	Yijing Wang, linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev,
	linux-arm-kernel
In-Reply-To: <1416219710-26088-1-git-send-email-wangyijing@huawei.com>

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 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

^ permalink raw reply related

* [RFC PATCH 14/16] arm/PCI: Introduce pci_get_domain_nr()
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Thierry Reding, Suravee.Suthikulpanit,
	Yijing Wang, linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev,
	linux-arm-kernel
In-Reply-To: <1416219710-26088-1-git-send-email-wangyijing@huawei.com>

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 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

^ permalink raw reply related

* [RFC PATCH 00/16] Refine PCI host bridge scan interfaces
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Thierry Reding, Suravee.Suthikulpanit,
	Yijing Wang, linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev,
	linux-arm-kernel

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(-)

^ permalink raw reply

* [RFC PATCH 13/16] ia64/PCI: Use pci_scan_host_bridge() to refactor pci_acpi_scan_root()
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Thierry Reding, Suravee.Suthikulpanit,
	Yijing Wang, linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev,
	linux-arm-kernel
In-Reply-To: <1416219710-26088-1-git-send-email-wangyijing@huawei.com>

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 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

^ permalink raw reply related

* [RFC PATCH 16/16] powerpc/PCI: Use pci_scan_host_bridge() to scan PCI bus
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Thierry Reding, Suravee.Suthikulpanit,
	Yijing Wang, linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev,
	linux-arm-kernel
In-Reply-To: <1416219710-26088-1-git-send-email-wangyijing@huawei.com>

Signed-off-by: Yijing Wang <wangyijing@huawei.com>
---
 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

^ permalink raw reply related

* Re: [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources
From: Arnd Bergmann @ 2014-11-17 10:08 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Bjorn Helgaas, Thierry Reding,
	Suravee.Suthikulpanit, Yijing Wang, linux-ia64, Thomas Gleixner,
	Wuyun, linuxppc-dev, Yijing Wang
In-Reply-To: <1416219710-26088-2-git-send-email-wangyijing@huawei.com>

On Monday 17 November 2014 18:21:35 Yijing Wang wrote:
> -       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

^ permalink raw reply

* Re: [PATCH 2/2] powerpc/mpc85xx: Add DPAA Q/BMan support to device tree(s)
From: Emil Medve @ 2014-11-17 10:31 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, Geoff Thorpe, Poonam Aggrwal, Chunhe Lan
In-Reply-To: <1415914923.15957.64.camel@freescale.com>

Hello Scott,


On 11/13/2014 03:42 PM, Scott Wood wrote:
> On Thu, 2014-11-13 at 03:21 -0600, Emil Medve wrote:
>> From: Kumar Gala <galak@kernel.crashing.org>
>>
>> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
>> Signed-off-by: Geoff Thorpe <Geoff.Thorpe@freescale.com>
>> Signed-off-by: Hai-Ying Wang <Haiying.Wang@freescale.com>
>> Signed-off-by: Chunhe Lan <Chunhe.Lan@freescale.com>
>> Signed-off-by: Poonam Aggrwal <poonam.aggrwal@freescale.com>
>> Signed-off-by: Emil Medve <Emilian.Medve@Freescale.com>
>> Change-Id: If643fa5ba0a903aef8f5056a2c90ebecc995b760
> 
> I suspect these patches are changed quite a bit from Kumar's version...

Across SDK releases I've been trying retain the authors names and the
'Signed-off-by' list is the only place that can accommodate them all.
Kumar is the first author, and besides this exercise the most significant

> It's good to note changes after the listed author has stopped being
> involved, so they don't get the blame for anything they wouldn't have
> put in there.

Bah. Most of the sordid history is lost

> Why is the devicetree list not CCed?

For no good reason. Will add it for the next version

>> diff --git a/arch/powerpc/boot/dts/b4qds.dtsi b/arch/powerpc/boot/dts/b4qds.dtsi
>> index 6188583..48c3fb4 100644
>> --- a/arch/powerpc/boot/dts/b4qds.dtsi
>> +++ b/arch/powerpc/boot/dts/b4qds.dtsi
>> @@ -1,7 +1,7 @@
>>  /*
>>   * B4420DS Device Tree Source
>>   *
>> - * Copyright 2012 Freescale Semiconductor, Inc.
>> + * Copyright 2012 - 2014 Freescale Semiconductor, Inc.
>>   *
>>   * Redistribution and use in source and binary forms, with or without
>>   * modification, are permitted provided that the following conditions are met:
>> @@ -38,6 +38,7 @@
>>  	#address-cells = <2>;
>>  	#size-cells = <2>;
>>  	interrupt-parent = <&mpic>;
>> +	reserved-ranges;
> 
> I don't see reserved-ranges documented anywhere,

Some digging through the git log will add some context to it

> and from the code in arch/powerpc I don't see how it has any effect
> when empty.

When I first wrote these nodes there was a bug that got fixed since
here: 'edba274 powerpc: fix skipping call to
early_init_fdt_scan_reserved_mem'. I'll remove the property in the next
version of the patch

>> +	reserved-memory {
>> +		#address-cells = <2>;
>> +		#size-cells = <2>;
>> +		ranges;
>> +
>> +		bman_fbpr: bman-fbpr {
>> +			compatible = "fsl,bman-fbpr";
>> +			alloc-ranges = <0 0 0xffff 0xffffffff>;
>> +			size = <0 0x1000000>;
>> +			alignment = <0 0x1000000>;
>> +			no-map;
>> +			reusable;
>> +		};
>> +		qman_fqd: qman-fqd {
>> +			compatible = "fsl,qman-fqd";
>> +			alloc-ranges = <0 0 0xffff 0xffffffff>;
>> +			size = <0 0x400000>;
>> +			alignment = <0 0x400000>;
>> +			no-map;
>> +			reusable;
>> +		};
>> +		qman_pfdr: qman-pfdr {
>> +			compatible = "fsl,qman-pfdr";
>> +			alloc-ranges = <0 0 0xffff 0xffffffff>;
>> +			size = <0 0x2000000>;
>> +			alignment = <0 0x2000000>;
>> +			no-map;
>> +			reusable;
>> +		};
>> +	};
> 
> no-map and reusable don't make sense together.  How can the OS reuse the
> memory if it can't map it?

Perhaps I've been reading/speculating(?) too much about it. Now granted
the code is still young (?), but in between "under the control of the
device driver using the region" and "the device driver(s) owning the
region need to be able to reclaim it back" it sort of made sense

> no-map is burdensome (and I believe not yet implemented) on mpc85xx,
> where we want to use huge TLB entries to cover all of (low) memory.  Is
> it really needed?

I'm thinking no-map would be part of having/making this reserved memory
into a different coherency domain then the... everything else

> What do we gain from specifying reusable here?

I guess the obvious of having this memory usable for something else when
the B/QMan drivers don't use it

> How is it actually supposed to work?

You mean how should one implement 'reusable'?

>> diff --git a/arch/powerpc/boot/dts/fsl/b4420si-post.dtsi b/arch/powerpc/boot/dts/fsl/b4420si-post.dtsi
>> index 86161ae..0f56263 100644
>> --- a/arch/powerpc/boot/dts/fsl/b4420si-post.dtsi
>> +++ b/arch/powerpc/boot/dts/fsl/b4420si-post.dtsi
>> @@ -1,7 +1,7 @@
>>  /*
>>   * B4420 Silicon/SoC Device Tree Source (post include)
>>   *
>> - * Copyright 2012 Freescale Semiconductor, Inc.
>> + * Copyright 2012 - 2014 Freescale Semiconductor, Inc.
>>   *
>>   * Redistribution and use in source and binary forms, with or without
>>   * modification, are permitted provided that the following conditions are met:
>> diff --git a/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi b/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi
>> index 338af7e..f392949 100644
>> --- a/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi
>> +++ b/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi
>> @@ -1,7 +1,7 @@
>>  /*
>>   * B4420 Silicon/SoC Device Tree Source (pre include)
>>   *
>> - * Copyright 2012 Freescale Semiconductor, Inc.
>> + * Copyright 2012 - 2014 Freescale Semiconductor, Inc.
>>   *
>>   * Redistribution and use in source and binary forms, with or without
>>   * modification, are permitted provided that the following conditions are met:
> 
> Why are you updating the copyright year on files you didn't change?

This leaked in here as I was splitting patches. I'll remove it here and
elsewhere


Cheers,

^ permalink raw reply

* Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
From: Arnd Bergmann @ 2014-11-17 10:56 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Bjorn Helgaas, Thierry Reding,
	Suravee.Suthikulpanit, Yijing Wang, linux-ia64, Thomas Gleixner,
	Wuyun, linux-arm-kernel
In-Reply-To: <1416219710-26088-8-git-send-email-wangyijing@huawei.com>

On Monday 17 November 2014 18:21:41 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.
> 
> Signed-off-by: Yijing Wang <wangyijing@huawei.com>
> ---
>  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.

> +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.

> +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).

> +	host = kzalloc(sizeof(*host), GFP_KERNEL);
> +	if (!host)
> +		return NULL;

devm_kzalloc maybe?

> +	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?

> 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

^ permalink raw reply

* Re: [RFC PATCH 14/16] arm/PCI: Introduce pci_get_domain_nr()
From: Lorenzo Pieralisi @ 2014-11-17 12:08 UTC (permalink / raw)
  To: Yijing Wang
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci@vger.kernel.org,
	x86@kernel.org, linux-kernel@vger.kernel.org, huxinwei@huawei.com,
	Thierry Reding, suravee.suthikulpanit@amd.com, Bjorn Helgaas,
	linux-ia64@vger.kernel.org, Thomas Gleixner, Wuyun,
	linuxppc-dev@lists.ozlabs.org,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <1416219710-26088-15-git-send-email-wangyijing@huawei.com>

On Mon, Nov 17, 2014 at 10:21:48AM +0000, Yijing Wang wrote:
> Signed-off-by: Yijing Wang <wangyijing@huawei.com>
> ---
>  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
> 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=
)
> +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=
)
> +{
> +=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

^ permalink raw reply

* Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces
From: Arnd Bergmann @ 2014-11-17 14:13 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Bjorn Helgaas, Thierry Reding,
	Suravee.Suthikulpanit, Yijing Wang, linux-ia64, Thomas Gleixner,
	Wuyun, linuxppc-dev
In-Reply-To: <1416219710-26088-1-git-send-email-wangyijing@huawei.com>

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

^ permalink raw reply

* Re: [RFC PATCH 09/16] PCI: Associate .get_msi_ctrl() with pci_host_bridge
From: Lorenzo Pieralisi @ 2014-11-17 15:03 UTC (permalink / raw)
  To: Yijing Wang
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci@vger.kernel.org,
	x86@kernel.org, linux-kernel@vger.kernel.org, huxinwei@huawei.com,
	Thierry Reding, linux-arm-kernel@lists.infradead.org,
	suravee.suthikulpanit@amd.com, Bjorn Helgaas,
	linux-ia64@vger.kernel.org, Thomas Gleixner, Wuyun,
	linuxppc-dev@lists.ozlabs.org, Yijing Wang
In-Reply-To: <1416219710-26088-10-git-send-email-wangyijing@huawei.com>

On Mon, Nov 17, 2014 at 10:21:43AM +0000, Yijing Wang wrote:
> From: Yijing Wang <wangyijing0307@gmail.com>
>=20
> Signed-off-by: Yijing Wang <wangyijing@huawei.com>
> ---
>  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

^ permalink raw reply

* [PATCH REPOST 0/3] VPHN parsing fixes
From: Greg Kurz @ 2014-11-17 17:42 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackerras

Repost with Cc: for Michael and Ben...

The following commit fixed an endianness issue in the VPHN code:

commit 5c9fb1899400096c6818181c525897a31d57e488
Author: Greg Kurz <gkurz@linux.vnet.ibm.com>
Date:   Wed Oct 15 12:42:58 2014 +0200

    powerpc/vphn: NUMA node code expects big-endian

It was discussed at the time that we should patch the parsing code instead
of boldly fixing all the values returned by the hypervisor. It is the goal
of this series.

I have an extra question: PAPR+ says that H_HOME_NODE_ASSOCIATIVITY is supposed
to populate registers R4 to R9 with 16-bit or 32-bit values. This means that we
could theorically get 24 associativity domain numbers. According to this commentthe code is limited to 12 though:

/*
 * 6 64-bit registers unpacked into 12 32-bit associativity values. To form
 * the complete property we have to add the length in the first cell.
 */
#define VPHN_ASSOC_BUFSIZE (VPHN_REGISTER_COUNT*sizeof(u64)/sizeof(u32) + 1)

I could find no justification for the fact that we don't expect the registers
to hold 16-bit relevant numbers only. Have I missed something ?

---

Greg Kurz (3):
      powerpc/vphn: clarify the H_HOME_NODE_ASSOCIATIVITY API
      powerpc/vphn: simplify the parsing code
      powerpc/vphn: move endianness fixing to vphn_unpack_associativity()


 arch/powerpc/mm/numa.c | 62 +++++++++++++++++++++++++++++++-------------------
 1 file changed, 39 insertions(+), 23 deletions(-)

--
Greg

^ permalink raw reply

* [PATCH REPOST 1/3] powerpc/vphn: clarify the H_HOME_NODE_ASSOCIATIVITY API
From: Greg Kurz @ 2014-11-17 17:42 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackerras
In-Reply-To: <20141117174216.7717.10926.stgit@bahia.local>

The number of values returned by the H_HOME_NODE_ASSOCIATIVITY h_call deserves
to be explicitly defined, for a better understanding of the code.

Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
---
 arch/powerpc/mm/numa.c |    8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index b9d1dfd..1425517 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -1401,11 +1401,15 @@ static int update_cpu_associativity_changes_mask(void)
 	return cpumask_weight(changes);
 }
 
+/* The H_HOME_NODE_ASSOCIATIVITY h_call returns 6 64-bit registers.
+ */
+#define VPHN_REGISTER_COUNT 6
+
 /*
  * 6 64-bit registers unpacked into 12 32-bit associativity values. To form
  * the complete property we have to add the length in the first cell.
  */
-#define VPHN_ASSOC_BUFSIZE (6*sizeof(u64)/sizeof(u32) + 1)
+#define VPHN_ASSOC_BUFSIZE (VPHN_REGISTER_COUNT*sizeof(u64)/sizeof(u32) + 1)
 
 /*
  * Convert the associativity domain numbers returned from the hypervisor
@@ -1463,7 +1467,7 @@ static long hcall_vphn(unsigned long cpu, __be32 *associativity)
 	int i;
 
 	rc = plpar_hcall9(H_HOME_NODE_ASSOCIATIVITY, retbuf, flags, hwcpu);
-	for (i = 0; i < 6; i++)
+	for (i = 0; i < VPHN_REGISTER_COUNT; i++)
 		retbuf[i] = cpu_to_be64(retbuf[i]);
 	vphn_unpack_associativity(retbuf, associativity);
 

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox