linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources
  2014-11-17 10:21 ` [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources Yijing Wang
@ 2014-11-17 10:08   ` Arnd Bergmann
  2014-11-18  7:44     ` Yijing Wang
  0 siblings, 1 reply; 65+ messages in thread
From: Arnd Bergmann @ 2014-11-17 10:08 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Yijing Wang, Bjorn Helgaas, Liviu Dudau, Tony Luck, Russell King,
	linux-pci, x86, linux-kernel, Xinwei Hu, Thierry Reding,
	Yijing Wang, Suravee.Suthikulpanit, Benjamin Herrenschmidt,
	linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev

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	[flat|nested] 65+ messages in thread

* [RFC PATCH 00/16] Refine PCI host bridge scan interfaces
@ 2014-11-17 10:21 Yijing Wang
  2014-11-17 10:21 ` [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources Yijing Wang
                   ` (16 more replies)
  0 siblings, 17 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-pci, linux-kernel, Xinwei Hu, Wuyun, linux-arm-kernel,
	Russell King, x86, Thomas Gleixner, Benjamin Herrenschmidt,
	linuxppc-dev, Tony Luck, linux-ia64, Thierry Reding, Liviu Dudau,
	Suravee.Suthikulpanit, Yijing Wang

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	[flat|nested] 65+ messages in thread

* [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources
  2014-11-17 10:21 [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Yijing Wang
@ 2014-11-17 10:21 ` Yijing Wang
  2014-11-17 10:08   ` Arnd Bergmann
  2014-11-17 10:21 ` [RFC PATCH 02/16] PCI: Use pci_scan_root_bus() instead of pci_scan_bus() Yijing Wang
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 65+ messages in thread
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-pci, linux-kernel, Xinwei Hu, Wuyun, linux-arm-kernel,
	Russell King, x86, Thomas Gleixner, Benjamin Herrenschmidt,
	linuxppc-dev, Tony Luck, linux-ia64, Thierry Reding, Liviu Dudau,
	Suravee.Suthikulpanit, Yijing Wang, Yijing Wang

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	[flat|nested] 65+ messages in thread

* [RFC PATCH 02/16] PCI: Use pci_scan_root_bus() instead of pci_scan_bus()
  2014-11-17 10:21 [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Yijing Wang
  2014-11-17 10:21 ` [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources Yijing Wang
@ 2014-11-17 10:21 ` Yijing Wang
  2014-11-18 14:28   ` Liviu Dudau
  2014-11-17 10:21 ` [RFC PATCH 03/16] PCI: Clean up pci_scan_bus() Yijing Wang
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 65+ messages in thread
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-pci, linux-kernel, Xinwei Hu, Wuyun, linux-arm-kernel,
	Russell King, x86, Thomas Gleixner, Benjamin Herrenschmidt,
	linuxppc-dev, Tony Luck, linux-ia64, Thierry Reding, Liviu Dudau,
	Suravee.Suthikulpanit, Yijing Wang, Yijing Wang

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	[flat|nested] 65+ messages in thread

* [RFC PATCH 03/16] PCI: Clean up pci_scan_bus()
  2014-11-17 10:21 [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Yijing Wang
  2014-11-17 10:21 ` [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources Yijing Wang
  2014-11-17 10:21 ` [RFC PATCH 02/16] PCI: Use pci_scan_root_bus() instead of pci_scan_bus() Yijing Wang
@ 2014-11-17 10:21 ` Yijing Wang
  2014-11-17 10:21 ` [RFC PATCH 04/16] PCI: Rip out pci_bus_add_devices() from pci_scan_root_bus() Yijing Wang
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-pci, linux-kernel, Xinwei Hu, Wuyun, linux-arm-kernel,
	Russell King, x86, Thomas Gleixner, Benjamin Herrenschmidt,
	linuxppc-dev, Tony Luck, linux-ia64, Thierry Reding, Liviu Dudau,
	Suravee.Suthikulpanit, Yijing Wang

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	[flat|nested] 65+ messages in thread

* [RFC PATCH 04/16] PCI: Rip out pci_bus_add_devices() from pci_scan_root_bus()
  2014-11-17 10:21 [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Yijing Wang
                   ` (2 preceding siblings ...)
  2014-11-17 10:21 ` [RFC PATCH 03/16] PCI: Clean up pci_scan_bus() Yijing Wang
@ 2014-11-17 10:21 ` Yijing Wang
  2014-11-18 14:34   ` Liviu Dudau
  2014-11-17 10:21 ` [RFC PATCH 05/16] PCI: Use pci_scan_root_bus() instead of pci_scan_bus_parented() Yijing Wang
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 65+ messages in thread
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-pci, linux-kernel, Xinwei Hu, Wuyun, linux-arm-kernel,
	Russell King, x86, Thomas Gleixner, Benjamin Herrenschmidt,
	linuxppc-dev, Tony Luck, linux-ia64, Thierry Reding, Liviu Dudau,
	Suravee.Suthikulpanit, Yijing Wang

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	[flat|nested] 65+ messages in thread

* [RFC PATCH 05/16] PCI: Use pci_scan_root_bus() instead of pci_scan_bus_parented()
  2014-11-17 10:21 [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Yijing Wang
                   ` (3 preceding siblings ...)
  2014-11-17 10:21 ` [RFC PATCH 04/16] PCI: Rip out pci_bus_add_devices() from pci_scan_root_bus() Yijing Wang
@ 2014-11-17 10:21 ` Yijing Wang
  2014-11-17 10:21 ` [RFC PATCH 06/16] PCI: Use u32 type to combine PCI domain and bus number Yijing Wang
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-pci, linux-kernel, Xinwei Hu, Wuyun, linux-arm-kernel,
	Russell King, x86, Thomas Gleixner, Benjamin Herrenschmidt,
	linuxppc-dev, Tony Luck, linux-ia64, Thierry Reding, Liviu Dudau,
	Suravee.Suthikulpanit, Yijing Wang

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	[flat|nested] 65+ messages in thread

* [RFC PATCH 06/16] PCI: Use u32 type to combine PCI domain and bus number
  2014-11-17 10:21 [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Yijing Wang
                   ` (4 preceding siblings ...)
  2014-11-17 10:21 ` [RFC PATCH 05/16] PCI: Use pci_scan_root_bus() instead of pci_scan_bus_parented() Yijing Wang
@ 2014-11-17 10:21 ` Yijing Wang
  2014-11-17 10:21 ` [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus() Yijing Wang
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-pci, linux-kernel, Xinwei Hu, Wuyun, linux-arm-kernel,
	Russell King, x86, Thomas Gleixner, Benjamin Herrenschmidt,
	linuxppc-dev, Tony Luck, linux-ia64, Thierry Reding, Liviu Dudau,
	Suravee.Suthikulpanit, Yijing Wang

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	[flat|nested] 65+ messages in thread

* [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
  2014-11-17 10:21 [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Yijing Wang
                   ` (5 preceding siblings ...)
  2014-11-17 10:21 ` [RFC PATCH 06/16] PCI: Use u32 type to combine PCI domain and bus number Yijing Wang
@ 2014-11-17 10:21 ` Yijing Wang
  2014-11-17 10:56   ` Arnd Bergmann
  2014-11-18 15:30   ` Liviu Dudau
  2014-11-17 10:21 ` [RFC PATCH 08/16] PCI: Introduce pci_scan_host_bridge() and pci_host_info Yijing Wang
                   ` (9 subsequent siblings)
  16 siblings, 2 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-pci, linux-kernel, Xinwei Hu, Wuyun, linux-arm-kernel,
	Russell King, x86, Thomas Gleixner, Benjamin Herrenschmidt,
	linuxppc-dev, Tony Luck, linux-ia64, Thierry Reding, Liviu Dudau,
	Suravee.Suthikulpanit, Yijing Wang

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	[flat|nested] 65+ messages in thread

* [RFC PATCH 08/16] PCI: Introduce pci_scan_host_bridge() and pci_host_info
  2014-11-17 10:21 [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Yijing Wang
                   ` (6 preceding siblings ...)
  2014-11-17 10:21 ` [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus() Yijing Wang
@ 2014-11-17 10:21 ` Yijing Wang
  2014-11-18 15:42   ` Liviu Dudau
  2014-11-17 10:21 ` [RFC PATCH 09/16] PCI: Associate .get_msi_ctrl() with pci_host_bridge Yijing Wang
                   ` (8 subsequent siblings)
  16 siblings, 1 reply; 65+ messages in thread
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-pci, linux-kernel, Xinwei Hu, Wuyun, linux-arm-kernel,
	Russell King, x86, Thomas Gleixner, Benjamin Herrenschmidt,
	linuxppc-dev, Tony Luck, linux-ia64, Thierry Reding, Liviu Dudau,
	Suravee.Suthikulpanit, Yijing Wang, Yijing Wang

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	[flat|nested] 65+ messages in thread

* [RFC PATCH 09/16] PCI: Associate .get_msi_ctrl() with pci_host_bridge
  2014-11-17 10:21 [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Yijing Wang
                   ` (7 preceding siblings ...)
  2014-11-17 10:21 ` [RFC PATCH 08/16] PCI: Introduce pci_scan_host_bridge() and pci_host_info Yijing Wang
@ 2014-11-17 10:21 ` Yijing Wang
  2014-11-17 15:03   ` Lorenzo Pieralisi
  2014-11-17 10:21 ` [RFC PATCH 10/16] PCI: Add of_scan_bus() to pci_host_info Yijing Wang
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 65+ messages in thread
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-pci, linux-kernel, Xinwei Hu, Wuyun, linux-arm-kernel,
	Russell King, x86, Thomas Gleixner, Benjamin Herrenschmidt,
	linuxppc-dev, Tony Luck, linux-ia64, Thierry Reding, Liviu Dudau,
	Suravee.Suthikulpanit, Yijing Wang, Yijing Wang

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	[flat|nested] 65+ messages in thread

* [RFC PATCH 10/16] PCI: Add of_scan_bus() to pci_host_info
  2014-11-17 10:21 [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Yijing Wang
                   ` (8 preceding siblings ...)
  2014-11-17 10:21 ` [RFC PATCH 09/16] PCI: Associate .get_msi_ctrl() with pci_host_bridge Yijing Wang
@ 2014-11-17 10:21 ` Yijing Wang
  2014-11-17 10:21 ` [RFC PATCH 11/16] x86/PCI: Use pci_scan_host_bridge() instead of pci_create_root_bus() Yijing Wang
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-pci, linux-kernel, Xinwei Hu, Wuyun, linux-arm-kernel,
	Russell King, x86, Thomas Gleixner, Benjamin Herrenschmidt,
	linuxppc-dev, Tony Luck, linux-ia64, Thierry Reding, Liviu Dudau,
	Suravee.Suthikulpanit, Yijing Wang

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	[flat|nested] 65+ messages in thread

* [RFC PATCH 11/16] x86/PCI: Use pci_scan_host_bridge() instead of pci_create_root_bus()
  2014-11-17 10:21 [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Yijing Wang
                   ` (9 preceding siblings ...)
  2014-11-17 10:21 ` [RFC PATCH 10/16] PCI: Add of_scan_bus() to pci_host_info Yijing Wang
@ 2014-11-17 10:21 ` Yijing Wang
  2014-11-17 10:21 ` [RFC PATCH 12/16] ia64/PCI: Remove the redundant bus variable Yijing Wang
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-pci, linux-kernel, Xinwei Hu, Wuyun, linux-arm-kernel,
	Russell King, x86, Thomas Gleixner, Benjamin Herrenschmidt,
	linuxppc-dev, Tony Luck, linux-ia64, Thierry Reding, Liviu Dudau,
	Suravee.Suthikulpanit, Yijing Wang

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	[flat|nested] 65+ messages in thread

* [RFC PATCH 12/16] ia64/PCI: Remove the redundant bus variable
  2014-11-17 10:21 [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Yijing Wang
                   ` (10 preceding siblings ...)
  2014-11-17 10:21 ` [RFC PATCH 11/16] x86/PCI: Use pci_scan_host_bridge() instead of pci_create_root_bus() Yijing Wang
@ 2014-11-17 10:21 ` Yijing Wang
  2014-11-17 10:21 ` [RFC PATCH 13/16] ia64/PCI: Use pci_scan_host_bridge() to refactor pci_acpi_scan_root() Yijing Wang
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-pci, linux-kernel, Xinwei Hu, Wuyun, linux-arm-kernel,
	Russell King, x86, Thomas Gleixner, Benjamin Herrenschmidt,
	linuxppc-dev, Tony Luck, linux-ia64, Thierry Reding, Liviu Dudau,
	Suravee.Suthikulpanit, Yijing Wang

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	[flat|nested] 65+ messages in thread

* [RFC PATCH 13/16] ia64/PCI: Use pci_scan_host_bridge() to refactor pci_acpi_scan_root()
  2014-11-17 10:21 [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Yijing Wang
                   ` (11 preceding siblings ...)
  2014-11-17 10:21 ` [RFC PATCH 12/16] ia64/PCI: Remove the redundant bus variable Yijing Wang
@ 2014-11-17 10:21 ` Yijing Wang
  2014-11-17 10:21 ` [RFC PATCH 14/16] arm/PCI: Introduce pci_get_domain_nr() Yijing Wang
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-pci, linux-kernel, Xinwei Hu, Wuyun, linux-arm-kernel,
	Russell King, x86, Thomas Gleixner, Benjamin Herrenschmidt,
	linuxppc-dev, Tony Luck, linux-ia64, Thierry Reding, Liviu Dudau,
	Suravee.Suthikulpanit, Yijing Wang

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	[flat|nested] 65+ messages in thread

* [RFC PATCH 14/16] arm/PCI: Introduce pci_get_domain_nr()
  2014-11-17 10:21 [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Yijing Wang
                   ` (12 preceding siblings ...)
  2014-11-17 10:21 ` [RFC PATCH 13/16] ia64/PCI: Use pci_scan_host_bridge() to refactor pci_acpi_scan_root() Yijing Wang
@ 2014-11-17 10:21 ` Yijing Wang
  2014-11-17 12:08   ` Lorenzo Pieralisi
  2014-11-17 10:21 ` [RFC PATCH 15/16] arm/PCI: Use pci_scan_host_bridge() instead of pci_scan_root_bus() Yijing Wang
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 65+ messages in thread
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-pci, linux-kernel, Xinwei Hu, Wuyun, linux-arm-kernel,
	Russell King, x86, Thomas Gleixner, Benjamin Herrenschmidt,
	linuxppc-dev, Tony Luck, linux-ia64, Thierry Reding, Liviu Dudau,
	Suravee.Suthikulpanit, Yijing Wang

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	[flat|nested] 65+ messages in thread

* [RFC PATCH 15/16] arm/PCI: Use pci_scan_host_bridge() instead of pci_scan_root_bus()
  2014-11-17 10:21 [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Yijing Wang
                   ` (13 preceding siblings ...)
  2014-11-17 10:21 ` [RFC PATCH 14/16] arm/PCI: Introduce pci_get_domain_nr() Yijing Wang
@ 2014-11-17 10:21 ` Yijing Wang
  2014-11-17 10:21 ` [RFC PATCH 16/16] powerpc/PCI: Use pci_scan_host_bridge() to scan PCI bus Yijing Wang
  2014-11-17 14:13 ` [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Arnd Bergmann
  16 siblings, 0 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-pci, linux-kernel, Xinwei Hu, Wuyun, linux-arm-kernel,
	Russell King, x86, Thomas Gleixner, Benjamin Herrenschmidt,
	linuxppc-dev, Tony Luck, linux-ia64, Thierry Reding, Liviu Dudau,
	Suravee.Suthikulpanit, Yijing Wang

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	[flat|nested] 65+ messages in thread

* [RFC PATCH 16/16] powerpc/PCI: Use pci_scan_host_bridge() to scan PCI bus
  2014-11-17 10:21 [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Yijing Wang
                   ` (14 preceding siblings ...)
  2014-11-17 10:21 ` [RFC PATCH 15/16] arm/PCI: Use pci_scan_host_bridge() instead of pci_scan_root_bus() Yijing Wang
@ 2014-11-17 10:21 ` Yijing Wang
  2014-11-17 14:13 ` [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Arnd Bergmann
  16 siblings, 0 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-17 10:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-pci, linux-kernel, Xinwei Hu, Wuyun, linux-arm-kernel,
	Russell King, x86, Thomas Gleixner, Benjamin Herrenschmidt,
	linuxppc-dev, Tony Luck, linux-ia64, Thierry Reding, Liviu Dudau,
	Suravee.Suthikulpanit, Yijing Wang

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	[flat|nested] 65+ messages in thread

* Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
  2014-11-17 10:21 ` [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus() Yijing Wang
@ 2014-11-17 10:56   ` Arnd Bergmann
  2014-11-18  8:32     ` Yijing Wang
  2014-11-18 15:30   ` Liviu Dudau
  1 sibling, 1 reply; 65+ messages in thread
From: Arnd Bergmann @ 2014-11-17 10:56 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Yijing Wang, Bjorn Helgaas, Liviu Dudau, Tony Luck, Russell King,
	linux-pci, x86, linux-kernel, Xinwei Hu, Thierry Reding,
	Suravee.Suthikulpanit, linux-ia64, Thomas Gleixner, Wuyun,
	linux-arm-kernel

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	[flat|nested] 65+ messages in thread

* Re: [RFC PATCH 14/16] arm/PCI: Introduce pci_get_domain_nr()
  2014-11-17 10:21 ` [RFC PATCH 14/16] arm/PCI: Introduce pci_get_domain_nr() Yijing Wang
@ 2014-11-17 12:08   ` Lorenzo Pieralisi
  2014-11-18  0:55     ` Yijing Wang
  0 siblings, 1 reply; 65+ messages in thread
From: Lorenzo Pieralisi @ 2014-11-17 12:08 UTC (permalink / raw)
  To: Yijing Wang
  Cc: Bjorn Helgaas, linux-pci, linux-kernel, huxinwei, Wuyun,
	linux-arm-kernel, Russell King, x86, Thomas Gleixner,
	Benjamin Herrenschmidt, linuxppc-dev, Tony Luck, linux-ia64,
	Thierry Reding, Liviu Dudau, suravee.suthikulpanit

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

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	[flat|nested] 65+ messages in thread

* Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces
  2014-11-17 10:21 [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Yijing Wang
                   ` (15 preceding siblings ...)
  2014-11-17 10:21 ` [RFC PATCH 16/16] powerpc/PCI: Use pci_scan_host_bridge() to scan PCI bus Yijing Wang
@ 2014-11-17 14:13 ` Arnd Bergmann
  2014-11-18 11:17   ` Yijing Wang
  2014-11-20 11:54   ` Tomasz Nowicki
  16 siblings, 2 replies; 65+ messages in thread
From: Arnd Bergmann @ 2014-11-17 14:13 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Yijing Wang, Bjorn Helgaas, Liviu Dudau, Tony Luck, Russell King,
	linux-pci, x86, linux-kernel, Xinwei Hu, Thierry Reding,
	Suravee.Suthikulpanit, Benjamin Herrenschmidt, linux-ia64,
	Thomas Gleixner, Wuyun, linuxppc-dev

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	[flat|nested] 65+ messages in thread

* Re: [RFC PATCH 09/16] PCI: Associate .get_msi_ctrl() with pci_host_bridge
  2014-11-17 10:21 ` [RFC PATCH 09/16] PCI: Associate .get_msi_ctrl() with pci_host_bridge Yijing Wang
@ 2014-11-17 15:03   ` Lorenzo Pieralisi
  0 siblings, 0 replies; 65+ messages in thread
From: Lorenzo Pieralisi @ 2014-11-17 15:03 UTC (permalink / raw)
  To: Yijing Wang
  Cc: Bjorn Helgaas, Liviu Dudau, Tony Luck, Russell King, linux-pci,
	x86, linux-kernel, huxinwei, Thierry Reding, Yijing Wang,
	suravee.suthikulpanit, linux-ia64, Thomas Gleixner, Wuyun,
	linuxppc-dev, linux-arm-kernel

On Mon, Nov 17, 2014 at 10:21:43AM +0000, Yijing Wang wrote:
> 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);
>  };

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	[flat|nested] 65+ messages in thread

* Re: [RFC PATCH 14/16] arm/PCI: Introduce pci_get_domain_nr()
  2014-11-17 12:08   ` Lorenzo Pieralisi
@ 2014-11-18  0:55     ` Yijing Wang
  0 siblings, 0 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-18  0:55 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Bjorn Helgaas, linux-pci, linux-kernel, huxinwei, Wuyun,
	linux-arm-kernel, Russell King, x86, Thomas Gleixner,
	Benjamin Herrenschmidt, linuxppc-dev, Tony Luck, linux-ia64,
	Thierry Reding, Liviu Dudau, suravee.suthikulpanit

>>  
>> -	bus->domain_nr = domain;
>> +void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
>> +{
>> +	bus->domain_nr = pci_get_domain_nr(parent);
>>  }
>>  #endif
> 
> This code is superseded by the last patches I sent to move the domain
> assignment to PCI core code.
> 
> http://lists.infradead.org/pipermail/linux-arm-kernel/2014-November/301220.html

OK, I will update it based the latest one.

> 
> Lorenzo
> 
> 
> .
> 


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources
  2014-11-17 10:08   ` Arnd Bergmann
@ 2014-11-18  7:44     ` Yijing Wang
  2014-11-18  9:36       ` Arnd Bergmann
  0 siblings, 1 reply; 65+ messages in thread
From: Yijing Wang @ 2014-11-18  7:44 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: Bjorn Helgaas, Liviu Dudau, Tony Luck, Russell King, linux-pci,
	x86, linux-kernel, Xinwei Hu, Thierry Reding, Yijing Wang,
	Suravee.Suthikulpanit, Benjamin Herrenschmidt, linux-ia64,
	Thomas Gleixner, Wuyun, linuxppc-dev

On 2014/11/17 18:08, Arnd Bergmann wrote:
> 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.

Hi Arnd, pci host bridge windows are the ranges allow child devices to setup
from. Add all of IO/MEM here just a limit to child devices, no request for these
resources, so it won't hurt another host bridge. Some platforms have no dts or ACPI
report host bridge resources, in this case, we directly assign ioport/iomem_resources
as the root resources of PCI devices.

Thanks!
Yijing.

> 
> 	Arnd
> 
> .
> 


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
  2014-11-17 10:56   ` Arnd Bergmann
@ 2014-11-18  8:32     ` Yijing Wang
  2014-11-18  9:30       ` Arnd Bergmann
  2014-11-18 14:48       ` Liviu Dudau
  0 siblings, 2 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-18  8:32 UTC (permalink / raw)
  To: Arnd Bergmann, linuxppc-dev
  Cc: Bjorn Helgaas, Liviu Dudau, Tony Luck, Russell King, linux-pci,
	x86, linux-kernel, Xinwei Hu, Thierry Reding,
	Suravee.Suthikulpanit, linux-ia64, Thomas Gleixner, Wuyun,
	linux-arm-kernel


>> +LIST_HEAD(pci_host_bridge_list);
>> +DECLARE_RWSEM(pci_host_bridge_sem);
> 
> Unless the pci_host_bridge_sem is accessed thousands of times per second,
> it's normally better to use a simple mutex instead.

OK, I will use simple mutex instead.

> 
>> +static struct resource busn_resource = {
>> +	.name	= "PCI busn",
>> +	.start	= 0,
>> +	.end	= 255,
>> +	.flags	= IORESOURCE_BUS,
>> +};
> 
> I think it would be better to require callers to pass the bus resource
> down to the function.

Hmm, I think most of caller will provide the bus resource, but some others
will not give any bus resource, extremely, no any resources :(. But we still
need properly configure their resources for compatibility.

> 
>> +struct pci_host_bridge *pci_create_host_bridge(
>> +		struct device *parent, u32 db, 
>> +		struct pci_ops *ops, void *sysdata, 
>> +		struct list_head *resources)
>> +{
> 
> Do we still need to pass the 'sysdata' in here? If we are guaranteed to
> have a device pointer, we should always be able to get the driver
> private data from dev_get_drvdata(host->dev->parent).

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

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

I don't know much detail about devm_kzalloc(), but we have no pci host driver
here, and I found no devm_kzalloc() uses in core PCI code before.

> 
>> +	if (!resources) {
>> +		/* Use default IO/MEM/BUS resources*/
>> +		pci_add_resource(&host->windows, &ioport_resource);
>> +		pci_add_resource(&host->windows, &iomem_resource);
>> +		pci_add_resource(&host->windows, &busn_resource);
>> +	} else {
>> +		list_for_each_entry_safe(window, n, resources, list)
>> +			list_move_tail(&window->list, &host->windows);
>> +	}
> 
> I think we should assume that the correct resources are passed. You
> could add a wrapper around this function to convert old platforms
> though.

OK, I will move these code out of pci_create_host_bridge, and add a wrapper
to setup the default resources.

> 
>> +EXPORT_SYMBOL(pci_create_host_bridge);
> 
> EXPORT_SYMBOL_GPL() maybe?

OK, will update it.

> 
>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>> index 8b11b38..daa7f40 100644
>> --- a/include/linux/pci.h
>> +++ b/include/linux/pci.h
>> @@ -402,7 +402,12 @@ struct pci_host_bridge_window {
>>  struct pci_host_bridge {
>>  	struct device dev;
>>  	struct pci_bus *bus;		/* root bus */
>> +	struct list_head list;
>>  	struct list_head windows;	/* pci_host_bridge_windows */
>> +	int busnum;
> 
> The busnum should already be implied through the bus resource.

Yes, I will consider remove it and introduce a helper function to get the root bus number, thanks!

Thanks!
Yijing.

> 
> 	Arnd
> 
> .
> 


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
  2014-11-18  8:32     ` Yijing Wang
@ 2014-11-18  9:30       ` Arnd Bergmann
  2014-11-18 11:44         ` Yijing Wang
  2014-11-18 14:48       ` Liviu Dudau
  1 sibling, 1 reply; 65+ messages in thread
From: Arnd Bergmann @ 2014-11-18  9:30 UTC (permalink / raw)
  To: Yijing Wang
  Cc: linuxppc-dev, Bjorn Helgaas, Liviu Dudau, Tony Luck,
	Russell King, linux-pci, x86, linux-kernel, Xinwei Hu,
	Thierry Reding, Suravee.Suthikulpanit, linux-ia64,
	Thomas Gleixner, Wuyun, linux-arm-kernel

On Tuesday 18 November 2014 16:32:26 Yijing Wang wrote:

> >> +static struct resource busn_resource = {
> >> +	.name	= "PCI busn",
> >> +	.start	= 0,
> >> +	.end	= 255,
> >> +	.flags	= IORESOURCE_BUS,
> >> +};
> > 
> > I think it would be better to require callers to pass the bus resource
> > down to the function.
> 
> Hmm, I think most of caller will provide the bus resource, but some others
> will not give any bus resource, extremely, no any resources :(. But we still
> need properly configure their resources for compatibility.

I think that is what the conversion to pci_scan_bus_parented() is about:
The idea is that we add the correct bus resource to callers of
pci_scan_bus_parented or pci_scan_bus and then change them to call
pci_scan_root_bus instead.

> >> +struct pci_host_bridge *pci_create_host_bridge(
> >> +		struct device *parent, u32 db, 
> >> +		struct pci_ops *ops, void *sysdata, 
> >> +		struct list_head *resources)
> >> +{
> > 
> > Do we still need to pass the 'sysdata' in here? If we are guaranteed to
> > have a device pointer, we should always be able to get the driver
> > private data from dev_get_drvdata(host->dev->parent).
> 
> We need, some platforms pass NULL pointer as host bridge parent.

But those don't have to use the new pci_create_host_bridge() function,
right?

> >> +	host = kzalloc(sizeof(*host), GFP_KERNEL);
> >> +	if (!host)
> >> +		return NULL;
> > 
> > devm_kzalloc maybe?
> 
> I don't know much detail about devm_kzalloc(), but we have no pci host driver
> here, and I found no devm_kzalloc() uses in core PCI code before.

It also depends on having a valid device pointer. The idea is that the memory
is automatically freed if the probe() function returns with an error, or
the device driver gets unloaded. For the classic PCI hosts that are not
connected to a device, that wouldn't work of course.

	Arnd

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

* Re: [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources
  2014-11-18  7:44     ` Yijing Wang
@ 2014-11-18  9:36       ` Arnd Bergmann
  2014-11-18 11:46         ` Yijing Wang
  0 siblings, 1 reply; 65+ messages in thread
From: Arnd Bergmann @ 2014-11-18  9:36 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Yijing Wang, Liviu Dudau, Tony Luck, Russell King, linux-pci,
	x86, linux-kernel, Xinwei Hu, Thierry Reding,
	Suravee.Suthikulpanit, Benjamin Herrenschmidt, Bjorn Helgaas,
	linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev, Yijing Wang

On Tuesday 18 November 2014 15:44:23 Yijing Wang wrote:
> On 2014/11/17 18:08, Arnd Bergmann wrote:
> > 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.
> 
> Hi Arnd, pci host bridge windows are the ranges allow child devices to setup
> from. Add all of IO/MEM here just a limit to child devices, no request for these
> resources, so it won't hurt another host bridge. Some platforms have no dts or ACPI
> report host bridge resources, in this case, we directly assign ioport/iomem_resources
> as the root resources of PCI devices.

But it would be wrong to allow hosts to allocate a device BAR that is not
visible through the host bridge. I think we need to keep these separate
from the general case: if you call any of the modern interfaces you have
to provide the resources and a device. I notice that there is only one
caller of pci_scan_bus_parented(), we should probably change that over to
pci_scan_root_bus() or your new interface and remove the old one, but
keep pci_scan_bus() as the only entry point for all of the legacy users
that do not know about the resources.

	Arnd

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

* Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces
  2014-11-17 14:13 ` [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Arnd Bergmann
@ 2014-11-18 11:17   ` Yijing Wang
  2014-11-18 11:30     ` Arnd Bergmann
  2014-11-20 11:54   ` Tomasz Nowicki
  1 sibling, 1 reply; 65+ messages in thread
From: Yijing Wang @ 2014-11-18 11:17 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: Bjorn Helgaas, Liviu Dudau, Tony Luck, Russell King, linux-pci,
	x86, linux-kernel, Xinwei Hu, Thierry Reding,
	Suravee.Suthikulpanit, Benjamin Herrenschmidt, linux-ia64,
	Thomas Gleixner, Wuyun, linuxppc-dev

On 2014/11/17 22:13, Arnd Bergmann wrote:
> 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.

Hi Arnd, thanks very much for your review and comments!

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

What arm32 code you are trying to untangle for example ?

Introduce pci_host_info here because I want to make the PCI scan interfaces
simple to host drviers, host drivers only need to call one scan
interface(pci_scan_host_bridge), but from your comments,
The combination pci_create_host_bridge() + pci_scan_xx()
seems to be more popular.

> 
> As a general approach, I'd rather see generic helper functions
> being exported by the PCI core that a driver may or may not
> call. 
> The way you split the interface between things that happen
> before scanning the buses (pci_create_host_bridge) and
> the actual scanning (__pci_create_root_bus, pci_scan_child_bus)
> seems very helpful and I think we can expand that concept further:
> 
> - The normal pci_create_host_bridge() function can contain
>   all of the DT scanning functions (finding bus/mem/io resources, 
>   finding the msi-parent), while drivers that don't depend on DT
>   for this information can call the same function and fill the
>   same things after they have the pci_host_bridge pointer.
> 
> - If a driver needs to set up mapping windows, it can do that after
>   calling pci_create_host_bridge(). E.g. all the dw_pcie glue drivers
>   can call a dw_pcie_setup_windows() function that takes the resources
>   out of the pci_host_bridge pointer before the bus is scanned.
> 
> - The ACPI code can have a completely different way of creating
>   a struct pci_host_bridge, which is also passed into the same
>   bus scanning functions, but doesn't have to come from
>   pci_create_host_bridge.

I hope platforms with ACPI or DT could both use pci_create_host_bridge().
Why we need to use two different ways to process it ?

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


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces
  2014-11-18 11:17   ` Yijing Wang
@ 2014-11-18 11:30     ` Arnd Bergmann
  2014-11-18 11:45       ` Lorenzo Pieralisi
  2014-11-18 12:17       ` Yijing Wang
  0 siblings, 2 replies; 65+ messages in thread
From: Arnd Bergmann @ 2014-11-18 11:30 UTC (permalink / raw)
  To: Yijing Wang
  Cc: linux-arm-kernel, Bjorn Helgaas, Liviu Dudau, Tony Luck,
	Russell King, linux-pci, x86, linux-kernel, Xinwei Hu,
	Thierry Reding, Suravee.Suthikulpanit, Benjamin Herrenschmidt,
	linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev

On Tuesday 18 November 2014 19:17:32 Yijing Wang wrote:
> On 2014/11/17 22:13, Arnd Bergmann wrote:
> > 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.
> 
> Hi Arnd, thanks very much for your review and comments!
> 
> > 
> > I don't particularly like the way you use the 'pci_host_info'
> > to pass callback pointers and some of the generic information.
> > This duplicates some of the issues we are currently trying
> > to untangle in the arm32 code to make drivers easier to share
> > between architectures.
> 
> What arm32 code you are trying to untangle for example ?

We have a few problems that currently prevent us from using shared
drivers across arm32 and arm64:

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

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

- The way we pass a temporary structure (hw_pci) with function pointers
  into the architecture code makes it relatively hard to follow
  how the initialization sequence works.
 
> Introduce pci_host_info here because I want to make the PCI scan interfaces
> simple to host drviers, host drivers only need to call one scan
> interface(pci_scan_host_bridge), but from your comments,
> The combination pci_create_host_bridge() + pci_scan_xx()
> seems to be more popular.

Yes, I think a simpler interface structure would be better than trying
to minimize the amount of code needed in drivers at the expense of
interface complexity.

> > As a general approach, I'd rather see generic helper functions
> > being exported by the PCI core that a driver may or may not
> > call. 
> > The way you split the interface between things that happen
> > before scanning the buses (pci_create_host_bridge) and
> > the actual scanning (__pci_create_root_bus, pci_scan_child_bus)
> > seems very helpful and I think we can expand that concept further:
> > 
> > - The normal pci_create_host_bridge() function can contain
> >   all of the DT scanning functions (finding bus/mem/io resources, 
> >   finding the msi-parent), while drivers that don't depend on DT
> >   for this information can call the same function and fill the
> >   same things after they have the pci_host_bridge pointer.
> > 
> > - If a driver needs to set up mapping windows, it can do that after
> >   calling pci_create_host_bridge(). E.g. all the dw_pcie glue drivers
> >   can call a dw_pcie_setup_windows() function that takes the resources
> >   out of the pci_host_bridge pointer before the bus is scanned.
> > 
> > - The ACPI code can have a completely different way of creating
> >   a struct pci_host_bridge, which is also passed into the same
> >   bus scanning functions, but doesn't have to come from
> >   pci_create_host_bridge.
> 
> I hope platforms with ACPI or DT could both use pci_create_host_bridge().
> Why we need to use two different ways to process it ?

These are completely different use cases:

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

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

	Arnd

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

* Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
  2014-11-18  9:30       ` Arnd Bergmann
@ 2014-11-18 11:44         ` Yijing Wang
  2014-11-18 12:25           ` Arnd Bergmann
  0 siblings, 1 reply; 65+ messages in thread
From: Yijing Wang @ 2014-11-18 11:44 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linuxppc-dev, Bjorn Helgaas, Liviu Dudau, Tony Luck,
	Russell King, linux-pci, x86, linux-kernel, Xinwei Hu,
	Thierry Reding, Suravee.Suthikulpanit, linux-ia64,
	Thomas Gleixner, Wuyun, linux-arm-kernel

On 2014/11/18 17:30, Arnd Bergmann wrote:
> On Tuesday 18 November 2014 16:32:26 Yijing Wang wrote:
> 
>>>> +static struct resource busn_resource = {
>>>> +	.name	= "PCI busn",
>>>> +	.start	= 0,
>>>> +	.end	= 255,
>>>> +	.flags	= IORESOURCE_BUS,
>>>> +};
>>>
>>> I think it would be better to require callers to pass the bus resource
>>> down to the function.
>>
>> Hmm, I think most of caller will provide the bus resource, but some others
>> will not give any bus resource, extremely, no any resources :(. But we still
>> need properly configure their resources for compatibility.
> 
> I think that is what the conversion to pci_scan_bus_parented() is about:
> The idea is that we add the correct bus resource to callers of
> pci_scan_bus_parented or pci_scan_bus and then change them to call
> pci_scan_root_bus instead.

It looks good to me, but for simplification, or I will try to use a wrapper to
process the drivers don't pass the busnr resources, and make sure the generic
pci_create_host_bridge() always get the valid resources.

> 
>>>> +struct pci_host_bridge *pci_create_host_bridge(
>>>> +		struct device *parent, u32 db, 
>>>> +		struct pci_ops *ops, void *sysdata, 
>>>> +		struct list_head *resources)
>>>> +{
>>>
>>> Do we still need to pass the 'sysdata' in here? If we are guaranteed to
>>> have a device pointer, we should always be able to get the driver
>>> private data from dev_get_drvdata(host->dev->parent).
>>
>> We need, some platforms pass NULL pointer as host bridge parent.
> 
> But those don't have to use the new pci_create_host_bridge() function,
> right?

As I mentioned in another reply, I hope all pci host drivers could use
pci_create_host_bridge(), keep different PCI scan interfaces in PCI core
make things become complex.


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


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces
  2014-11-18 11:30     ` Arnd Bergmann
@ 2014-11-18 11:45       ` Lorenzo Pieralisi
  2014-11-18 12:14         ` Yijing Wang
  2014-11-18 12:17       ` Yijing Wang
  1 sibling, 1 reply; 65+ messages in thread
From: Lorenzo Pieralisi @ 2014-11-18 11:45 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Yijing Wang, Liviu Dudau, Tony Luck, Russell King, linux-pci,
	x86, linux-kernel, huxinwei, Thierry Reding,
	suravee.suthikulpanit, Bjorn Helgaas, linux-ia64,
	Thomas Gleixner, Wuyun, linuxppc-dev, linux-arm-kernel

On Tue, Nov 18, 2014 at 11:30:11AM +0000, Arnd Bergmann wrote:
> On Tuesday 18 November 2014 19:17:32 Yijing Wang wrote:
> > On 2014/11/17 22:13, Arnd Bergmann wrote:
> > > 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.
> > 
> > Hi Arnd, thanks very much for your review and comments!
> > 
> > > 
> > > I don't particularly like the way you use the 'pci_host_info'
> > > to pass callback pointers and some of the generic information.
> > > This duplicates some of the issues we are currently trying
> > > to untangle in the arm32 code to make drivers easier to share
> > > between architectures.
> > 
> > What arm32 code you are trying to untangle for example ?
> 
> We have a few problems that currently prevent us from using shared
> drivers across arm32 and arm64:
> 
> - arm32 has an architecture-defined pci_sys_data structure, but
>   we really want to have one that is defined by the host bridge driver
>   and that is architecture independent. Some core functions depend
>   on this structure at the moment, which Lorenzo is trying to
>   undo

Yes, and on this specific point I would like to understand why we
are adding yet more pci_sys_data data in the last series that is
already in -next:

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

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

Thanks,
Lorenzo

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

* Re: [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources
  2014-11-18  9:36       ` Arnd Bergmann
@ 2014-11-18 11:46         ` Yijing Wang
  2014-11-18 14:23           ` Liviu Dudau
  0 siblings, 1 reply; 65+ messages in thread
From: Yijing Wang @ 2014-11-18 11:46 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Thierry Reding, Suravee.Suthikulpanit,
	Benjamin Herrenschmidt, Bjorn Helgaas, linux-ia64,
	Thomas Gleixner, Wuyun, linuxppc-dev, Yijing Wang

On 2014/11/18 17:36, Arnd Bergmann wrote:
> On Tuesday 18 November 2014 15:44:23 Yijing Wang wrote:
>> On 2014/11/17 18:08, Arnd Bergmann wrote:
>>> 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.
>>
>> Hi Arnd, pci host bridge windows are the ranges allow child devices to setup
>> from. Add all of IO/MEM here just a limit to child devices, no request for these
>> resources, so it won't hurt another host bridge. Some platforms have no dts or ACPI
>> report host bridge resources, in this case, we directly assign ioport/iomem_resources
>> as the root resources of PCI devices.
> 
> But it would be wrong to allow hosts to allocate a device BAR that is not
> visible through the host bridge. I think we need to keep these separate
> from the general case: if you call any of the modern interfaces you have
> to provide the resources and a device. I notice that there is only one
> caller of pci_scan_bus_parented(), we should probably change that over to
> pci_scan_root_bus() or your new interface and remove the old one, but
> keep pci_scan_bus() as the only entry point for all of the legacy users
> that do not know about the resources.

Ok, I will move this out of the generic interface.

Thanks!
Yijing.

> 
> 	Arnd
> 
> .
> 


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces
  2014-11-18 11:45       ` Lorenzo Pieralisi
@ 2014-11-18 12:14         ` Yijing Wang
  0 siblings, 0 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-18 12:14 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Arnd Bergmann
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, huxinwei, Thierry Reding, suravee.suthikulpanit,
	Bjorn Helgaas, linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev,
	linux-arm-kernel

On 2014/11/18 19:45, Lorenzo Pieralisi wrote:
> On Tue, Nov 18, 2014 at 11:30:11AM +0000, Arnd Bergmann wrote:
>> On Tuesday 18 November 2014 19:17:32 Yijing Wang wrote:
>>> On 2014/11/17 22:13, Arnd Bergmann wrote:
>>>> 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.
>>>
>>> Hi Arnd, thanks very much for your review and comments!
>>>
>>>>
>>>> I don't particularly like the way you use the 'pci_host_info'
>>>> to pass callback pointers and some of the generic information.
>>>> This duplicates some of the issues we are currently trying
>>>> to untangle in the arm32 code to make drivers easier to share
>>>> between architectures.
>>>
>>> What arm32 code you are trying to untangle for example ?
>>
>> We have a few problems that currently prevent us from using shared
>> drivers across arm32 and arm64:
>>
>> - arm32 has an architecture-defined pci_sys_data structure, but
>>   we really want to have one that is defined by the host bridge driver
>>   and that is architecture independent. Some core functions depend
>>   on this structure at the moment, which Lorenzo is trying to
>>   undo
> 
> Yes, and on this specific point I would like to understand why we
> are adding yet more pci_sys_data data in the last series that is
> already in -next:
> 
> https://lkml.org/lkml/2014/10/27/85
> 
> What does this buy us ? The cover letter says already that there *is*
> a better solution, why do not we work on that instead of adding more churn
> to arch specific code ?

In my plan, first save msi_chip in pci_sys_data, so we could remove the lots duplicate
pcibios_add_bus(), second, make a generic pci_host_bridge, and move the msi_chip in that,
so we could eliminate all MSI arch weak functions. And in arm I think it's no need to
associate msi_chip with PCI bus, because all pci devices under the same pci host bridge
share the same msi_chip.



> 
> Thanks,
> Lorenzo
> 
> .
> 


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces
  2014-11-18 11:30     ` Arnd Bergmann
  2014-11-18 11:45       ` Lorenzo Pieralisi
@ 2014-11-18 12:17       ` Yijing Wang
  2014-11-18 12:27         ` Arnd Bergmann
  1 sibling, 1 reply; 65+ messages in thread
From: Yijing Wang @ 2014-11-18 12:17 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, Bjorn Helgaas, Liviu Dudau, Tony Luck,
	Russell King, linux-pci, x86, linux-kernel, Xinwei Hu,
	Thierry Reding, Suravee.Suthikulpanit, Benjamin Herrenschmidt,
	linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev

On 2014/11/18 19:30, Arnd Bergmann wrote:
> On Tuesday 18 November 2014 19:17:32 Yijing Wang wrote:
>> On 2014/11/17 22:13, Arnd Bergmann wrote:
>>> 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.
>>
>> Hi Arnd, thanks very much for your review and comments!
>>
>>>
>>> I don't particularly like the way you use the 'pci_host_info'
>>> to pass callback pointers and some of the generic information.
>>> This duplicates some of the issues we are currently trying
>>> to untangle in the arm32 code to make drivers easier to share
>>> between architectures.
>>
>> What arm32 code you are trying to untangle for example ?
> 
> We have a few problems that currently prevent us from using shared
> drivers across arm32 and arm64:
> 
> - arm32 has an architecture-defined pci_sys_data structure, but
>   we really want to have one that is defined by the host bridge driver
>   and that is architecture independent. Some core functions depend
>   on this structure at the moment, which Lorenzo is trying to
>   undo
> 
> - The pci_common_init interface on arm32 doesn't work well on
>   loadable drivers, it does not return an error, and it is built
>   around the assumption that you probe all pci host bridges at
>   the same time, while the standard Linux driver model assumes
>   that you probe one at a time.
> 
> - The way we pass a temporary structure (hw_pci) with function pointers
>   into the architecture code makes it relatively hard to follow
>   how the initialization sequence works.
>  
>> Introduce pci_host_info here because I want to make the PCI scan interfaces
>> simple to host drviers, host drivers only need to call one scan
>> interface(pci_scan_host_bridge), but from your comments,
>> The combination pci_create_host_bridge() + pci_scan_xx()
>> seems to be more popular.
> 
> Yes, I think a simpler interface structure would be better than trying
> to minimize the amount of code needed in drivers at the expense of
> interface complexity.
> 
>>> As a general approach, I'd rather see generic helper functions
>>> being exported by the PCI core that a driver may or may not
>>> call. 
>>> The way you split the interface between things that happen
>>> before scanning the buses (pci_create_host_bridge) and
>>> the actual scanning (__pci_create_root_bus, pci_scan_child_bus)
>>> seems very helpful and I think we can expand that concept further:
>>>
>>> - The normal pci_create_host_bridge() function can contain
>>>   all of the DT scanning functions (finding bus/mem/io resources, 
>>>   finding the msi-parent), while drivers that don't depend on DT
>>>   for this information can call the same function and fill the
>>>   same things after they have the pci_host_bridge pointer.
>>>
>>> - If a driver needs to set up mapping windows, it can do that after
>>>   calling pci_create_host_bridge(). E.g. all the dw_pcie glue drivers
>>>   can call a dw_pcie_setup_windows() function that takes the resources
>>>   out of the pci_host_bridge pointer before the bus is scanned.
>>>
>>> - The ACPI code can have a completely different way of creating
>>>   a struct pci_host_bridge, which is also passed into the same
>>>   bus scanning functions, but doesn't have to come from
>>>   pci_create_host_bridge.

Thanks for your explanation, I will consider these problems when I refactor the
core generic interfaces.

>>
>> I hope platforms with ACPI or DT could both use pci_create_host_bridge().
>> Why we need to use two different ways to process it ?
> 
> These are completely different use cases:
> 
> a) For DT, we want loadable device drivers that start by probing a host
>    bridge device which was added through the DT platform code. The
>    driver is self-contained, and eventually we want to be able to unload
>    it. We have lots of different per-soc drivers that require different
>    quirks
> 
> b) For ACPI, the interface is defined in the ACPI spec across architectures
>    and SoCs, we don't have host bridge drivers and the code that initializes
>    the PCI is required early during boot and called from architecture
>    code. There is no parent device, as ACPI sees PCI as a fundamental building
>    block by itself, and there are no drivers because the firmware does
>    the initial hardware setup, so we only have to access the config space.

Hmmm, I'm a little confused, so why you think ACPI host driver should not use
pci_create_host_bridge(), because ACPI PCI driver has no parent device ?

> 
> 	Arnd
> 
> .
> 


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
  2014-11-18 11:44         ` Yijing Wang
@ 2014-11-18 12:25           ` Arnd Bergmann
  2014-11-18 12:41             ` Yijing Wang
  0 siblings, 1 reply; 65+ messages in thread
From: Arnd Bergmann @ 2014-11-18 12:25 UTC (permalink / raw)
  To: Yijing Wang
  Cc: linuxppc-dev, Bjorn Helgaas, Liviu Dudau, Tony Luck,
	Russell King, linux-pci, x86, linux-kernel, Xinwei Hu,
	Thierry Reding, Suravee.Suthikulpanit, linux-ia64,
	Thomas Gleixner, Wuyun, linux-arm-kernel

On Tuesday 18 November 2014 19:44:36 Yijing Wang wrote:
> On 2014/11/18 17:30, Arnd Bergmann wrote:
> > On Tuesday 18 November 2014 16:32:26 Yijing Wang wrote:
> > 
> >>>> +static struct resource busn_resource = {
> >>>> +	.name	= "PCI busn",
> >>>> +	.start	= 0,
> >>>> +	.end	= 255,
> >>>> +	.flags	= IORESOURCE_BUS,
> >>>> +};
> >>>
> >>> I think it would be better to require callers to pass the bus resource
> >>> down to the function.
> >>
> >> Hmm, I think most of caller will provide the bus resource, but some others
> >> will not give any bus resource, extremely, no any resources :(. But we still
> >> need properly configure their resources for compatibility.
> > 
> > I think that is what the conversion to pci_scan_bus_parented() is about:
> > The idea is that we add the correct bus resource to callers of
> > pci_scan_bus_parented or pci_scan_bus and then change them to call
> > pci_scan_root_bus instead.
> 
> It looks good to me, but for simplification, or I will try to use a wrapper to
> process the drivers don't pass the busnr resources, and make sure the generic
> pci_create_host_bridge() always get the valid resources.

Ok.
 
> >>>> +struct pci_host_bridge *pci_create_host_bridge(
> >>>> +		struct device *parent, u32 db, 
> >>>> +		struct pci_ops *ops, void *sysdata, 
> >>>> +		struct list_head *resources)
> >>>> +{
> >>>
> >>> Do we still need to pass the 'sysdata' in here? If we are guaranteed to
> >>> have a device pointer, we should always be able to get the driver
> >>> private data from dev_get_drvdata(host->dev->parent).
> >>
> >> We need, some platforms pass NULL pointer as host bridge parent.
> > 
> > But those don't have to use the new pci_create_host_bridge() function,
> > right?
> 
> As I mentioned in another reply, I hope all pci host drivers could use
> pci_create_host_bridge(), keep different PCI scan interfaces in PCI core
> make things become complex.

Doing this for all platforms that have PCI support would be a lot of
work though, I think it's better to focus on having a the best interface
for the majority of users.

	Arnd

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

* Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces
  2014-11-18 12:17       ` Yijing Wang
@ 2014-11-18 12:27         ` Arnd Bergmann
  2014-11-20 12:01           ` Tomasz Nowicki
  0 siblings, 1 reply; 65+ messages in thread
From: Arnd Bergmann @ 2014-11-18 12:27 UTC (permalink / raw)
  To: Yijing Wang
  Cc: linux-arm-kernel, Bjorn Helgaas, Liviu Dudau, Tony Luck,
	Russell King, linux-pci, x86, linux-kernel, Xinwei Hu,
	Thierry Reding, Suravee.Suthikulpanit, Benjamin Herrenschmidt,
	linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev

On Tuesday 18 November 2014 20:17:57 Yijing Wang wrote:
> 
> >>
> >> I hope platforms with ACPI or DT could both use pci_create_host_bridge().
> >> Why we need to use two different ways to process it ?
> > 
> > These are completely different use cases:
> > 
> > a) For DT, we want loadable device drivers that start by probing a host
> >    bridge device which was added through the DT platform code. The
> >    driver is self-contained, and eventually we want to be able to unload
> >    it. We have lots of different per-soc drivers that require different
> >    quirks
> > 
> > b) For ACPI, the interface is defined in the ACPI spec across architectures
> >    and SoCs, we don't have host bridge drivers and the code that initializes
> >    the PCI is required early during boot and called from architecture
> >    code. There is no parent device, as ACPI sees PCI as a fundamental building
> >    block by itself, and there are no drivers because the firmware does
> >    the initial hardware setup, so we only have to access the config space.
> 
> Hmmm, I'm a little confused, so why you think ACPI host driver should not use
> pci_create_host_bridge(), because ACPI PCI driver has no parent device ?

It's one of the difference. Having a parent device can certainly make your
life simpler, since you have devm_kzalloc(), dev_info(), etc. Coming from
the other end, I think ACPI needs PCI to be available during early boot,
at a time where we might not want pci_create_host_bridge() to do the
right thing.

	Arnd

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

* Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
  2014-11-18 12:25           ` Arnd Bergmann
@ 2014-11-18 12:41             ` Yijing Wang
  0 siblings, 0 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-18 12:41 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linuxppc-dev, Bjorn Helgaas, Liviu Dudau, Tony Luck,
	Russell King, linux-pci, x86, linux-kernel, Xinwei Hu,
	Thierry Reding, Suravee.Suthikulpanit, linux-ia64,
	Thomas Gleixner, Wuyun, linux-arm-kernel

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

Yes.

> 
> 	Arnd
> 
> .
> 


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources
  2014-11-18 11:46         ` Yijing Wang
@ 2014-11-18 14:23           ` Liviu Dudau
  2014-11-19  1:15             ` Yijing Wang
  0 siblings, 1 reply; 65+ messages in thread
From: Liviu Dudau @ 2014-11-18 14:23 UTC (permalink / raw)
  To: Yijing Wang
  Cc: Arnd Bergmann, linux-arm-kernel, Liviu Dudau, Tony Luck,
	Russell King, linux-pci, x86, linux-kernel, huxinwei,
	Thierry Reding, suravee.suthikulpanit, Benjamin Herrenschmidt,
	Bjorn Helgaas, linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev,
	Yijing Wang

On Tue, Nov 18, 2014 at 11:46:06AM +0000, Yijing Wang wrote:
> On 2014/11/18 17:36, Arnd Bergmann wrote:
> > On Tuesday 18 November 2014 15:44:23 Yijing Wang wrote:
> >> On 2014/11/17 18:08, Arnd Bergmann wrote:
> >>> 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.
> >>
> >> Hi Arnd, pci host bridge windows are the ranges allow child devices to setup
> >> from. Add all of IO/MEM here just a limit to child devices, no request for these
> >> resources, so it won't hurt another host bridge. Some platforms have no dts or ACPI
> >> report host bridge resources, in this case, we directly assign ioport/iomem_resources
> >> as the root resources of PCI devices.
> > 
> > But it would be wrong to allow hosts to allocate a device BAR that is not
> > visible through the host bridge. I think we need to keep these separate
> > from the general case: if you call any of the modern interfaces you have
> > to provide the resources and a device. I notice that there is only one
> > caller of pci_scan_bus_parented(), we should probably change that over to
> > pci_scan_root_bus() or your new interface and remove the old one, but
> > keep pci_scan_bus() as the only entry point for all of the legacy users
> > that do not know about the resources.
> 
> Ok, I will move this out of the generic interface.

My suggestion would actually be to trigger a warning/error if you detect that the resources
are missing. That way we can force the drivers to clean up.

Best regards,
Liviu

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

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯


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

* Re: [RFC PATCH 02/16] PCI: Use pci_scan_root_bus() instead of pci_scan_bus()
  2014-11-17 10:21 ` [RFC PATCH 02/16] PCI: Use pci_scan_root_bus() instead of pci_scan_bus() Yijing Wang
@ 2014-11-18 14:28   ` Liviu Dudau
  2014-11-19  1:19     ` Yijing Wang
  0 siblings, 1 reply; 65+ messages in thread
From: Liviu Dudau @ 2014-11-18 14:28 UTC (permalink / raw)
  To: Yijing Wang
  Cc: Bjorn Helgaas, linux-pci, linux-kernel, huxinwei, Wuyun,
	linux-arm-kernel, Russell King, x86, Thomas Gleixner,
	Benjamin Herrenschmidt, linuxppc-dev, Tony Luck, linux-ia64,
	Thierry Reding, Liviu Dudau, suravee.suthikulpanit, Yijing Wang

On Mon, Nov 17, 2014 at 10:21:36AM +0000, Yijing Wang wrote:
> 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.

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

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

Best regards,
Liviu

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

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯


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

* Re: [RFC PATCH 04/16] PCI: Rip out pci_bus_add_devices() from pci_scan_root_bus()
  2014-11-17 10:21 ` [RFC PATCH 04/16] PCI: Rip out pci_bus_add_devices() from pci_scan_root_bus() Yijing Wang
@ 2014-11-18 14:34   ` Liviu Dudau
  2014-11-19  1:21     ` Yijing Wang
  0 siblings, 1 reply; 65+ messages in thread
From: Liviu Dudau @ 2014-11-18 14:34 UTC (permalink / raw)
  To: Yijing Wang
  Cc: Bjorn Helgaas, linux-pci, linux-kernel, huxinwei, Wuyun,
	linux-arm-kernel, Russell King, x86, Thomas Gleixner,
	Benjamin Herrenschmidt, linuxppc-dev, Tony Luck, linux-ia64,
	Thierry Reding, Liviu Dudau, suravee.suthikulpanit

On Mon, Nov 17, 2014 at 10:21:38AM +0000, Yijing Wang wrote:
> Rip out pci_bus_add_devices() from pci_scan_root_bus()
> for following reasons.
> 1. pci_scan_root_bus() means we only do the scan, we should
> not add pci busses.
> 2. A lots of drviers which use pci_scan_root_bus() call
> pci_bus_size_bridges(), pci_bus_assign_resources() after
> pci_scan_root_bus(). But strictly speaking pci_bus_add_devices()
> should be called after the resources assignment.

This looks like a nice cleanup! Can we split this patch out
of the series and start the ball running on getting ACKs
for it? You are touching a lot of drivers here, you probably
don't want the whole series to wait on approvals for this.

Best regards,
Liviu

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

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯


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

* Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
  2014-11-18  8:32     ` Yijing Wang
  2014-11-18  9:30       ` Arnd Bergmann
@ 2014-11-18 14:48       ` Liviu Dudau
  2014-11-19  2:24         ` Yijing Wang
  1 sibling, 1 reply; 65+ messages in thread
From: Liviu Dudau @ 2014-11-18 14:48 UTC (permalink / raw)
  To: Yijing Wang
  Cc: Arnd Bergmann, linuxppc-dev, Bjorn Helgaas, Liviu Dudau,
	Tony Luck, Russell King, linux-pci, x86, linux-kernel, huxinwei,
	Thierry Reding, suravee.suthikulpanit, linux-ia64,
	Thomas Gleixner, Wuyun, linux-arm-kernel

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

Yijing,

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

Something like this:

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

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


Then we can retrieve the host bridge structure from everywhere we have a device.

Best regards,
Liviu

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

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯


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

* Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
  2014-11-17 10:21 ` [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus() Yijing Wang
  2014-11-17 10:56   ` Arnd Bergmann
@ 2014-11-18 15:30   ` Liviu Dudau
  2014-11-19  1:42     ` Yijing Wang
  1 sibling, 1 reply; 65+ messages in thread
From: Liviu Dudau @ 2014-11-18 15:30 UTC (permalink / raw)
  To: Yijing Wang
  Cc: Bjorn Helgaas, linux-pci, linux-kernel, huxinwei, Wuyun,
	linux-arm-kernel, Russell King, x86, Thomas Gleixner,
	Benjamin Herrenschmidt, linuxppc-dev, Tony Luck, linux-ia64,
	Thierry Reding, Liviu Dudau, suravee.suthikulpanit

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

Please Cc: Yinghai Lu and Jiang Liu on future versions.

More comments on the conversion of pci_create_root_bus():

> Signed-off-by: Yijing Wang <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,

I don't thinks it is worth moving the buses' pci_ops into pci_host_bridge. It
might be more useful to have pci_host_bridge specific ops here.

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

I think bridge should be the b->sysdata here. 

> +       b->ops = bridge->ops;

See comment above why I don't think this is necessary.

> +       b->number = b->busn_res.start = bridge->busnum;
>         pci_bus_assign_domain_nr(b, parent);
> -       b2 = pci_find_bus(pci_domain_nr(b), bus);
> +       bridge->domain = pci_domain_nr(b);

Do you really want to overwrite the bridge's domain with the one from a bus that
could possibly be rejected a couple of lines further down?

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

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

Best regards,
Liviu

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

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯


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

* Re: [RFC PATCH 08/16] PCI: Introduce pci_scan_host_bridge() and pci_host_info
  2014-11-17 10:21 ` [RFC PATCH 08/16] PCI: Introduce pci_scan_host_bridge() and pci_host_info Yijing Wang
@ 2014-11-18 15:42   ` Liviu Dudau
  2014-11-19  2:09     ` Yijing Wang
  0 siblings, 1 reply; 65+ messages in thread
From: Liviu Dudau @ 2014-11-18 15:42 UTC (permalink / raw)
  To: Yijing Wang
  Cc: Bjorn Helgaas, linux-pci, linux-kernel, huxinwei, Wuyun,
	linux-arm-kernel, Russell King, x86, Thomas Gleixner,
	Benjamin Herrenschmidt, linuxppc-dev, Tony Luck, linux-ia64,
	Thierry Reding, Liviu Dudau, suravee.suthikulpanit, Yijing Wang

On Mon, Nov 17, 2014 at 10:21:42AM +0000, Yijing Wang wrote:
> 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*/

Why do you need this hack? Just for calling pci_domain_nr() ?

>  	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;

I'm confused about this assignment. Isn't this a nop as the else part
means info->res_type *is* 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;

I have mixed feelings about this patch. While it is heading in the right direction
of moving pci_host_bridge relevant information towards the right user, I don't think
you picked up the right set to move. The resource list is going to be copied into
internal pci_host_bridge list anyway, keeping another copy is not helpful *and*
you have increased the code size.

I think for now we should aim to get the *missing* data into pci_host_bridge: MSI
controllers and PCI domain/segment. Then we can do more cleanup.

>  
> -	host = pci_create_host_bridge(parent, db, ops, sysdata, resources);
> +	host = pci_create_host_bridge(parent, db, ops, &info);
>  	if (!host)
>  		return NULL;
>  
> @@ -2070,6 +2094,47 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
>  }
>  EXPORT_SYMBOL(pci_scan_root_bus);
>  
> +struct pci_host_bridge *pci_scan_host_bridge(
> +		struct device *parent, u32 db, struct pci_ops *ops,
> +		struct pci_host_info *info)
> +{
> +	struct pci_host_bridge_window *window;
> +	bool found = false;
> +	struct pci_host_bridge *host;
> +	int max;
> +
> +	host = pci_create_host_bridge(parent, db, ops, info);
> +	if (!host)
> +		return NULL;
> +
> +	list_for_each_entry(window, &host->windows, list)
> +		if (window->res->flags & IORESOURCE_BUS) {
> +			found = true;
> +			break;
> +		}
> +
> +	host->bus = __pci_create_root_bus(host);
> +	if (!host->bus) {
> +		pci_free_host_bridge(host);
> +		return NULL;
> +	}
> +
> +	if (!found) {
> +		dev_info(&host->bus->dev,
> +		 "No busn resource found for root bus, will use [bus %02x-ff]\n",
> +			host->busnum);
> +		pci_bus_insert_busn_res(host->bus, host->busnum, 255);
> +	}
> +
> +	max = pci_scan_child_bus(host->bus);
> +	if (!found)
> +		pci_bus_update_busn_res_end(host->bus, max);
> +
> +	return host;
> +
> +}
> +EXPORT_SYMBOL(pci_scan_host_bridge);
> +
>  /**
>   * pci_rescan_bus_bridge_resize - scan a PCI bus for devices.
>   * @bridge: PCI bridge for the bus to scan
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index daa7f40..a51f5f5 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -412,6 +412,21 @@ struct pci_host_bridge {
>  	void *release_data;
>  };
>  
> +struct pci_host_info {
> +	u8 res_type;
> +	void *arg;
> +	struct list_head *resources; /*just for build, will clean up later */
> +	int (*init_res)(struct pci_host_bridge *host, 
> +			struct pci_host_info *info);
> +};
> +
> +static inline void init_pci_host_info(struct pci_host_info *info)
> +{
> +	memset(info, 0 , sizeof(*info));
> +}

Where is this used?

> +
> +#define PCI_HOST_RES_DEFAULT	0x2
> +

Magic number?

Best regards,
Liviu

>  #define	to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)
>  void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
>  		     void (*release_fn)(struct pci_host_bridge *),
> @@ -420,7 +435,7 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
>  int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
>  struct pci_host_bridge *pci_create_host_bridge(
>  		struct device *parent, u32 db, struct pci_ops *ops, 
> -		void *sys, struct list_head *resources);
> +		struct pci_host_info *info);
>  /*
>   * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
>   * to P2P or CardBus bridge windows) go in a table.  Additional ones (for
> @@ -785,6 +800,9 @@ void pci_bus_release_busn_res(struct pci_bus *b);
>  struct pci_bus *pci_scan_root_bus(struct device *parent, u32 bus,
>  					     struct pci_ops *ops, void *sysdata,
>  					     struct list_head *resources);
> +struct pci_host_bridge *pci_scan_host_bridge(struct device *parent,
> +		u32 db, struct pci_ops *ops,
> +		struct pci_host_info *info);
>  struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
>  				int busnr);
>  void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);
> -- 
> 1.7.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯


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

* Re: [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources
  2014-11-18 14:23           ` Liviu Dudau
@ 2014-11-19  1:15             ` Yijing Wang
  0 siblings, 0 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-19  1:15 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Arnd Bergmann, linux-arm-kernel, Liviu Dudau, Tony Luck,
	Russell King, linux-pci, x86, linux-kernel, huxinwei,
	Thierry Reding, suravee.suthikulpanit, Benjamin Herrenschmidt,
	Bjorn Helgaas, linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev,
	Yijing Wang

On 2014/11/18 22:23, Liviu Dudau wrote:
> On Tue, Nov 18, 2014 at 11:46:06AM +0000, Yijing Wang wrote:
>> On 2014/11/18 17:36, Arnd Bergmann wrote:
>>> On Tuesday 18 November 2014 15:44:23 Yijing Wang wrote:
>>>> On 2014/11/17 18:08, Arnd Bergmann wrote:
>>>>> 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.
>>>>
>>>> Hi Arnd, pci host bridge windows are the ranges allow child devices to setup
>>>> from. Add all of IO/MEM here just a limit to child devices, no request for these
>>>> resources, so it won't hurt another host bridge. Some platforms have no dts or ACPI
>>>> report host bridge resources, in this case, we directly assign ioport/iomem_resources
>>>> as the root resources of PCI devices.
>>>
>>> But it would be wrong to allow hosts to allocate a device BAR that is not
>>> visible through the host bridge. I think we need to keep these separate
>>> from the general case: if you call any of the modern interfaces you have
>>> to provide the resources and a device. I notice that there is only one
>>> caller of pci_scan_bus_parented(), we should probably change that over to
>>> pci_scan_root_bus() or your new interface and remove the old one, but
>>> keep pci_scan_bus() as the only entry point for all of the legacy users
>>> that do not know about the resources.
>>
>> Ok, I will move this out of the generic interface.
> 
> My suggestion would actually be to trigger a warning/error if you detect that the resources
> are missing. That way we can force the drivers to clean up.

It make sense to me, thanks.

> 
> Best regards,
> Liviu
> 
>>
>> Thanks!
>> Yijing.
>>
>>>
>>> 	Arnd
>>>
>>> .
>>>
>>
>>
>> -- 
>> Thanks!
>> Yijing
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
> 


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 02/16] PCI: Use pci_scan_root_bus() instead of pci_scan_bus()
  2014-11-18 14:28   ` Liviu Dudau
@ 2014-11-19  1:19     ` Yijing Wang
  0 siblings, 0 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-19  1:19 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Bjorn Helgaas, linux-pci, linux-kernel, huxinwei, Wuyun,
	linux-arm-kernel, Russell King, x86, Thomas Gleixner,
	Benjamin Herrenschmidt, linuxppc-dev, Tony Luck, linux-ia64,
	Thierry Reding, Liviu Dudau, suravee.suthikulpanit, Yijing Wang

On 2014/11/18 22:28, Liviu Dudau wrote:
> On Mon, Nov 17, 2014 at 10:21:36AM +0000, Yijing Wang wrote:
>> 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.
> 
> Actually, I think this patch goes in the wrong direction. You are adding
> two additional parameters that are NULL for every call you replace.
> pci_scan_bus() was actually intended as a "shortcut with defaults" kind
> of call so that you don't have to pass a value for parameters you don't
> care about.
> 
> My suggestion would be to keep the function as is and replace the call
> to pci_create_root_bus() inside with the appropriate sequence.

Hmmm, maybe you are right, provide a simple pci scan interfaces
(which don't care parent and resources) is better than use a complex
one with several NULL arguments. :)


> 
> Best regards,
> Liviu
> 
>>
>> 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
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
> 


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 04/16] PCI: Rip out pci_bus_add_devices() from pci_scan_root_bus()
  2014-11-18 14:34   ` Liviu Dudau
@ 2014-11-19  1:21     ` Yijing Wang
  0 siblings, 0 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-19  1:21 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Bjorn Helgaas, linux-pci, linux-kernel, huxinwei, Wuyun,
	linux-arm-kernel, Russell King, x86, Thomas Gleixner,
	Benjamin Herrenschmidt, linuxppc-dev, Tony Luck, linux-ia64,
	Thierry Reding, Liviu Dudau, suravee.suthikulpanit

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

OK, I will separately this one out of this series.

> 
> Best regards,
> Liviu
> 
>>
>> 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
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
> 


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
  2014-11-18 15:30   ` Liviu Dudau
@ 2014-11-19  1:42     ` Yijing Wang
  2014-11-19 16:37       ` Liviu Dudau
  0 siblings, 1 reply; 65+ messages in thread
From: Yijing Wang @ 2014-11-19  1:42 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Bjorn Helgaas, linux-pci, linux-kernel, huxinwei, Wuyun,
	linux-arm-kernel, Russell King, x86, Thomas Gleixner,
	Benjamin Herrenschmidt, linuxppc-dev, Tony Luck, linux-ia64,
	Thierry Reding, Liviu Dudau, suravee.suthikulpanit

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

That's my mistake, will add CC Yinghai and Jiang in next version.

> 
>> Signed-off-by: Yijing Wang <wangyijing@huawei.com>
>> ---
...
>> +
>> +static void pci_release_host_bridge_dev(struct device *dev)
>> +{
>> +       struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
>> +
>> +       if (bridge->release_fn)
>> +               bridge->release_fn(bridge);
>> +       pci_free_resource_list(&bridge->windows);
>> +       kfree(bridge);
>> +}
>> +
>> +struct pci_host_bridge *pci_create_host_bridge(
>> +               struct device *parent, u32 db,
>> +               struct pci_ops *ops, void *sysdata,
> 
> I don't thinks it is worth moving the buses' pci_ops into pci_host_bridge. It
> might be more useful to have pci_host_bridge specific ops here.

Because we want to create pci_host_bridge before pci root bus creation,
so when we scan the root bus and child buses, we use pci_host_bridge as
the only argument, and another pci_host_info will be addes in later patch,
which one support carry the pci_host_bridge ops.

> 
>> +               struct list_head *resources)
>> +{
>> +       int error;
>> +       struct pci_bus *b;
>> +       struct pci_host_bridge *host, *h;
...
>> -struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
>> -               struct pci_ops *ops, void *sysdata, struct list_head *resources)
>> +struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *bridge)
>>  {
>>         int error;
>> -       struct pci_host_bridge *bridge;
>>         struct pci_bus *b, *b2;
>> -       struct pci_host_bridge_window *window, *n;
>> +       struct pci_host_bridge_window *window;
>>         struct resource *res;
>>         resource_size_t offset;
>>         char bus_addr[64];
>>         char *fmt;
>> -       u8      bus = PCI_BUSNUM(db);
>> +       struct device *parent = bridge->dev.parent;
>>
>>         b = pci_alloc_bus(NULL);
>>         if (!b)
>>                 return NULL;
>>
>> -       b->sysdata = sysdata;
>> -       b->ops = ops;
>> -       b->number = b->busn_res.start = bus;
>> +       b->sysdata = bridge->sysdata;
> 
> I think bridge should be the b->sysdata here. 

? what's the meaning?

> 
>> +       b->ops = bridge->ops;
> 
> See comment above why I don't think this is necessary.
> 
>> +       b->number = b->busn_res.start = bridge->busnum;
>>         pci_bus_assign_domain_nr(b, parent);
>> -       b2 = pci_find_bus(pci_domain_nr(b), bus);
>> +       bridge->domain = pci_domain_nr(b);
> 
> Do you really want to overwrite the bridge's domain with the one from a bus that
> could possibly be rejected a couple of lines further down?
> 
> As an asside: if we are doing the split of pci_host_bridge from root bus creation
> it is worth in my opinion to move the domain setup in pci_create_host_bridge()
> and stop fiddling with it here.


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


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

Thanks!
Yijing.

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


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 08/16] PCI: Introduce pci_scan_host_bridge() and pci_host_info
  2014-11-18 15:42   ` Liviu Dudau
@ 2014-11-19  2:09     ` Yijing Wang
  2014-11-19 16:41       ` Liviu Dudau
  0 siblings, 1 reply; 65+ messages in thread
From: Yijing Wang @ 2014-11-19  2:09 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Bjorn Helgaas, linux-pci, linux-kernel, huxinwei, Wuyun,
	linux-arm-kernel, Russell King, x86, Thomas Gleixner,
	Benjamin Herrenschmidt, linuxppc-dev, Tony Luck, linux-ia64,
	Thierry Reding, Liviu Dudau, suravee.suthikulpanit, Yijing Wang

>>  struct pci_host_bridge *pci_create_host_bridge(
>> -		struct device *parent, u32 db, 
>> -		struct pci_ops *ops, void *sysdata, 
>> -		struct list_head *resources)
>> +		struct device *parent, u32 db, struct pci_ops *ops, 
>> +		struct pci_host_info *info)
>>  {
>>  	int error;
>>  	struct pci_bus *b;
>>  	struct pci_host_bridge *host, *h;
>> -	struct pci_host_bridge_window *window, *n;
>>  
>>  	down_read(&pci_host_bridge_sem);
>>  	list_for_each_entry(h, &pci_host_bridge_list, list) {
>> @@ -53,7 +51,7 @@ struct pci_host_bridge *pci_create_host_bridge(
>>  	if (!host)
>>  		return NULL;
>>  
>> -	host->sysdata = sysdata;
>> +	host->sysdata = info->arg;
>>  	host->busnum = PCI_BUSNUM(db);
>>  	host->domain = PCI_DOMAIN(db);
>>  	host->ops = ops;
>> @@ -63,18 +61,23 @@ struct pci_host_bridge *pci_create_host_bridge(
>>  
>>  	/* this is hack, just for build, will be removed later*/
> 
> Why do you need this hack? Just for calling pci_domain_nr() ?

Yes, it's temporary code, we need domain number here for pci host bridge register.

> 
>>  	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);
>>  
...
>> +static int pci_default_init_res(struct pci_host_bridge *host,
>> +		struct pci_host_info *info)
>> +{
>> +	struct pci_host_bridge_window *window, *n;
>> +
>> +	if (info->res_type != PCI_HOST_RES_DEFAULT) 
>> +		list_for_each_entry_safe(window, n, info->resources,
>> +				list)
>> +			list_move_tail(&window->list, &host->windows);
>> +	else
>> +		info->res_type = PCI_HOST_RES_DEFAULT;
> 
> I'm confused about this assignment. Isn't this a nop as the else part
> means info->res_type *is* PCI_HOST_RES_DEFAULT?

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

+struct pci_host_info {
+	u8 res_type;
+	void *arg;
+	struct list_head *resources; /*just for build, will clean up later */
+	int (*init_res)(struct pci_host_bridge *host,
+			struct pci_host_info *info);
+};
+

> 
>> +
>> +	return 0;
>> +}
...
>> @@ -2038,8 +2057,13 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
>>  	bool found = false;
>>  	struct pci_host_bridge *host;
>>  	int max;
>> +	struct pci_host_info info;
>> +	
>> +	info.arg = sysdata;
>> +	info.resources = resources;
>> +	info.init_res = pci_default_init_res;
> 
> I have mixed feelings about this patch. While it is heading in the right direction
> of moving pci_host_bridge relevant information towards the right user, I don't think
> you picked up the right set to move. The resource list is going to be copied into
> internal pci_host_bridge list anyway, keeping another copy is not helpful *and*
> you have increased the code size.
> 
> I think for now we should aim to get the *missing* data into pci_host_bridge: MSI
> controllers and PCI domain/segment. Then we can do more cleanup.

Hi Liviu, I agree with you here, the changes to resources stuff seems not a perfect
solution. In my patch 6, we could pass pci domain nr by u32 PCI_DOMBUS(domain, bus) argument,
and store it in pci_host_bridge. For msi controller, we couldn't save the msi_controller
in pci_host_bridge. Before we assume one pci host bridge only had one msi_controller,
but now something changes, Jiang introduce hierarchy irq domain in x86, and now
one pci host bridge may has more than one msi_controller. So I prefer to add a
function to pci_host_bridge something like

struct msi_controller *pci_get_msi_controller(struct pci_dev *dev)

> 
>>  
>> -	host = pci_create_host_bridge(parent, db, ops, sysdata, resources);
>> +	host = pci_create_host_bridge(parent, db, ops, &info);
>>  	if (!host)
>>  		return NULL;
>>  
>> @@ -2070,6 +2094,47 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
>>  }
>>  EXPORT_SYMBOL(pci_scan_root_bus);
>>  
>> +struct pci_host_bridge *pci_scan_host_bridge(
>> +		struct device *parent, u32 db, struct pci_ops *ops,
>> +		struct pci_host_info *info)
>> +{
>> +	struct pci_host_bridge_window *window;
>> +	bool found = false;
>> +	struct pci_host_bridge *host;
>> +	int max;
>> +
>> +	host = pci_create_host_bridge(parent, db, ops, info);
>> +	if (!host)
>> +		return NULL;
>> +
>> +	list_for_each_entry(window, &host->windows, list)
>> +		if (window->res->flags & IORESOURCE_BUS) {
>> +			found = true;
>> +			break;
>> +		}
>> +
>> +	host->bus = __pci_create_root_bus(host);
>> +	if (!host->bus) {
>> +		pci_free_host_bridge(host);
>> +		return NULL;
>> +	}
>> +
>> +	if (!found) {
>> +		dev_info(&host->bus->dev,
>> +		 "No busn resource found for root bus, will use [bus %02x-ff]\n",
>> +			host->busnum);
>> +		pci_bus_insert_busn_res(host->bus, host->busnum, 255);
>> +	}
>> +
>> +	max = pci_scan_child_bus(host->bus);
>> +	if (!found)
>> +		pci_bus_update_busn_res_end(host->bus, max);
>> +
>> +	return host;
>> +
>> +}
>> +EXPORT_SYMBOL(pci_scan_host_bridge);
>> +
>>  /**
>>   * pci_rescan_bus_bridge_resize - scan a PCI bus for devices.
>>   * @bridge: PCI bridge for the bus to scan
>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>> index daa7f40..a51f5f5 100644
>> --- a/include/linux/pci.h
>> +++ b/include/linux/pci.h
>> @@ -412,6 +412,21 @@ struct pci_host_bridge {
>>  	void *release_data;
>>  };
>>  
>> +struct pci_host_info {
>> +	u8 res_type;
>> +	void *arg;
>> +	struct list_head *resources; /*just for build, will clean up later */
>> +	int (*init_res)(struct pci_host_bridge *host, 
>> +			struct pci_host_info *info);
>> +};
>> +
>> +static inline void init_pci_host_info(struct pci_host_info *info)
>> +{
>> +	memset(info, 0 , sizeof(*info));
>> +}
> 
> Where is this used?

Host driver uses it to init pci_host_info.

> 
>> +
>> +#define PCI_HOST_RES_DEFAULT	0x2
>> +
> 
> Magic number?

Hmmm, I will rework pci host bridge resources stuff.

> 
> Best regards,
> Liviu
> 
>>  #define	to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)
>>  void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
>>  		     void (*release_fn)(struct pci_host_bridge *),
>> @@ -420,7 +435,7 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
>>  int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
>>  struct pci_host_bridge *pci_create_host_bridge(
>>  		struct device *parent, u32 db, struct pci_ops *ops, 
>> -		void *sys, struct list_head *resources);
>> +		struct pci_host_info *info);
>>  /*
>>   * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
>>   * to P2P or CardBus bridge windows) go in a table.  Additional ones (for
>> @@ -785,6 +800,9 @@ void pci_bus_release_busn_res(struct pci_bus *b);
>>  struct pci_bus *pci_scan_root_bus(struct device *parent, u32 bus,
>>  					     struct pci_ops *ops, void *sysdata,
>>  					     struct list_head *resources);
>> +struct pci_host_bridge *pci_scan_host_bridge(struct device *parent,
>> +		u32 db, struct pci_ops *ops,
>> +		struct pci_host_info *info);
>>  struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
>>  				int busnr);
>>  void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);
>> -- 
>> 1.7.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
> 


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
  2014-11-18 14:48       ` Liviu Dudau
@ 2014-11-19  2:24         ` Yijing Wang
  2014-11-19 16:29           ` Liviu Dudau
  0 siblings, 1 reply; 65+ messages in thread
From: Yijing Wang @ 2014-11-19  2:24 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Arnd Bergmann, linuxppc-dev, Bjorn Helgaas, Liviu Dudau,
	Tony Luck, Russell King, linux-pci, x86, linux-kernel, huxinwei,
	Thierry Reding, suravee.suthikulpanit, linux-ia64,
	Thomas Gleixner, Wuyun, linux-arm-kernel

>> We need, some platforms pass NULL pointer as host bridge parent.
> 
> Yijing,
> 
> May I suggest a different approach here? Rather than having to pass an opaque
> pointer that gets converted by the host bridge driver back to the private
> structure, what about promoting a new style of usage, that is similar to the
> way device drivers work? Lets try to promote the embedding of the generic
> pci_host_bridge structure in the host bridge specific structure! Then we can
> access the private data doing container_of().
> 
> Something like this:
> 
> struct pci_controller {
> 	struct pci_host_bridge bridge;
> 	/* private host bridge data here */
> 	.....
> };
> 
> #define PCI_CONTROLLER(bus)	({
> 	struct pci_host_bridge *hb = to_pci_host_bridge(bus->bridge); \
> 	container_of(hb, struct pci_controller, bridge); })
> 
> 
> Then we can retrieve the host bridge structure from everywhere we have a device.

Hi Liviu, it looks good to me, because this change will involve lots platforms,
I would think more about it. Thanks for your suggestion very much! :)


Thanks!
Yijing.

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


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
  2014-11-19  2:24         ` Yijing Wang
@ 2014-11-19 16:29           ` Liviu Dudau
  2014-11-20  2:00             ` Yijing Wang
  0 siblings, 1 reply; 65+ messages in thread
From: Liviu Dudau @ 2014-11-19 16:29 UTC (permalink / raw)
  To: Yijing Wang
  Cc: Liviu Dudau, Arnd Bergmann, linuxppc-dev, Bjorn Helgaas,
	Tony Luck, Russell King, linux-pci, x86, linux-kernel, huxinwei,
	Thierry Reding, suravee.suthikulpanit, linux-ia64,
	Thomas Gleixner, Wuyun, linux-arm-kernel

On Wed, Nov 19, 2014 at 10:24:52AM +0800, Yijing Wang wrote:
> >> We need, some platforms pass NULL pointer as host bridge parent.
> > 
> > Yijing,
> > 
> > May I suggest a different approach here? Rather than having to pass an opaque
> > pointer that gets converted by the host bridge driver back to the private
> > structure, what about promoting a new style of usage, that is similar to the
> > way device drivers work? Lets try to promote the embedding of the generic
> > pci_host_bridge structure in the host bridge specific structure! Then we can
> > access the private data doing container_of().
> > 
> > Something like this:
> > 
> > struct pci_controller {
> > 	struct pci_host_bridge bridge;
> > 	/* private host bridge data here */
> > 	.....
> > };
> > 
> > #define PCI_CONTROLLER(bus)	({
> > 	struct pci_host_bridge *hb = to_pci_host_bridge(bus->bridge); \
> > 	container_of(hb, struct pci_controller, bridge); })
> > 
> > 
> > Then we can retrieve the host bridge structure from everywhere we have a device.
> 
> Hi Liviu, it looks good to me, because this change will involve lots platforms,
> I would think more about it. Thanks for your suggestion very much! :)

Given that I also look at this area maybe we should join forces and divide the problem?

Best regards,
Liviu

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

-- 
-------------------
   .oooO
   (   )
    \ (  Oooo.
     \_) (   )
          ) /
         (_/

 One small step
   for me ...


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

* Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
  2014-11-19  1:42     ` Yijing Wang
@ 2014-11-19 16:37       ` Liviu Dudau
  2014-11-20  2:47         ` Yijing Wang
  0 siblings, 1 reply; 65+ messages in thread
From: Liviu Dudau @ 2014-11-19 16:37 UTC (permalink / raw)
  To: Yijing Wang
  Cc: Bjorn Helgaas, linux-pci, linux-kernel, huxinwei, Wuyun,
	linux-arm-kernel, Russell King, x86, Thomas Gleixner,
	Benjamin Herrenschmidt, linuxppc-dev, Tony Luck, linux-ia64,
	Thierry Reding, Liviu Dudau, suravee.suthikulpanit

On Wed, Nov 19, 2014 at 01:42:52AM +0000, Yijing Wang wrote:
> On 2014/11/18 23:30, Liviu Dudau wrote:
> > On Mon, Nov 17, 2014 at 10:21:41AM +0000, Yijing Wang wrote:
> >> There are some common PCI infos like domain, msi_controller, these
> >> infos are saved in arch PCI sysdata, and lots arch specific functions
> >> like pci_domain_nr() and pcibios_msi_controller() required.
> >> We could separate pci_host_bridge creation out of pci_create_root_bus(),
> >> then we could put the common infos in, then we could eliminate
> >> the arch specifc functions.
> >>
> >
> > Please Cc: Yinghai Lu and Jiang Liu on future versions.
> >
> > More comments on the conversion of pci_create_root_bus():
> 
> That's my mistake, will add CC Yinghai and Jiang in next version.
> 
> >
> >> Signed-off-by: Yijing Wang <wangyijing@huawei.com>
> >> ---
> ...
> >> +
> >> +static void pci_release_host_bridge_dev(struct device *dev)
> >> +{
> >> +       struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
> >> +
> >> +       if (bridge->release_fn)
> >> +               bridge->release_fn(bridge);
> >> +       pci_free_resource_list(&bridge->windows);
> >> +       kfree(bridge);
> >> +}
> >> +
> >> +struct pci_host_bridge *pci_create_host_bridge(
> >> +               struct device *parent, u32 db,
> >> +               struct pci_ops *ops, void *sysdata,
> >
> > I don't thinks it is worth moving the buses' pci_ops into pci_host_bridge. It
> > might be more useful to have pci_host_bridge specific ops here.
> 
> Because we want to create pci_host_bridge before pci root bus creation,
> so when we scan the root bus and child buses, we use pci_host_bridge as
> the only argument, and another pci_host_info will be addes in later patch,
> which one support carry the pci_host_bridge ops.

But pci_create_root_bus() already has a pci_ops argument, I don't see the reason
to drop that.

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

> 
> >
> >> +               struct list_head *resources)
> >> +{
> >> +       int error;
> >> +       struct pci_bus *b;
> >> +       struct pci_host_bridge *host, *h;
> ...
> >> -struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
> >> -               struct pci_ops *ops, void *sysdata, struct list_head *resources)
> >> +struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *bridge)
> >>  {
> >>         int error;
> >> -       struct pci_host_bridge *bridge;
> >>         struct pci_bus *b, *b2;
> >> -       struct pci_host_bridge_window *window, *n;
> >> +       struct pci_host_bridge_window *window;
> >>         struct resource *res;
> >>         resource_size_t offset;
> >>         char bus_addr[64];
> >>         char *fmt;
> >> -       u8      bus = PCI_BUSNUM(db);
> >> +       struct device *parent = bridge->dev.parent;
> >>
> >>         b = pci_alloc_bus(NULL);
> >>         if (!b)
> >>                 return NULL;
> >>
> >> -       b->sysdata = sysdata;
> >> -       b->ops = ops;
> >> -       b->number = b->busn_res.start = bus;
> >> +       b->sysdata = bridge->sysdata;
> >
> > I think bridge should be the b->sysdata here.
> 
> ? what's the meaning?

Currently, bus->sysdata holds a pointer to the arch/driver host bridge structure, as passed
in pci_create_root_bus(). If you agree with my idea of wrapping the host bridge driver
structure around the pci_host_bridge, then we will always have a way of retrieving that
information; but for backwards compatibility we could set bus->sysdata to be the bridge.
Then existing macros that convert sysdata to pci_controller can be reused after being
updated.

Best regards,
Liviu

> 
> >
> >> +       b->ops = bridge->ops;
> >
> > See comment above why I don't think this is necessary.
> >
> >> +       b->number = b->busn_res.start = bridge->busnum;
> >>         pci_bus_assign_domain_nr(b, parent);
> >> -       b2 = pci_find_bus(pci_domain_nr(b), bus);
> >> +       bridge->domain = pci_domain_nr(b);
> >
> > Do you really want to overwrite the bridge's domain with the one from a bus that
> > could possibly be rejected a couple of lines further down?
> >
> > As an asside: if we are doing the split of pci_host_bridge from root bus creation
> > it is worth in my opinion to move the domain setup in pci_create_host_bridge()
> > and stop fiddling with it here.
> 
> 
> Hi Liviu, these lines just temporary, I will remove it after all host drivers
> save its domain in pci_host_bridge.
> 
> 
> >
> > Otherwise it looks to me like you are heading in the right direction.
> 
> Thanks!
> Yijing.
> 
> >
> > Best regards,
> > Liviu
> >
> >> +       b2 = pci_find_bus(pci_domain_nr(b), bridge->busnum);
> >>         if (b2) {
> >>                 /* If we already got to this bus through a different bridge, ignore it */
> >>                 dev_dbg(&b2->dev, "bus already known\n");
> >>                 goto err_out;
> >>         }
> >>
> >> -       bridge = pci_alloc_host_bridge(b);
> >> -       if (!bridge)
> >> -               goto err_out;
> >> -
> >> -       bridge->dev.parent = parent;
> >> -       bridge->dev.release = pci_release_host_bridge_dev;
> >> -       dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
> >> -       error = pcibios_root_bridge_prepare(bridge);
> >> -       if (error) {
> >> -               kfree(bridge);
> >> -               goto err_out;
> >> -       }
> >> -
> >> -       error = device_register(&bridge->dev);
> >> -       if (error) {
> >> -               put_device(&bridge->dev);
> >> -               goto err_out;
> >> -       }
> >>         b->bridge = get_device(&bridge->dev);
> >>         device_enable_async_suspend(b->bridge);
> >>         pci_set_bus_of_node(b);
> >> @@ -1950,7 +1899,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
> >>
> >>         b->dev.class = &pcibus_class;
> >>         b->dev.parent = b->bridge;
> >> -       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
> >> +       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), b->number);
> >>         error = device_register(&b->dev);
> >>         if (error)
> >>                 goto class_dev_reg_err;
> >> @@ -1966,12 +1915,11 @@ struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
> >>                 printk(KERN_INFO "PCI host bridge to bus %s\n", dev_name(&b->dev));
> >>
> >>         /* Add initial resources to the bus */
> >> -       list_for_each_entry_safe(window, n, resources, list) {
> >> -               list_move_tail(&window->list, &bridge->windows);
> >> +       list_for_each_entry(window, &bridge->windows, list) {
> >>                 res = window->res;
> >>                 offset = window->offset;
> >>                 if (res->flags & IORESOURCE_BUS)
> >> -                       pci_bus_insert_busn_res(b, bus, res->end);
> >> +                       pci_bus_insert_busn_res(b, b->number, res->end);
> >>                 else
> >>                         pci_bus_add_resource(b, res, 0);
> >>                 if (offset) {
> >> @@ -2001,6 +1949,25 @@ err_out:
> >>         return NULL;
> >>  }
> >>
> >> +struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
> >> +               struct pci_ops *ops, void *sysdata, struct list_head *resources)
> >> +{
> >> +       struct pci_host_bridge *host;
> >> +
> >> +       host = pci_create_host_bridge(parent, bus, ops,
> >> +                       sysdata ,resources);
> >> +       if (!host)
> >> +               return NULL;
> >> +
> >> +       host->bus = __pci_create_root_bus(host);
> >> +       if (!host->bus) {
> >> +               pci_free_host_bridge(host);
> >> +               return NULL;
> >> +       }
> >> +
> >> +       return host->bus;
> >> +}
> >> +
> >>  int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
> >>  {
> >>         struct resource *res = &b->busn_res;
> >> @@ -2069,40 +2036,37 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
> >>  {
> >>         struct pci_host_bridge_window *window;
> >>         bool found = false;
> >> -       struct pci_bus *b;
> >> -       LIST_HEAD(default_res);
> >> +       struct pci_host_bridge *host;
> >>         int max;
> >>
> >> -       if (!resources) {
> >> -               pci_add_resource(&default_res, &ioport_resource);
> >> -               pci_add_resource(&default_res, &iomem_resource);
> >> -               pci_add_resource(&default_res, &busn_resource);
> >> -       } else {
> >> -               list_for_each_entry(window, resources, list)
> >> -                       if (window->res->flags & IORESOURCE_BUS) {
> >> -                               found = true;
> >> -                               break;
> >> -                       }
> >> -       }
> >> +       host = pci_create_host_bridge(parent, db, ops, sysdata, resources);
> >> +       if (!host)
> >> +               return NULL;
> >>
> >> -       b = pci_create_root_bus(parent, db, ops, sysdata,
> >> -                       resources ? resources : &default_res);
> >> -       if (!b)
> >> +       list_for_each_entry(window, &host->windows, list)
> >> +               if (window->res->flags & IORESOURCE_BUS) {
> >> +                       found = true;
> >> +                       break;
> >> +               }
> >> +
> >> +       host->bus = __pci_create_root_bus(host);
> >> +       if (!host->bus) {
> >> +               pci_free_host_bridge(host);
> >>                 return NULL;
> >> +       }
> >>
> >>         if (!found) {
> >> -               dev_info(&b->dev,
> >> +               dev_info(&host->bus->dev,
> >>                  "No busn resource found for root bus, will use [bus %02x-ff]\n",
> >>                         PCI_BUSNUM(db));
> >> -               pci_bus_insert_busn_res(b, PCI_BUSNUM(db), 255);
> >> +               pci_bus_insert_busn_res(host->bus, PCI_BUSNUM(db), 255);
> >>         }
> >>
> >> -       max = pci_scan_child_bus(b);
> >> -
> >> +       max = pci_scan_child_bus(host->bus);
> >>         if (!found)
> >> -               pci_bus_update_busn_res_end(b, max);
> >> +               pci_bus_update_busn_res_end(host->bus, max);
> >>
> >> -       return b;
> >> +       return host->bus;
> >>  }
> >>  EXPORT_SYMBOL(pci_scan_root_bus);
> >>
> >> diff --git a/include/linux/pci.h b/include/linux/pci.h
> >> index 8b11b38..daa7f40 100644
> >> --- a/include/linux/pci.h
> >> +++ b/include/linux/pci.h
> >> @@ -402,7 +402,12 @@ struct pci_host_bridge_window {
> >>  struct pci_host_bridge {
> >>         struct device dev;
> >>         struct pci_bus *bus;            /* root bus */
> >> +       struct list_head list;
> >>         struct list_head windows;       /* pci_host_bridge_windows */
> >> +       int busnum;
> >> +       int domain;
> >> +       void *sysdata;
> >> +       struct pci_ops *ops;
> >>         void (*release_fn)(struct pci_host_bridge *);
> >>         void *release_data;
> >>  };
> >> @@ -413,7 +418,9 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
> >>                      void *release_data);
> >>
> >>  int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
> >> -
> >> +struct pci_host_bridge *pci_create_host_bridge(
> >> +               struct device *parent, u32 db, struct pci_ops *ops,
> >> +               void *sys, struct list_head *resources);
> >>  /*
> >>   * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
> >>   * to P2P or CardBus bridge windows) go in a table.  Additional ones (for
> >> @@ -770,6 +777,8 @@ void pci_bus_add_devices(const struct pci_bus *bus);
> >>  struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
> >>                                     struct pci_ops *ops, void *sysdata,
> >>                                     struct list_head *resources);
> >> +struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *host);
> >> +void pci_free_host_bridge(struct pci_host_bridge *host);
> >>  int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
> >>  int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
> >>  void pci_bus_release_busn_res(struct pci_bus *b);
> >> --
> >> 1.7.1
> >>
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> >> the body of a message to majordomo@vger.kernel.org
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >>
> >
> 
> 
> --
> Thanks!
> Yijing
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯


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

* Re: [RFC PATCH 08/16] PCI: Introduce pci_scan_host_bridge() and pci_host_info
  2014-11-19  2:09     ` Yijing Wang
@ 2014-11-19 16:41       ` Liviu Dudau
  2014-11-20  2:54         ` Yijing Wang
  0 siblings, 1 reply; 65+ messages in thread
From: Liviu Dudau @ 2014-11-19 16:41 UTC (permalink / raw)
  To: Yijing Wang
  Cc: Bjorn Helgaas, linux-pci, linux-kernel, huxinwei, Wuyun,
	linux-arm-kernel, Russell King, x86, Thomas Gleixner,
	Benjamin Herrenschmidt, linuxppc-dev, Tony Luck, linux-ia64,
	Thierry Reding, Liviu Dudau, suravee.suthikulpanit, Yijing Wang

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

That's not what I've asked! Your code does:

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

info->res_type is already == PCI_HOST_RES_DEFAULT in the else side, assignment is a NOP?


> 
> > 
> >> +
> >> +	return 0;
> >> +}
> ...
> >> @@ -2038,8 +2057,13 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
> >>  	bool found = false;
> >>  	struct pci_host_bridge *host;
> >>  	int max;
> >> +	struct pci_host_info info;
> >> +	
> >> +	info.arg = sysdata;
> >> +	info.resources = resources;
> >> +	info.init_res = pci_default_init_res;
> > 
> > I have mixed feelings about this patch. While it is heading in the right direction
> > of moving pci_host_bridge relevant information towards the right user, I don't think
> > you picked up the right set to move. The resource list is going to be copied into
> > internal pci_host_bridge list anyway, keeping another copy is not helpful *and*
> > you have increased the code size.
> > 
> > I think for now we should aim to get the *missing* data into pci_host_bridge: MSI
> > controllers and PCI domain/segment. Then we can do more cleanup.
> 
> Hi Liviu, I agree with you here, the changes to resources stuff seems not a perfect
> solution. In my patch 6, we could pass pci domain nr by u32 PCI_DOMBUS(domain, bus) argument,
> and store it in pci_host_bridge. For msi controller, we couldn't save the msi_controller
> in pci_host_bridge. Before we assume one pci host bridge only had one msi_controller,
> but now something changes, Jiang introduce hierarchy irq domain in x86, and now
> one pci host bridge may has more than one msi_controller. So I prefer to add a
> function to pci_host_bridge something like
> 
> struct msi_controller *pci_get_msi_controller(struct pci_dev *dev)

Yes, good idea.

> 
> > 
> >>  
> >> -	host = pci_create_host_bridge(parent, db, ops, sysdata, resources);
> >> +	host = pci_create_host_bridge(parent, db, ops, &info);
> >>  	if (!host)
> >>  		return NULL;
> >>  
> >> @@ -2070,6 +2094,47 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
> >>  }
> >>  EXPORT_SYMBOL(pci_scan_root_bus);
> >>  
> >> +struct pci_host_bridge *pci_scan_host_bridge(
> >> +		struct device *parent, u32 db, struct pci_ops *ops,
> >> +		struct pci_host_info *info)
> >> +{
> >> +	struct pci_host_bridge_window *window;
> >> +	bool found = false;
> >> +	struct pci_host_bridge *host;
> >> +	int max;
> >> +
> >> +	host = pci_create_host_bridge(parent, db, ops, info);
> >> +	if (!host)
> >> +		return NULL;
> >> +
> >> +	list_for_each_entry(window, &host->windows, list)
> >> +		if (window->res->flags & IORESOURCE_BUS) {
> >> +			found = true;
> >> +			break;
> >> +		}
> >> +
> >> +	host->bus = __pci_create_root_bus(host);
> >> +	if (!host->bus) {
> >> +		pci_free_host_bridge(host);
> >> +		return NULL;
> >> +	}
> >> +
> >> +	if (!found) {
> >> +		dev_info(&host->bus->dev,
> >> +		 "No busn resource found for root bus, will use [bus %02x-ff]\n",
> >> +			host->busnum);
> >> +		pci_bus_insert_busn_res(host->bus, host->busnum, 255);
> >> +	}
> >> +
> >> +	max = pci_scan_child_bus(host->bus);
> >> +	if (!found)
> >> +		pci_bus_update_busn_res_end(host->bus, max);
> >> +
> >> +	return host;
> >> +
> >> +}
> >> +EXPORT_SYMBOL(pci_scan_host_bridge);
> >> +
> >>  /**
> >>   * pci_rescan_bus_bridge_resize - scan a PCI bus for devices.
> >>   * @bridge: PCI bridge for the bus to scan
> >> diff --git a/include/linux/pci.h b/include/linux/pci.h
> >> index daa7f40..a51f5f5 100644
> >> --- a/include/linux/pci.h
> >> +++ b/include/linux/pci.h
> >> @@ -412,6 +412,21 @@ struct pci_host_bridge {
> >>  	void *release_data;
> >>  };
> >>  
> >> +struct pci_host_info {
> >> +	u8 res_type;
> >> +	void *arg;
> >> +	struct list_head *resources; /*just for build, will clean up later */
> >> +	int (*init_res)(struct pci_host_bridge *host, 
> >> +			struct pci_host_info *info);
> >> +};
> >> +
> >> +static inline void init_pci_host_info(struct pci_host_info *info)
> >> +{
> >> +	memset(info, 0 , sizeof(*info));
> >> +}
> > 
> > Where is this used?
> 
> Host driver uses it to init pci_host_info.

Might be worth adding it that patch rather than here.

Best regards,
Liviu

> 
> > 
> >> +
> >> +#define PCI_HOST_RES_DEFAULT	0x2
> >> +
> > 
> > Magic number?
> 
> Hmmm, I will rework pci host bridge resources stuff.
> 
> > 
> > Best regards,
> > Liviu
> > 
> >>  #define	to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)
> >>  void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
> >>  		     void (*release_fn)(struct pci_host_bridge *),
> >> @@ -420,7 +435,7 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
> >>  int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
> >>  struct pci_host_bridge *pci_create_host_bridge(
> >>  		struct device *parent, u32 db, struct pci_ops *ops, 
> >> -		void *sys, struct list_head *resources);
> >> +		struct pci_host_info *info);
> >>  /*
> >>   * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
> >>   * to P2P or CardBus bridge windows) go in a table.  Additional ones (for
> >> @@ -785,6 +800,9 @@ void pci_bus_release_busn_res(struct pci_bus *b);
> >>  struct pci_bus *pci_scan_root_bus(struct device *parent, u32 bus,
> >>  					     struct pci_ops *ops, void *sysdata,
> >>  					     struct list_head *resources);
> >> +struct pci_host_bridge *pci_scan_host_bridge(struct device *parent,
> >> +		u32 db, struct pci_ops *ops,
> >> +		struct pci_host_info *info);
> >>  struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
> >>  				int busnr);
> >>  void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);
> >> -- 
> >> 1.7.1
> >>
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> >> the body of a message to majordomo@vger.kernel.org
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >>
> > 
> 
> 
> -- 
> Thanks!
> Yijing
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯


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

* Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
  2014-11-19 16:29           ` Liviu Dudau
@ 2014-11-20  2:00             ` Yijing Wang
  0 siblings, 0 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-20  2:00 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Liviu Dudau, Arnd Bergmann, linuxppc-dev, Bjorn Helgaas,
	Tony Luck, Russell King, linux-pci, x86, linux-kernel, huxinwei,
	Thierry Reding, suravee.suthikulpanit, linux-ia64,
	Thomas Gleixner, Wuyun, linux-arm-kernel

>>> Something like this:
>>>
>>> struct pci_controller {
>>> 	struct pci_host_bridge bridge;
>>> 	/* private host bridge data here */
>>> 	.....
>>> };
>>>
>>> #define PCI_CONTROLLER(bus)	({
>>> 	struct pci_host_bridge *hb = to_pci_host_bridge(bus->bridge); \
>>> 	container_of(hb, struct pci_controller, bridge); })
>>>
>>>
>>> Then we can retrieve the host bridge structure from everywhere we have a device.
>>
>> Hi Liviu, it looks good to me, because this change will involve lots platforms,
>> I would think more about it. Thanks for your suggestion very much! :)
> 
> Given that I also look at this area maybe we should join forces and divide the problem?

That's better, we could cooperate to do this. :)

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


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
  2014-11-19 16:37       ` Liviu Dudau
@ 2014-11-20  2:47         ` Yijing Wang
  2014-11-20  9:47           ` Liviu Dudau
  0 siblings, 1 reply; 65+ messages in thread
From: Yijing Wang @ 2014-11-20  2:47 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Bjorn Helgaas, linux-pci, linux-kernel, huxinwei, Wuyun,
	linux-arm-kernel, Russell King, x86, Thomas Gleixner,
	Benjamin Herrenschmidt, linuxppc-dev, Tony Luck, linux-ia64,
	Thierry Reding, Liviu Dudau, suravee.suthikulpanit

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

I want to unexport pci_create_root_bus() if we have pci_create_host_bridge().


>>>> -struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
>>>> -               struct pci_ops *ops, void *sysdata, struct list_head *resources)
>>>> +struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *bridge)
>>>>  {
>>>>         int error;
>>>> -       struct pci_host_bridge *bridge;
>>>>         struct pci_bus *b, *b2;
>>>> -       struct pci_host_bridge_window *window, *n;
>>>> +       struct pci_host_bridge_window *window;
>>>>         struct resource *res;
>>>>         resource_size_t offset;
>>>>         char bus_addr[64];
>>>>         char *fmt;
>>>> -       u8      bus = PCI_BUSNUM(db);
>>>> +       struct device *parent = bridge->dev.parent;
>>>>
>>>>         b = pci_alloc_bus(NULL);
>>>>         if (!b)
>>>>                 return NULL;
>>>>
>>>> -       b->sysdata = sysdata;
>>>> -       b->ops = ops;
>>>> -       b->number = b->busn_res.start = bus;
>>>> +       b->sysdata = bridge->sysdata;
>>>
>>> I think bridge should be the b->sysdata here.
>>
>> ? what's the meaning?
> 
> Currently, bus->sysdata holds a pointer to the arch/driver host bridge structure, as passed
> in pci_create_root_bus(). If you agree with my idea of wrapping the host bridge driver
> structure around the pci_host_bridge, then we will always have a way of retrieving that
> information; but for backwards compatibility we could set bus->sysdata to be the bridge.
> Then existing macros that convert sysdata to pci_controller can be reused after being
> updated.

I think wrapping the host bridge driver structure around the pci_host_bridge could help
us to find the private pci_controller, but in this case, pci_host_bridge is not a pointer
so we put all pci_host_bridge init stuff in host drivers ? And if we still use arch spec
macros convert ssydata to pci_controller, so what's the greatest advantage ?

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



> 
> Best regards,
> Liviu
> 
>>
>>>
>>>> +       b->ops = bridge->ops;
>>>
>>> See comment above why I don't think this is necessary.
>>>
>>>> +       b->number = b->busn_res.start = bridge->busnum;
>>>>         pci_bus_assign_domain_nr(b, parent);
>>>> -       b2 = pci_find_bus(pci_domain_nr(b), bus);
>>>> +       bridge->domain = pci_domain_nr(b);
>>>
>>> Do you really want to overwrite the bridge's domain with the one from a bus that
>>> could possibly be rejected a couple of lines further down?
>>>
>>> As an asside: if we are doing the split of pci_host_bridge from root bus creation
>>> it is worth in my opinion to move the domain setup in pci_create_host_bridge()
>>> and stop fiddling with it here.
>>
>>
>> Hi Liviu, these lines just temporary, I will remove it after all host drivers
>> save its domain in pci_host_bridge.
>>
>>
>>>
>>> Otherwise it looks to me like you are heading in the right direction.
>>
>> Thanks!
>> Yijing.
>>
>>>
>>> Best regards,
>>> Liviu
>>>
>>>> +       b2 = pci_find_bus(pci_domain_nr(b), bridge->busnum);
>>>>         if (b2) {
>>>>                 /* If we already got to this bus through a different bridge, ignore it */
>>>>                 dev_dbg(&b2->dev, "bus already known\n");
>>>>                 goto err_out;
>>>>         }
>>>>
>>>> -       bridge = pci_alloc_host_bridge(b);
>>>> -       if (!bridge)
>>>> -               goto err_out;
>>>> -
>>>> -       bridge->dev.parent = parent;
>>>> -       bridge->dev.release = pci_release_host_bridge_dev;
>>>> -       dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
>>>> -       error = pcibios_root_bridge_prepare(bridge);
>>>> -       if (error) {
>>>> -               kfree(bridge);
>>>> -               goto err_out;
>>>> -       }
>>>> -
>>>> -       error = device_register(&bridge->dev);
>>>> -       if (error) {
>>>> -               put_device(&bridge->dev);
>>>> -               goto err_out;
>>>> -       }
>>>>         b->bridge = get_device(&bridge->dev);
>>>>         device_enable_async_suspend(b->bridge);
>>>>         pci_set_bus_of_node(b);
>>>> @@ -1950,7 +1899,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
>>>>
>>>>         b->dev.class = &pcibus_class;
>>>>         b->dev.parent = b->bridge;
>>>> -       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
>>>> +       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), b->number);
>>>>         error = device_register(&b->dev);
>>>>         if (error)
>>>>                 goto class_dev_reg_err;
>>>> @@ -1966,12 +1915,11 @@ struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
>>>>                 printk(KERN_INFO "PCI host bridge to bus %s\n", dev_name(&b->dev));
>>>>
>>>>         /* Add initial resources to the bus */
>>>> -       list_for_each_entry_safe(window, n, resources, list) {
>>>> -               list_move_tail(&window->list, &bridge->windows);
>>>> +       list_for_each_entry(window, &bridge->windows, list) {
>>>>                 res = window->res;
>>>>                 offset = window->offset;
>>>>                 if (res->flags & IORESOURCE_BUS)
>>>> -                       pci_bus_insert_busn_res(b, bus, res->end);
>>>> +                       pci_bus_insert_busn_res(b, b->number, res->end);
>>>>                 else
>>>>                         pci_bus_add_resource(b, res, 0);
>>>>                 if (offset) {
>>>> @@ -2001,6 +1949,25 @@ err_out:
>>>>         return NULL;
>>>>  }
>>>>
>>>> +struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
>>>> +               struct pci_ops *ops, void *sysdata, struct list_head *resources)
>>>> +{
>>>> +       struct pci_host_bridge *host;
>>>> +
>>>> +       host = pci_create_host_bridge(parent, bus, ops,
>>>> +                       sysdata ,resources);
>>>> +       if (!host)
>>>> +               return NULL;
>>>> +
>>>> +       host->bus = __pci_create_root_bus(host);
>>>> +       if (!host->bus) {
>>>> +               pci_free_host_bridge(host);
>>>> +               return NULL;
>>>> +       }
>>>> +
>>>> +       return host->bus;
>>>> +}
>>>> +
>>>>  int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
>>>>  {
>>>>         struct resource *res = &b->busn_res;
>>>> @@ -2069,40 +2036,37 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
>>>>  {
>>>>         struct pci_host_bridge_window *window;
>>>>         bool found = false;
>>>> -       struct pci_bus *b;
>>>> -       LIST_HEAD(default_res);
>>>> +       struct pci_host_bridge *host;
>>>>         int max;
>>>>
>>>> -       if (!resources) {
>>>> -               pci_add_resource(&default_res, &ioport_resource);
>>>> -               pci_add_resource(&default_res, &iomem_resource);
>>>> -               pci_add_resource(&default_res, &busn_resource);
>>>> -       } else {
>>>> -               list_for_each_entry(window, resources, list)
>>>> -                       if (window->res->flags & IORESOURCE_BUS) {
>>>> -                               found = true;
>>>> -                               break;
>>>> -                       }
>>>> -       }
>>>> +       host = pci_create_host_bridge(parent, db, ops, sysdata, resources);
>>>> +       if (!host)
>>>> +               return NULL;
>>>>
>>>> -       b = pci_create_root_bus(parent, db, ops, sysdata,
>>>> -                       resources ? resources : &default_res);
>>>> -       if (!b)
>>>> +       list_for_each_entry(window, &host->windows, list)
>>>> +               if (window->res->flags & IORESOURCE_BUS) {
>>>> +                       found = true;
>>>> +                       break;
>>>> +               }
>>>> +
>>>> +       host->bus = __pci_create_root_bus(host);
>>>> +       if (!host->bus) {
>>>> +               pci_free_host_bridge(host);
>>>>                 return NULL;
>>>> +       }
>>>>
>>>>         if (!found) {
>>>> -               dev_info(&b->dev,
>>>> +               dev_info(&host->bus->dev,
>>>>                  "No busn resource found for root bus, will use [bus %02x-ff]\n",
>>>>                         PCI_BUSNUM(db));
>>>> -               pci_bus_insert_busn_res(b, PCI_BUSNUM(db), 255);
>>>> +               pci_bus_insert_busn_res(host->bus, PCI_BUSNUM(db), 255);
>>>>         }
>>>>
>>>> -       max = pci_scan_child_bus(b);
>>>> -
>>>> +       max = pci_scan_child_bus(host->bus);
>>>>         if (!found)
>>>> -               pci_bus_update_busn_res_end(b, max);
>>>> +               pci_bus_update_busn_res_end(host->bus, max);
>>>>
>>>> -       return b;
>>>> +       return host->bus;
>>>>  }
>>>>  EXPORT_SYMBOL(pci_scan_root_bus);
>>>>
>>>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>>>> index 8b11b38..daa7f40 100644
>>>> --- a/include/linux/pci.h
>>>> +++ b/include/linux/pci.h
>>>> @@ -402,7 +402,12 @@ struct pci_host_bridge_window {
>>>>  struct pci_host_bridge {
>>>>         struct device dev;
>>>>         struct pci_bus *bus;            /* root bus */
>>>> +       struct list_head list;
>>>>         struct list_head windows;       /* pci_host_bridge_windows */
>>>> +       int busnum;
>>>> +       int domain;
>>>> +       void *sysdata;
>>>> +       struct pci_ops *ops;
>>>>         void (*release_fn)(struct pci_host_bridge *);
>>>>         void *release_data;
>>>>  };
>>>> @@ -413,7 +418,9 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
>>>>                      void *release_data);
>>>>
>>>>  int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
>>>> -
>>>> +struct pci_host_bridge *pci_create_host_bridge(
>>>> +               struct device *parent, u32 db, struct pci_ops *ops,
>>>> +               void *sys, struct list_head *resources);
>>>>  /*
>>>>   * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
>>>>   * to P2P or CardBus bridge windows) go in a table.  Additional ones (for
>>>> @@ -770,6 +777,8 @@ void pci_bus_add_devices(const struct pci_bus *bus);
>>>>  struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
>>>>                                     struct pci_ops *ops, void *sysdata,
>>>>                                     struct list_head *resources);
>>>> +struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *host);
>>>> +void pci_free_host_bridge(struct pci_host_bridge *host);
>>>>  int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
>>>>  int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
>>>>  void pci_bus_release_busn_res(struct pci_bus *b);
>>>> --
>>>> 1.7.1
>>>>
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
>>>> the body of a message to majordomo@vger.kernel.org
>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>>
>>>
>>
>>
>> --
>> Thanks!
>> Yijing
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
> 


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 08/16] PCI: Introduce pci_scan_host_bridge() and pci_host_info
  2014-11-19 16:41       ` Liviu Dudau
@ 2014-11-20  2:54         ` Yijing Wang
  0 siblings, 0 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-20  2:54 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Bjorn Helgaas, linux-pci, linux-kernel, huxinwei, Wuyun,
	linux-arm-kernel, Russell King, x86, Thomas Gleixner,
	Benjamin Herrenschmidt, linuxppc-dev, Tony Luck, linux-ia64,
	Thierry Reding, Liviu Dudau, suravee.suthikulpanit, Yijing Wang

>> No, in this patch, host drivers pass a pci host bridge resources init hook
>> in pci_host_info *info, and we call this info->init_res() in pci_create_host_bridge().
>>
>> +struct pci_host_info {
>> +	u8 res_type;
>> +	void *arg;
>> +	struct list_head *resources; /*just for build, will clean up later */
>> +	int (*init_res)(struct pci_host_bridge *host,
>> +			struct pci_host_info *info);
>> +};
>> +
> 
> That's not what I've asked! Your code does:
> 
> 	if (info->res_type != PCI_HOST_RES_DEFAULT)
> 		....
> 	else /* info->res_type == PCI_HOST_RES_DEFAULT)
> 		info->res_type = PCI_HOST_RES_DEFAULT;
> 
> info->res_type is already == PCI_HOST_RES_DEFAULT in the else side, assignment is a NOP?

Hmmm, I wanted pci_create_host_bridge() to process the default res later(add default res),
It's ugly code, I will rework it.

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

OK

> 
> Best regards,
> Liviu
> 
>>
>>>
>>>> +
>>>> +#define PCI_HOST_RES_DEFAULT	0x2
>>>> +
>>>
>>> Magic number?
>>
>> Hmmm, I will rework pci host bridge resources stuff.
>>
>>>
>>> Best regards,
>>> Liviu
>>>
>>>>  #define	to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)
>>>>  void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
>>>>  		     void (*release_fn)(struct pci_host_bridge *),
>>>> @@ -420,7 +435,7 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
>>>>  int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
>>>>  struct pci_host_bridge *pci_create_host_bridge(
>>>>  		struct device *parent, u32 db, struct pci_ops *ops, 
>>>> -		void *sys, struct list_head *resources);
>>>> +		struct pci_host_info *info);
>>>>  /*
>>>>   * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
>>>>   * to P2P or CardBus bridge windows) go in a table.  Additional ones (for
>>>> @@ -785,6 +800,9 @@ void pci_bus_release_busn_res(struct pci_bus *b);
>>>>  struct pci_bus *pci_scan_root_bus(struct device *parent, u32 bus,
>>>>  					     struct pci_ops *ops, void *sysdata,
>>>>  					     struct list_head *resources);
>>>> +struct pci_host_bridge *pci_scan_host_bridge(struct device *parent,
>>>> +		u32 db, struct pci_ops *ops,
>>>> +		struct pci_host_info *info);
>>>>  struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
>>>>  				int busnr);
>>>>  void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);
>>>> -- 
>>>> 1.7.1
>>>>
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
>>>> the body of a message to majordomo@vger.kernel.org
>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>>
>>>
>>
>>
>> -- 
>> Thanks!
>> Yijing
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
> 


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
  2014-11-20  2:47         ` Yijing Wang
@ 2014-11-20  9:47           ` Liviu Dudau
  2014-11-21  2:53             ` Yijing Wang
  0 siblings, 1 reply; 65+ messages in thread
From: Liviu Dudau @ 2014-11-20  9:47 UTC (permalink / raw)
  To: Yijing Wang
  Cc: Bjorn Helgaas, linux-pci, linux-kernel, huxinwei, Wuyun,
	linux-arm-kernel, Russell King, x86, Thomas Gleixner,
	Benjamin Herrenschmidt, linuxppc-dev, Tony Luck, linux-ia64,
	Thierry Reding, Liviu Dudau, suravee.suthikulpanit

On Thu, Nov 20, 2014 at 02:47:35AM +0000, Yijing Wang wrote:
> >>>> +static void pci_release_host_bridge_dev(struct device *dev)
> >>>> +{
> >>>> +       struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
> >>>> +
> >>>> +       if (bridge->release_fn)
> >>>> +               bridge->release_fn(bridge);
> >>>> +       pci_free_resource_list(&bridge->windows);
> >>>> +       kfree(bridge);
> >>>> +}
> >>>> +
> >>>> +struct pci_host_bridge *pci_create_host_bridge(
> >>>> +               struct device *parent, u32 db,
> >>>> +               struct pci_ops *ops, void *sysdata,
> >>>
> >>> I don't thinks it is worth moving the buses' pci_ops into pci_host_bridge. It
> >>> might be more useful to have pci_host_bridge specific ops here.
> >>
> >> Because we want to create pci_host_bridge before pci root bus creation,
> >> so when we scan the root bus and child buses, we use pci_host_bridge as
> >> the only argument, and another pci_host_info will be addes in later patch,
> >> which one support carry the pci_host_bridge ops.
> >
> > But pci_create_root_bus() already has a pci_ops argument, I don't see the reason
> > to drop that.
> >
> > pci_create_host_bridge() can get pci_host_bridge ops while pci_create_root_bus() gets
> > the bus ops. For find out the MSI controller, the domain number and any other HB
> > specific stuff, you use the HB ops. For config R/W acceses you use bus ops.
> >
> 
> I want to unexport pci_create_root_bus() if we have pci_create_host_bridge().

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

Hope this makes sense.

> 
> 
> >>>> -struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
> >>>> -               struct pci_ops *ops, void *sysdata, struct list_head *resources)
> >>>> +struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *bridge)
> >>>>  {
> >>>>         int error;
> >>>> -       struct pci_host_bridge *bridge;
> >>>>         struct pci_bus *b, *b2;
> >>>> -       struct pci_host_bridge_window *window, *n;
> >>>> +       struct pci_host_bridge_window *window;
> >>>>         struct resource *res;
> >>>>         resource_size_t offset;
> >>>>         char bus_addr[64];
> >>>>         char *fmt;
> >>>> -       u8      bus = PCI_BUSNUM(db);
> >>>> +       struct device *parent = bridge->dev.parent;
> >>>>
> >>>>         b = pci_alloc_bus(NULL);
> >>>>         if (!b)
> >>>>                 return NULL;
> >>>>
> >>>> -       b->sysdata = sysdata;
> >>>> -       b->ops = ops;
> >>>> -       b->number = b->busn_res.start = bus;
> >>>> +       b->sysdata = bridge->sysdata;
> >>>
> >>> I think bridge should be the b->sysdata here.
> >>
> >> ? what's the meaning?
> >
> > Currently, bus->sysdata holds a pointer to the arch/driver host bridge structure, as passed
> > in pci_create_root_bus(). If you agree with my idea of wrapping the host bridge driver
> > structure around the pci_host_bridge, then we will always have a way of retrieving that
> > information; but for backwards compatibility we could set bus->sysdata to be the bridge.
> > Then existing macros that convert sysdata to pci_controller can be reused after being
> > updated.
> 
> I think wrapping the host bridge driver structure around the pci_host_bridge could help
> us to find the private pci_controller, but in this case, pci_host_bridge is not a pointer
> so we put all pci_host_bridge init stuff in host drivers ? 

Of course we put pci_host_bridge init *calls* in the host drivers because we need to do host
driver specific initialisation there anyway. 

> And if we still use arch spec
> macros convert ssydata to pci_controller, so what's the greatest advantage ?

Agree, the macro is not useful unless we have a common pci_controller structure. Sorry about
the noise.

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

I've never said we need to keep sysdata. From my discussion with Bjorn a year ago the idea was
to put the sysdata members into pci_host_bridge structure and remove sysdata member from pci_bus.
pci_scan_root_bus() can still get a parameter called sysdata if we want, but it will be a
struct pci_host_bridge * type.

Best regards,
Liviu

> 
> 
> 
> >
> > Best regards,
> > Liviu
> >
> >>
> >>>
> >>>> +       b->ops = bridge->ops;
> >>>
> >>> See comment above why I don't think this is necessary.
> >>>
> >>>> +       b->number = b->busn_res.start = bridge->busnum;
> >>>>         pci_bus_assign_domain_nr(b, parent);
> >>>> -       b2 = pci_find_bus(pci_domain_nr(b), bus);
> >>>> +       bridge->domain = pci_domain_nr(b);
> >>>
> >>> Do you really want to overwrite the bridge's domain with the one from a bus that
> >>> could possibly be rejected a couple of lines further down?
> >>>
> >>> As an asside: if we are doing the split of pci_host_bridge from root bus creation
> >>> it is worth in my opinion to move the domain setup in pci_create_host_bridge()
> >>> and stop fiddling with it here.
> >>
> >>
> >> Hi Liviu, these lines just temporary, I will remove it after all host drivers
> >> save its domain in pci_host_bridge.
> >>
> >>
> >>>
> >>> Otherwise it looks to me like you are heading in the right direction.
> >>
> >> Thanks!
> >> Yijing.
> >>
> >>>
> >>> Best regards,
> >>> Liviu
> >>>
> >>>> +       b2 = pci_find_bus(pci_domain_nr(b), bridge->busnum);
> >>>>         if (b2) {
> >>>>                 /* If we already got to this bus through a different bridge, ignore it */
> >>>>                 dev_dbg(&b2->dev, "bus already known\n");
> >>>>                 goto err_out;
> >>>>         }
> >>>>
> >>>> -       bridge = pci_alloc_host_bridge(b);
> >>>> -       if (!bridge)
> >>>> -               goto err_out;
> >>>> -
> >>>> -       bridge->dev.parent = parent;
> >>>> -       bridge->dev.release = pci_release_host_bridge_dev;
> >>>> -       dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
> >>>> -       error = pcibios_root_bridge_prepare(bridge);
> >>>> -       if (error) {
> >>>> -               kfree(bridge);
> >>>> -               goto err_out;
> >>>> -       }
> >>>> -
> >>>> -       error = device_register(&bridge->dev);
> >>>> -       if (error) {
> >>>> -               put_device(&bridge->dev);
> >>>> -               goto err_out;
> >>>> -       }
> >>>>         b->bridge = get_device(&bridge->dev);
> >>>>         device_enable_async_suspend(b->bridge);
> >>>>         pci_set_bus_of_node(b);
> >>>> @@ -1950,7 +1899,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
> >>>>
> >>>>         b->dev.class = &pcibus_class;
> >>>>         b->dev.parent = b->bridge;
> >>>> -       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
> >>>> +       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), b->number);
> >>>>         error = device_register(&b->dev);
> >>>>         if (error)
> >>>>                 goto class_dev_reg_err;
> >>>> @@ -1966,12 +1915,11 @@ struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
> >>>>                 printk(KERN_INFO "PCI host bridge to bus %s\n", dev_name(&b->dev));
> >>>>
> >>>>         /* Add initial resources to the bus */
> >>>> -       list_for_each_entry_safe(window, n, resources, list) {
> >>>> -               list_move_tail(&window->list, &bridge->windows);
> >>>> +       list_for_each_entry(window, &bridge->windows, list) {
> >>>>                 res = window->res;
> >>>>                 offset = window->offset;
> >>>>                 if (res->flags & IORESOURCE_BUS)
> >>>> -                       pci_bus_insert_busn_res(b, bus, res->end);
> >>>> +                       pci_bus_insert_busn_res(b, b->number, res->end);
> >>>>                 else
> >>>>                         pci_bus_add_resource(b, res, 0);
> >>>>                 if (offset) {
> >>>> @@ -2001,6 +1949,25 @@ err_out:
> >>>>         return NULL;
> >>>>  }
> >>>>
> >>>> +struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
> >>>> +               struct pci_ops *ops, void *sysdata, struct list_head *resources)
> >>>> +{
> >>>> +       struct pci_host_bridge *host;
> >>>> +
> >>>> +       host = pci_create_host_bridge(parent, bus, ops,
> >>>> +                       sysdata ,resources);
> >>>> +       if (!host)
> >>>> +               return NULL;
> >>>> +
> >>>> +       host->bus = __pci_create_root_bus(host);
> >>>> +       if (!host->bus) {
> >>>> +               pci_free_host_bridge(host);
> >>>> +               return NULL;
> >>>> +       }
> >>>> +
> >>>> +       return host->bus;
> >>>> +}
> >>>> +
> >>>>  int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
> >>>>  {
> >>>>         struct resource *res = &b->busn_res;
> >>>> @@ -2069,40 +2036,37 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
> >>>>  {
> >>>>         struct pci_host_bridge_window *window;
> >>>>         bool found = false;
> >>>> -       struct pci_bus *b;
> >>>> -       LIST_HEAD(default_res);
> >>>> +       struct pci_host_bridge *host;
> >>>>         int max;
> >>>>
> >>>> -       if (!resources) {
> >>>> -               pci_add_resource(&default_res, &ioport_resource);
> >>>> -               pci_add_resource(&default_res, &iomem_resource);
> >>>> -               pci_add_resource(&default_res, &busn_resource);
> >>>> -       } else {
> >>>> -               list_for_each_entry(window, resources, list)
> >>>> -                       if (window->res->flags & IORESOURCE_BUS) {
> >>>> -                               found = true;
> >>>> -                               break;
> >>>> -                       }
> >>>> -       }
> >>>> +       host = pci_create_host_bridge(parent, db, ops, sysdata, resources);
> >>>> +       if (!host)
> >>>> +               return NULL;
> >>>>
> >>>> -       b = pci_create_root_bus(parent, db, ops, sysdata,
> >>>> -                       resources ? resources : &default_res);
> >>>> -       if (!b)
> >>>> +       list_for_each_entry(window, &host->windows, list)
> >>>> +               if (window->res->flags & IORESOURCE_BUS) {
> >>>> +                       found = true;
> >>>> +                       break;
> >>>> +               }
> >>>> +
> >>>> +       host->bus = __pci_create_root_bus(host);
> >>>> +       if (!host->bus) {
> >>>> +               pci_free_host_bridge(host);
> >>>>                 return NULL;
> >>>> +       }
> >>>>
> >>>>         if (!found) {
> >>>> -               dev_info(&b->dev,
> >>>> +               dev_info(&host->bus->dev,
> >>>>                  "No busn resource found for root bus, will use [bus %02x-ff]\n",
> >>>>                         PCI_BUSNUM(db));
> >>>> -               pci_bus_insert_busn_res(b, PCI_BUSNUM(db), 255);
> >>>> +               pci_bus_insert_busn_res(host->bus, PCI_BUSNUM(db), 255);
> >>>>         }
> >>>>
> >>>> -       max = pci_scan_child_bus(b);
> >>>> -
> >>>> +       max = pci_scan_child_bus(host->bus);
> >>>>         if (!found)
> >>>> -               pci_bus_update_busn_res_end(b, max);
> >>>> +               pci_bus_update_busn_res_end(host->bus, max);
> >>>>
> >>>> -       return b;
> >>>> +       return host->bus;
> >>>>  }
> >>>>  EXPORT_SYMBOL(pci_scan_root_bus);
> >>>>
> >>>> diff --git a/include/linux/pci.h b/include/linux/pci.h
> >>>> index 8b11b38..daa7f40 100644
> >>>> --- a/include/linux/pci.h
> >>>> +++ b/include/linux/pci.h
> >>>> @@ -402,7 +402,12 @@ struct pci_host_bridge_window {
> >>>>  struct pci_host_bridge {
> >>>>         struct device dev;
> >>>>         struct pci_bus *bus;            /* root bus */
> >>>> +       struct list_head list;
> >>>>         struct list_head windows;       /* pci_host_bridge_windows */
> >>>> +       int busnum;
> >>>> +       int domain;
> >>>> +       void *sysdata;
> >>>> +       struct pci_ops *ops;
> >>>>         void (*release_fn)(struct pci_host_bridge *);
> >>>>         void *release_data;
> >>>>  };
> >>>> @@ -413,7 +418,9 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
> >>>>                      void *release_data);
> >>>>
> >>>>  int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
> >>>> -
> >>>> +struct pci_host_bridge *pci_create_host_bridge(
> >>>> +               struct device *parent, u32 db, struct pci_ops *ops,
> >>>> +               void *sys, struct list_head *resources);
> >>>>  /*
> >>>>   * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
> >>>>   * to P2P or CardBus bridge windows) go in a table.  Additional ones (for
> >>>> @@ -770,6 +777,8 @@ void pci_bus_add_devices(const struct pci_bus *bus);
> >>>>  struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
> >>>>                                     struct pci_ops *ops, void *sysdata,
> >>>>                                     struct list_head *resources);
> >>>> +struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *host);
> >>>> +void pci_free_host_bridge(struct pci_host_bridge *host);
> >>>>  int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
> >>>>  int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
> >>>>  void pci_bus_release_busn_res(struct pci_bus *b);
> >>>> --
> >>>> 1.7.1
> >>>>
> >>>> --
> >>>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> >>>> the body of a message to majordomo@vger.kernel.org
> >>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >>>>
> >>>
> >>
> >>
> >> --
> >> Thanks!
> >> Yijing
> >>
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> >> the body of a message to majordomo@vger.kernel.org
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >>
> >
> 
> 
> --
> Thanks!
> Yijing
> 
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯


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

* Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces
  2014-11-17 14:13 ` [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Arnd Bergmann
  2014-11-18 11:17   ` Yijing Wang
@ 2014-11-20 11:54   ` Tomasz Nowicki
  2014-11-20 12:08     ` Liviu Dudau
  1 sibling, 1 reply; 65+ messages in thread
From: Tomasz Nowicki @ 2014-11-20 11:54 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Bjorn Helgaas, Thierry Reding,
	Suravee.Suthikulpanit, Benjamin Herrenschmidt, Yijing Wang,
	linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev

On 17.11.2014 15:13, Arnd Bergmann wrote:
> 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.

How about finding PCI domain number (in the DT way) within 
pci_create_host_bridge() too ?

Tomasz

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

* Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces
  2014-11-18 12:27         ` Arnd Bergmann
@ 2014-11-20 12:01           ` Tomasz Nowicki
  2014-11-20 13:15             ` Arnd Bergmann
  0 siblings, 1 reply; 65+ messages in thread
From: Tomasz Nowicki @ 2014-11-20 12:01 UTC (permalink / raw)
  To: Arnd Bergmann, Yijing Wang
  Cc: Liviu Dudau, Tony Luck, Russell King, linux-pci, x86,
	linux-kernel, Xinwei Hu, Thierry Reding, Suravee.Suthikulpanit,
	Benjamin Herrenschmidt, Bjorn Helgaas, linux-ia64,
	Thomas Gleixner, Wuyun, linuxppc-dev, linux-arm-kernel

On 18.11.2014 13:27, Arnd Bergmann wrote:
> On Tuesday 18 November 2014 20:17:57 Yijing Wang wrote:
>>
>>>>
>>>> I hope platforms with ACPI or DT could both use pci_create_host_bridge().
>>>> Why we need to use two different ways to process it ?
>>>
>>> These are completely different use cases:
>>>
>>> a) For DT, we want loadable device drivers that start by probing a host
>>>     bridge device which was added through the DT platform code. The
>>>     driver is self-contained, and eventually we want to be able to unload
>>>     it. We have lots of different per-soc drivers that require different
>>>     quirks
>>>
>>> b) For ACPI, the interface is defined in the ACPI spec across architectures
>>>     and SoCs, we don't have host bridge drivers and the code that initializes
>>>     the PCI is required early during boot and called from architecture
>>>     code. There is no parent device, as ACPI sees PCI as a fundamental building
>>>     block by itself, and there are no drivers because the firmware does
>>>     the initial hardware setup, so we only have to access the config space.
>>
>> Hmmm, I'm a little confused, so why you think ACPI host driver should not use
>> pci_create_host_bridge(), because ACPI PCI driver has no parent device ?
>
> It's one of the difference. Having a parent device can certainly make your
> life simpler, since you have devm_kzalloc(), dev_info(), etc. Coming from
> the other end, I think ACPI needs PCI to be available during early boot,
> at a time where we might not want pci_create_host_bridge() to do the
> right thing.

Device pointer is not required for ACPI, struct acpi_device is all we 
need to get all that info. If pci_create_host_bridge() would be DT 
specific, it would be nice to have sth similar for ACPI but that is out 
of this patch set scope.

Tomasz

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

* Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces
  2014-11-20 11:54   ` Tomasz Nowicki
@ 2014-11-20 12:08     ` Liviu Dudau
  2014-11-20 12:53       ` Tomasz Nowicki
  0 siblings, 1 reply; 65+ messages in thread
From: Liviu Dudau @ 2014-11-20 12:08 UTC (permalink / raw)
  To: Tomasz Nowicki
  Cc: Arnd Bergmann, linux-arm-kernel, Tony Luck, Russell King,
	linux-pci, x86, linux-kernel, Xinwei Hu, Bjorn Helgaas,
	Thierry Reding, Suravee.Suthikulpanit, Benjamin Herrenschmidt,
	Yijing Wang, linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev

On Thu, Nov 20, 2014 at 12:54:48PM +0100, Tomasz Nowicki wrote:
> On 17.11.2014 15:13, Arnd Bergmann wrote:
> >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.
> 
> How about finding PCI domain number (in the DT way) within
> pci_create_host_bridge() too ?

It is an idea worth pursuing for the 99% of the cases. I would like
to understand the 1% of the time when we want a domain number to be
shared between two host bridges or the time when we want more than
one domain per bridge.

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

Best regards,
Liviu

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

-- 
-------------------
   .oooO
   (   )
    \ (  Oooo.
     \_) (   )
          ) /
         (_/

 One small step
   for me ...


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

* Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces
  2014-11-20 12:08     ` Liviu Dudau
@ 2014-11-20 12:53       ` Tomasz Nowicki
  2014-11-20 16:39         ` Liviu Dudau
  0 siblings, 1 reply; 65+ messages in thread
From: Tomasz Nowicki @ 2014-11-20 12:53 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Arnd Bergmann, linux-arm-kernel, Tony Luck, Russell King,
	linux-pci, x86, linux-kernel, Xinwei Hu, Bjorn Helgaas,
	Thierry Reding, Suravee.Suthikulpanit, Benjamin Herrenschmidt,
	Yijing Wang, linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev

On 20.11.2014 13:08, Liviu Dudau wrote:
> On Thu, Nov 20, 2014 at 12:54:48PM +0100, Tomasz Nowicki wrote:
>> On 17.11.2014 15:13, Arnd Bergmann wrote:
>>> 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.
>>
>> How about finding PCI domain number (in the DT way) within
>> pci_create_host_bridge() too ?
>
> It is an idea worth pursuing for the 99% of the cases. I would like
> to understand the 1% of the time when we want a domain number to be
> shared between two host bridges or the time when we want more than
> one domain per bridge.
Even though we have shared domain, this should be resolved via DT calls, 
do I miss something ?

>
> Is that possible? Is it useful? Is it already in practice?
This is good question... IMO:
1. Two host bridges can shared domain number if they are children of the 
same parent host bridge.
2. But I can not find good explanation for more than one domain per bridge.

Tomasz


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

* Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces
  2014-11-20 12:01           ` Tomasz Nowicki
@ 2014-11-20 13:15             ` Arnd Bergmann
  0 siblings, 0 replies; 65+ messages in thread
From: Arnd Bergmann @ 2014-11-20 13:15 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Tomasz Nowicki, Yijing Wang, Liviu Dudau, Tony Luck,
	Russell King, linux-pci, x86, linux-kernel, Xinwei Hu,
	Thierry Reding, Suravee.Suthikulpanit, Bjorn Helgaas, linux-ia64,
	Thomas Gleixner, Wuyun, linux-arm-kernel

On Thursday 20 November 2014 13:01:08 Tomasz Nowicki wrote:
> On 18.11.2014 13:27, Arnd Bergmann wrote:
> > On Tuesday 18 November 2014 20:17:57 Yijing Wang wrote:
> >>
> >>>>
> >>>> I hope platforms with ACPI or DT could both use pci_create_host_bridge().
> >>>> Why we need to use two different ways to process it ?
> >>>
> >>> These are completely different use cases:
> >>>
> >>> a) For DT, we want loadable device drivers that start by probing a host
> >>>     bridge device which was added through the DT platform code. The
> >>>     driver is self-contained, and eventually we want to be able to unload
> >>>     it. We have lots of different per-soc drivers that require different
> >>>     quirks
> >>>
> >>> b) For ACPI, the interface is defined in the ACPI spec across architectures
> >>>     and SoCs, we don't have host bridge drivers and the code that initializes
> >>>     the PCI is required early during boot and called from architecture
> >>>     code. There is no parent device, as ACPI sees PCI as a fundamental building
> >>>     block by itself, and there are no drivers because the firmware does
> >>>     the initial hardware setup, so we only have to access the config space.
> >>
> >> Hmmm, I'm a little confused, so why you think ACPI host driver should not use
> >> pci_create_host_bridge(), because ACPI PCI driver has no parent device ?
> >
> > It's one of the difference. Having a parent device can certainly make your
> > life simpler, since you have devm_kzalloc(), dev_info(), etc. Coming from
> > the other end, I think ACPI needs PCI to be available during early boot,
> > at a time where we might not want pci_create_host_bridge() to do the
> > right thing.
> 
> Device pointer is not required for ACPI, struct acpi_device is all we 
> need to get all that info. If pci_create_host_bridge() would be DT 
> specific, it would be nice to have sth similar for ACPI but that is out 
> of this patch set scope.

My point was more that we don't need to have something like it for ACPI,
since we don't get random drivers that need to be probed that way,
just one common implementation that calls into the PCI core. We should
of course share the common bits with pci_create_host_bridge() in some
form, but that can be done by moving the x86 pci_acpi_scan_root
function and/or acpi_pci_root_add() to a common place in drivers/pci
and then refactoring the internals.

	Arnd

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

* Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces
  2014-11-20 12:53       ` Tomasz Nowicki
@ 2014-11-20 16:39         ` Liviu Dudau
  2014-11-21  2:58           ` Yijing Wang
  0 siblings, 1 reply; 65+ messages in thread
From: Liviu Dudau @ 2014-11-20 16:39 UTC (permalink / raw)
  To: Tomasz Nowicki
  Cc: Arnd Bergmann, linux-arm-kernel, Tony Luck, Russell King,
	linux-pci, x86, linux-kernel, Xinwei Hu, Bjorn Helgaas,
	Thierry Reding, Suravee.Suthikulpanit, Benjamin Herrenschmidt,
	Yijing Wang, linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev

On Thu, Nov 20, 2014 at 01:53:48PM +0100, Tomasz Nowicki wrote:
> On 20.11.2014 13:08, Liviu Dudau wrote:
> >On Thu, Nov 20, 2014 at 12:54:48PM +0100, Tomasz Nowicki wrote:
> >>On 17.11.2014 15:13, Arnd Bergmann wrote:
> >>>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.
> >>
> >>How about finding PCI domain number (in the DT way) within
> >>pci_create_host_bridge() too ?
> >
> >It is an idea worth pursuing for the 99% of the cases. I would like
> >to understand the 1% of the time when we want a domain number to be
> >shared between two host bridges or the time when we want more than
> >one domain per bridge.
> Even though we have shared domain, this should be resolved via DT calls, do
> I miss something ?

If we only going to hold one domain number per host bridge, then no, you're
not missing anything.

> 
> >
> >Is that possible? Is it useful? Is it already in practice?
> This is good question... IMO:
> 1. Two host bridges can shared domain number if they are children of the
> same parent host bridge.
> 2. But I can not find good explanation for more than one domain per bridge.

Splitting a root bus into two or more "segments" ?

Best regards,
Liviu

> 
> Tomasz
> 
> 

-- 
-------------------
   .oooO
   (   )
    \ (  Oooo.
     \_) (   )
          ) /
         (_/

 One small step
   for me ...


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

* Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
  2014-11-20  9:47           ` Liviu Dudau
@ 2014-11-21  2:53             ` Yijing Wang
  2014-11-21  9:53               ` Liviu Dudau
  0 siblings, 1 reply; 65+ messages in thread
From: Yijing Wang @ 2014-11-21  2:53 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Bjorn Helgaas, linux-pci, linux-kernel, huxinwei, Wuyun,
	linux-arm-kernel, Russell King, x86, Thomas Gleixner,
	Benjamin Herrenschmidt, linuxppc-dev, Tony Luck, linux-ia64,
	Thierry Reding, Liviu Dudau, suravee.suthikulpanit

>>> pci_create_host_bridge() can get pci_host_bridge ops while pci_create_root_bus() gets
>>> the bus ops. For find out the MSI controller, the domain number and any other HB
>>> specific stuff, you use the HB ops. For config R/W acceses you use bus ops.
>>>
>>
>> I want to unexport pci_create_root_bus() if we have pci_create_host_bridge().
> 
> That's fine, but the function signature doesn't change, right? And I think we should keep
> pci_scan_root_bus() with the current signature as well (except change sysdata into a
> struct pci_host_bridge *). We create the host bridge in one step, stuff it with all the
> data that we need for scanning the root and associated busses, and then call pci_scan_root_bus().
> pci_host_bridge has the ops from pci_create_host_bridge() and the root bus from pci_scan_root_bus().

Liviu, could you have some draft patches about replace sysdata with pci_host_bridge, so we could
discuss the details base it. :)

> 
> Hope this makes sense.
> 
>>
>>
>>>>>> -struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
>>>>>> -               struct pci_ops *ops, void *sysdata, struct list_head *resources)
>>>>>> +struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *bridge)
>>>>>>  {
>>>>>>         int error;
>>>>>> -       struct pci_host_bridge *bridge;
>>>>>>         struct pci_bus *b, *b2;
>>>>>> -       struct pci_host_bridge_window *window, *n;
>>>>>> +       struct pci_host_bridge_window *window;
>>>>>>         struct resource *res;
>>>>>>         resource_size_t offset;
>>>>>>         char bus_addr[64];
>>>>>>         char *fmt;
>>>>>> -       u8      bus = PCI_BUSNUM(db);
>>>>>> +       struct device *parent = bridge->dev.parent;
>>>>>>
>>>>>>         b = pci_alloc_bus(NULL);
>>>>>>         if (!b)
>>>>>>                 return NULL;
>>>>>>
>>>>>> -       b->sysdata = sysdata;
>>>>>> -       b->ops = ops;
>>>>>> -       b->number = b->busn_res.start = bus;
>>>>>> +       b->sysdata = bridge->sysdata;
>>>>>
>>>>> I think bridge should be the b->sysdata here.
>>>>
>>>> ? what's the meaning?
>>>
>>> Currently, bus->sysdata holds a pointer to the arch/driver host bridge structure, as passed
>>> in pci_create_root_bus(). If you agree with my idea of wrapping the host bridge driver
>>> structure around the pci_host_bridge, then we will always have a way of retrieving that
>>> information; but for backwards compatibility we could set bus->sysdata to be the bridge.
>>> Then existing macros that convert sysdata to pci_controller can be reused after being
>>> updated.
>>
>> I think wrapping the host bridge driver structure around the pci_host_bridge could help
>> us to find the private pci_controller, but in this case, pci_host_bridge is not a pointer
>> so we put all pci_host_bridge init stuff in host drivers ? 
> 
> Of course we put pci_host_bridge init *calls* in the host drivers because we need to do host
> driver specific initialisation there anyway. 
> 
>> And if we still use arch spec
>> macros convert ssydata to pci_controller, so what's the greatest advantage ?
> 
> Agree, the macro is not useful unless we have a common pci_controller structure. Sorry about
> the noise.
> 
>>
>> If we move domain and msi_chip out of sysdata, what's other things in sysdata still need us
>> to convert in PCI core ?
> 
> I've never said we need to keep sysdata. From my discussion with Bjorn a year ago the idea was
> to put the sysdata members into pci_host_bridge structure and remove sysdata member from pci_bus.
> pci_scan_root_bus() can still get a parameter called sysdata if we want, but it will be a
> struct pci_host_bridge * type.

Fine.

> 
> Best regards,
> Liviu
> 
>>
>>
>>
>>>
>>> Best regards,
>>> Liviu
>>>
>>>>
>>>>>
>>>>>> +       b->ops = bridge->ops;
>>>>>
>>>>> See comment above why I don't think this is necessary.
>>>>>
>>>>>> +       b->number = b->busn_res.start = bridge->busnum;
>>>>>>         pci_bus_assign_domain_nr(b, parent);
>>>>>> -       b2 = pci_find_bus(pci_domain_nr(b), bus);
>>>>>> +       bridge->domain = pci_domain_nr(b);
>>>>>
>>>>> Do you really want to overwrite the bridge's domain with the one from a bus that
>>>>> could possibly be rejected a couple of lines further down?
>>>>>
>>>>> As an asside: if we are doing the split of pci_host_bridge from root bus creation
>>>>> it is worth in my opinion to move the domain setup in pci_create_host_bridge()
>>>>> and stop fiddling with it here.
>>>>
>>>>
>>>> Hi Liviu, these lines just temporary, I will remove it after all host drivers
>>>> save its domain in pci_host_bridge.
>>>>
>>>>
>>>>>
>>>>> Otherwise it looks to me like you are heading in the right direction.
>>>>
>>>> Thanks!
>>>> Yijing.
>>>>
>>>>>
>>>>> Best regards,
>>>>> Liviu
>>>>>
>>>>>> +       b2 = pci_find_bus(pci_domain_nr(b), bridge->busnum);
>>>>>>         if (b2) {
>>>>>>                 /* If we already got to this bus through a different bridge, ignore it */
>>>>>>                 dev_dbg(&b2->dev, "bus already known\n");
>>>>>>                 goto err_out;
>>>>>>         }
>>>>>>
>>>>>> -       bridge = pci_alloc_host_bridge(b);
>>>>>> -       if (!bridge)
>>>>>> -               goto err_out;
>>>>>> -
>>>>>> -       bridge->dev.parent = parent;
>>>>>> -       bridge->dev.release = pci_release_host_bridge_dev;
>>>>>> -       dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
>>>>>> -       error = pcibios_root_bridge_prepare(bridge);
>>>>>> -       if (error) {
>>>>>> -               kfree(bridge);
>>>>>> -               goto err_out;
>>>>>> -       }
>>>>>> -
>>>>>> -       error = device_register(&bridge->dev);
>>>>>> -       if (error) {
>>>>>> -               put_device(&bridge->dev);
>>>>>> -               goto err_out;
>>>>>> -       }
>>>>>>         b->bridge = get_device(&bridge->dev);
>>>>>>         device_enable_async_suspend(b->bridge);
>>>>>>         pci_set_bus_of_node(b);
>>>>>> @@ -1950,7 +1899,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
>>>>>>
>>>>>>         b->dev.class = &pcibus_class;
>>>>>>         b->dev.parent = b->bridge;
>>>>>> -       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
>>>>>> +       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), b->number);
>>>>>>         error = device_register(&b->dev);
>>>>>>         if (error)
>>>>>>                 goto class_dev_reg_err;
>>>>>> @@ -1966,12 +1915,11 @@ struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
>>>>>>                 printk(KERN_INFO "PCI host bridge to bus %s\n", dev_name(&b->dev));
>>>>>>
>>>>>>         /* Add initial resources to the bus */
>>>>>> -       list_for_each_entry_safe(window, n, resources, list) {
>>>>>> -               list_move_tail(&window->list, &bridge->windows);
>>>>>> +       list_for_each_entry(window, &bridge->windows, list) {
>>>>>>                 res = window->res;
>>>>>>                 offset = window->offset;
>>>>>>                 if (res->flags & IORESOURCE_BUS)
>>>>>> -                       pci_bus_insert_busn_res(b, bus, res->end);
>>>>>> +                       pci_bus_insert_busn_res(b, b->number, res->end);
>>>>>>                 else
>>>>>>                         pci_bus_add_resource(b, res, 0);
>>>>>>                 if (offset) {
>>>>>> @@ -2001,6 +1949,25 @@ err_out:
>>>>>>         return NULL;
>>>>>>  }
>>>>>>
>>>>>> +struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
>>>>>> +               struct pci_ops *ops, void *sysdata, struct list_head *resources)
>>>>>> +{
>>>>>> +       struct pci_host_bridge *host;
>>>>>> +
>>>>>> +       host = pci_create_host_bridge(parent, bus, ops,
>>>>>> +                       sysdata ,resources);
>>>>>> +       if (!host)
>>>>>> +               return NULL;
>>>>>> +
>>>>>> +       host->bus = __pci_create_root_bus(host);
>>>>>> +       if (!host->bus) {
>>>>>> +               pci_free_host_bridge(host);
>>>>>> +               return NULL;
>>>>>> +       }
>>>>>> +
>>>>>> +       return host->bus;
>>>>>> +}
>>>>>> +
>>>>>>  int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
>>>>>>  {
>>>>>>         struct resource *res = &b->busn_res;
>>>>>> @@ -2069,40 +2036,37 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
>>>>>>  {
>>>>>>         struct pci_host_bridge_window *window;
>>>>>>         bool found = false;
>>>>>> -       struct pci_bus *b;
>>>>>> -       LIST_HEAD(default_res);
>>>>>> +       struct pci_host_bridge *host;
>>>>>>         int max;
>>>>>>
>>>>>> -       if (!resources) {
>>>>>> -               pci_add_resource(&default_res, &ioport_resource);
>>>>>> -               pci_add_resource(&default_res, &iomem_resource);
>>>>>> -               pci_add_resource(&default_res, &busn_resource);
>>>>>> -       } else {
>>>>>> -               list_for_each_entry(window, resources, list)
>>>>>> -                       if (window->res->flags & IORESOURCE_BUS) {
>>>>>> -                               found = true;
>>>>>> -                               break;
>>>>>> -                       }
>>>>>> -       }
>>>>>> +       host = pci_create_host_bridge(parent, db, ops, sysdata, resources);
>>>>>> +       if (!host)
>>>>>> +               return NULL;
>>>>>>
>>>>>> -       b = pci_create_root_bus(parent, db, ops, sysdata,
>>>>>> -                       resources ? resources : &default_res);
>>>>>> -       if (!b)
>>>>>> +       list_for_each_entry(window, &host->windows, list)
>>>>>> +               if (window->res->flags & IORESOURCE_BUS) {
>>>>>> +                       found = true;
>>>>>> +                       break;
>>>>>> +               }
>>>>>> +
>>>>>> +       host->bus = __pci_create_root_bus(host);
>>>>>> +       if (!host->bus) {
>>>>>> +               pci_free_host_bridge(host);
>>>>>>                 return NULL;
>>>>>> +       }
>>>>>>
>>>>>>         if (!found) {
>>>>>> -               dev_info(&b->dev,
>>>>>> +               dev_info(&host->bus->dev,
>>>>>>                  "No busn resource found for root bus, will use [bus %02x-ff]\n",
>>>>>>                         PCI_BUSNUM(db));
>>>>>> -               pci_bus_insert_busn_res(b, PCI_BUSNUM(db), 255);
>>>>>> +               pci_bus_insert_busn_res(host->bus, PCI_BUSNUM(db), 255);
>>>>>>         }
>>>>>>
>>>>>> -       max = pci_scan_child_bus(b);
>>>>>> -
>>>>>> +       max = pci_scan_child_bus(host->bus);
>>>>>>         if (!found)
>>>>>> -               pci_bus_update_busn_res_end(b, max);
>>>>>> +               pci_bus_update_busn_res_end(host->bus, max);
>>>>>>
>>>>>> -       return b;
>>>>>> +       return host->bus;
>>>>>>  }
>>>>>>  EXPORT_SYMBOL(pci_scan_root_bus);
>>>>>>
>>>>>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>>>>>> index 8b11b38..daa7f40 100644
>>>>>> --- a/include/linux/pci.h
>>>>>> +++ b/include/linux/pci.h
>>>>>> @@ -402,7 +402,12 @@ struct pci_host_bridge_window {
>>>>>>  struct pci_host_bridge {
>>>>>>         struct device dev;
>>>>>>         struct pci_bus *bus;            /* root bus */
>>>>>> +       struct list_head list;
>>>>>>         struct list_head windows;       /* pci_host_bridge_windows */
>>>>>> +       int busnum;
>>>>>> +       int domain;
>>>>>> +       void *sysdata;
>>>>>> +       struct pci_ops *ops;
>>>>>>         void (*release_fn)(struct pci_host_bridge *);
>>>>>>         void *release_data;
>>>>>>  };
>>>>>> @@ -413,7 +418,9 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
>>>>>>                      void *release_data);
>>>>>>
>>>>>>  int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
>>>>>> -
>>>>>> +struct pci_host_bridge *pci_create_host_bridge(
>>>>>> +               struct device *parent, u32 db, struct pci_ops *ops,
>>>>>> +               void *sys, struct list_head *resources);
>>>>>>  /*
>>>>>>   * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
>>>>>>   * to P2P or CardBus bridge windows) go in a table.  Additional ones (for
>>>>>> @@ -770,6 +777,8 @@ void pci_bus_add_devices(const struct pci_bus *bus);
>>>>>>  struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
>>>>>>                                     struct pci_ops *ops, void *sysdata,
>>>>>>                                     struct list_head *resources);
>>>>>> +struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *host);
>>>>>> +void pci_free_host_bridge(struct pci_host_bridge *host);
>>>>>>  int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
>>>>>>  int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
>>>>>>  void pci_bus_release_busn_res(struct pci_bus *b);
>>>>>> --
>>>>>> 1.7.1
>>>>>>
>>>>>> --
>>>>>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
>>>>>> the body of a message to majordomo@vger.kernel.org
>>>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>>>>
>>>>>
>>>>
>>>>
>>>> --
>>>> Thanks!
>>>> Yijing
>>>>
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
>>>> the body of a message to majordomo@vger.kernel.org
>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>>
>>>
>>
>>
>> --
>> Thanks!
>> Yijing
>>
>>
> 


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 00/16] Refine PCI host bridge scan interfaces
  2014-11-20 16:39         ` Liviu Dudau
@ 2014-11-21  2:58           ` Yijing Wang
  0 siblings, 0 replies; 65+ messages in thread
From: Yijing Wang @ 2014-11-21  2:58 UTC (permalink / raw)
  To: Liviu Dudau, Tomasz Nowicki
  Cc: Arnd Bergmann, linux-arm-kernel, Tony Luck, Russell King,
	linux-pci, x86, linux-kernel, Xinwei Hu, Bjorn Helgaas,
	Thierry Reding, Suravee.Suthikulpanit, Benjamin Herrenschmidt,
	linux-ia64, Thomas Gleixner, Wuyun, linuxppc-dev

On 2014/11/21 0:39, Liviu Dudau wrote:
> On Thu, Nov 20, 2014 at 01:53:48PM +0100, Tomasz Nowicki wrote:
>> On 20.11.2014 13:08, Liviu Dudau wrote:
>>> On Thu, Nov 20, 2014 at 12:54:48PM +0100, Tomasz Nowicki wrote:
>>>> On 17.11.2014 15:13, Arnd Bergmann wrote:
>>>>> 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.
>>>>
>>>> How about finding PCI domain number (in the DT way) within
>>>> pci_create_host_bridge() too ?
>>>
>>> It is an idea worth pursuing for the 99% of the cases. I would like
>>> to understand the 1% of the time when we want a domain number to be
>>> shared between two host bridges or the time when we want more than
>>> one domain per bridge.
>> Even though we have shared domain, this should be resolved via DT calls, do
>> I miss something ?
> 
> If we only going to hold one domain number per host bridge, then no, you're
> not missing anything.
> 
>>
>>>
>>> Is that possible? Is it useful? Is it already in practice?
>> This is good question... IMO:
>> 1. Two host bridges can shared domain number if they are children of the
>> same parent host bridge.
>> 2. But I can not find good explanation for more than one domain per bridge.
> 
> Splitting a root bus into two or more "segments" ?

It seems impossible.

> 
> Best regards,
> Liviu
> 
>>
>> Tomasz
>>
>>
> 


-- 
Thanks!
Yijing


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

* Re: [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus()
  2014-11-21  2:53             ` Yijing Wang
@ 2014-11-21  9:53               ` Liviu Dudau
  0 siblings, 0 replies; 65+ messages in thread
From: Liviu Dudau @ 2014-11-21  9:53 UTC (permalink / raw)
  To: Yijing Wang
  Cc: Bjorn Helgaas, linux-pci, linux-kernel, huxinwei, Wuyun,
	linux-arm-kernel, Russell King, x86, Thomas Gleixner,
	Benjamin Herrenschmidt, linuxppc-dev, Tony Luck, linux-ia64,
	Thierry Reding, Liviu Dudau, suravee.suthikulpanit

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

Sure, I'll try to send something soon.

Best regards,
Liviu

> 
> >
> > Hope this makes sense.
> >
> >>
> >>
> >>>>>> -struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
> >>>>>> -               struct pci_ops *ops, void *sysdata, struct list_head *resources)
> >>>>>> +struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *bridge)
> >>>>>>  {
> >>>>>>         int error;
> >>>>>> -       struct pci_host_bridge *bridge;
> >>>>>>         struct pci_bus *b, *b2;
> >>>>>> -       struct pci_host_bridge_window *window, *n;
> >>>>>> +       struct pci_host_bridge_window *window;
> >>>>>>         struct resource *res;
> >>>>>>         resource_size_t offset;
> >>>>>>         char bus_addr[64];
> >>>>>>         char *fmt;
> >>>>>> -       u8      bus = PCI_BUSNUM(db);
> >>>>>> +       struct device *parent = bridge->dev.parent;
> >>>>>>
> >>>>>>         b = pci_alloc_bus(NULL);
> >>>>>>         if (!b)
> >>>>>>                 return NULL;
> >>>>>>
> >>>>>> -       b->sysdata = sysdata;
> >>>>>> -       b->ops = ops;
> >>>>>> -       b->number = b->busn_res.start = bus;
> >>>>>> +       b->sysdata = bridge->sysdata;
> >>>>>
> >>>>> I think bridge should be the b->sysdata here.
> >>>>
> >>>> ? what's the meaning?
> >>>
> >>> Currently, bus->sysdata holds a pointer to the arch/driver host bridge structure, as passed
> >>> in pci_create_root_bus(). If you agree with my idea of wrapping the host bridge driver
> >>> structure around the pci_host_bridge, then we will always have a way of retrieving that
> >>> information; but for backwards compatibility we could set bus->sysdata to be the bridge.
> >>> Then existing macros that convert sysdata to pci_controller can be reused after being
> >>> updated.
> >>
> >> I think wrapping the host bridge driver structure around the pci_host_bridge could help
> >> us to find the private pci_controller, but in this case, pci_host_bridge is not a pointer
> >> so we put all pci_host_bridge init stuff in host drivers ?
> >
> > Of course we put pci_host_bridge init *calls* in the host drivers because we need to do host
> > driver specific initialisation there anyway.
> >
> >> And if we still use arch spec
> >> macros convert ssydata to pci_controller, so what's the greatest advantage ?
> >
> > Agree, the macro is not useful unless we have a common pci_controller structure. Sorry about
> > the noise.
> >
> >>
> >> If we move domain and msi_chip out of sysdata, what's other things in sysdata still need us
> >> to convert in PCI core ?
> >
> > I've never said we need to keep sysdata. From my discussion with Bjorn a year ago the idea was
> > to put the sysdata members into pci_host_bridge structure and remove sysdata member from pci_bus.
> > pci_scan_root_bus() can still get a parameter called sysdata if we want, but it will be a
> > struct pci_host_bridge * type.
> 
> Fine.
> 
> >
> > Best regards,
> > Liviu
> >
> >>
> >>
> >>
> >>>
> >>> Best regards,
> >>> Liviu
> >>>
> >>>>
> >>>>>
> >>>>>> +       b->ops = bridge->ops;
> >>>>>
> >>>>> See comment above why I don't think this is necessary.
> >>>>>
> >>>>>> +       b->number = b->busn_res.start = bridge->busnum;
> >>>>>>         pci_bus_assign_domain_nr(b, parent);
> >>>>>> -       b2 = pci_find_bus(pci_domain_nr(b), bus);
> >>>>>> +       bridge->domain = pci_domain_nr(b);
> >>>>>
> >>>>> Do you really want to overwrite the bridge's domain with the one from a bus that
> >>>>> could possibly be rejected a couple of lines further down?
> >>>>>
> >>>>> As an asside: if we are doing the split of pci_host_bridge from root bus creation
> >>>>> it is worth in my opinion to move the domain setup in pci_create_host_bridge()
> >>>>> and stop fiddling with it here.
> >>>>
> >>>>
> >>>> Hi Liviu, these lines just temporary, I will remove it after all host drivers
> >>>> save its domain in pci_host_bridge.
> >>>>
> >>>>
> >>>>>
> >>>>> Otherwise it looks to me like you are heading in the right direction.
> >>>>
> >>>> Thanks!
> >>>> Yijing.
> >>>>
> >>>>>
> >>>>> Best regards,
> >>>>> Liviu
> >>>>>
> >>>>>> +       b2 = pci_find_bus(pci_domain_nr(b), bridge->busnum);
> >>>>>>         if (b2) {
> >>>>>>                 /* If we already got to this bus through a different bridge, ignore it */
> >>>>>>                 dev_dbg(&b2->dev, "bus already known\n");
> >>>>>>                 goto err_out;
> >>>>>>         }
> >>>>>>
> >>>>>> -       bridge = pci_alloc_host_bridge(b);
> >>>>>> -       if (!bridge)
> >>>>>> -               goto err_out;
> >>>>>> -
> >>>>>> -       bridge->dev.parent = parent;
> >>>>>> -       bridge->dev.release = pci_release_host_bridge_dev;
> >>>>>> -       dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
> >>>>>> -       error = pcibios_root_bridge_prepare(bridge);
> >>>>>> -       if (error) {
> >>>>>> -               kfree(bridge);
> >>>>>> -               goto err_out;
> >>>>>> -       }
> >>>>>> -
> >>>>>> -       error = device_register(&bridge->dev);
> >>>>>> -       if (error) {
> >>>>>> -               put_device(&bridge->dev);
> >>>>>> -               goto err_out;
> >>>>>> -       }
> >>>>>>         b->bridge = get_device(&bridge->dev);
> >>>>>>         device_enable_async_suspend(b->bridge);
> >>>>>>         pci_set_bus_of_node(b);
> >>>>>> @@ -1950,7 +1899,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
> >>>>>>
> >>>>>>         b->dev.class = &pcibus_class;
> >>>>>>         b->dev.parent = b->bridge;
> >>>>>> -       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
> >>>>>> +       dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), b->number);
> >>>>>>         error = device_register(&b->dev);
> >>>>>>         if (error)
> >>>>>>                 goto class_dev_reg_err;
> >>>>>> @@ -1966,12 +1915,11 @@ struct pci_bus *pci_create_root_bus(struct device *parent, u32 db,
> >>>>>>                 printk(KERN_INFO "PCI host bridge to bus %s\n", dev_name(&b->dev));
> >>>>>>
> >>>>>>         /* Add initial resources to the bus */
> >>>>>> -       list_for_each_entry_safe(window, n, resources, list) {
> >>>>>> -               list_move_tail(&window->list, &bridge->windows);
> >>>>>> +       list_for_each_entry(window, &bridge->windows, list) {
> >>>>>>                 res = window->res;
> >>>>>>                 offset = window->offset;
> >>>>>>                 if (res->flags & IORESOURCE_BUS)
> >>>>>> -                       pci_bus_insert_busn_res(b, bus, res->end);
> >>>>>> +                       pci_bus_insert_busn_res(b, b->number, res->end);
> >>>>>>                 else
> >>>>>>                         pci_bus_add_resource(b, res, 0);
> >>>>>>                 if (offset) {
> >>>>>> @@ -2001,6 +1949,25 @@ err_out:
> >>>>>>         return NULL;
> >>>>>>  }
> >>>>>>
> >>>>>> +struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
> >>>>>> +               struct pci_ops *ops, void *sysdata, struct list_head *resources)
> >>>>>> +{
> >>>>>> +       struct pci_host_bridge *host;
> >>>>>> +
> >>>>>> +       host = pci_create_host_bridge(parent, bus, ops,
> >>>>>> +                       sysdata ,resources);
> >>>>>> +       if (!host)
> >>>>>> +               return NULL;
> >>>>>> +
> >>>>>> +       host->bus = __pci_create_root_bus(host);
> >>>>>> +       if (!host->bus) {
> >>>>>> +               pci_free_host_bridge(host);
> >>>>>> +               return NULL;
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       return host->bus;
> >>>>>> +}
> >>>>>> +
> >>>>>>  int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
> >>>>>>  {
> >>>>>>         struct resource *res = &b->busn_res;
> >>>>>> @@ -2069,40 +2036,37 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, u32 db,
> >>>>>>  {
> >>>>>>         struct pci_host_bridge_window *window;
> >>>>>>         bool found = false;
> >>>>>> -       struct pci_bus *b;
> >>>>>> -       LIST_HEAD(default_res);
> >>>>>> +       struct pci_host_bridge *host;
> >>>>>>         int max;
> >>>>>>
> >>>>>> -       if (!resources) {
> >>>>>> -               pci_add_resource(&default_res, &ioport_resource);
> >>>>>> -               pci_add_resource(&default_res, &iomem_resource);
> >>>>>> -               pci_add_resource(&default_res, &busn_resource);
> >>>>>> -       } else {
> >>>>>> -               list_for_each_entry(window, resources, list)
> >>>>>> -                       if (window->res->flags & IORESOURCE_BUS) {
> >>>>>> -                               found = true;
> >>>>>> -                               break;
> >>>>>> -                       }
> >>>>>> -       }
> >>>>>> +       host = pci_create_host_bridge(parent, db, ops, sysdata, resources);
> >>>>>> +       if (!host)
> >>>>>> +               return NULL;
> >>>>>>
> >>>>>> -       b = pci_create_root_bus(parent, db, ops, sysdata,
> >>>>>> -                       resources ? resources : &default_res);
> >>>>>> -       if (!b)
> >>>>>> +       list_for_each_entry(window, &host->windows, list)
> >>>>>> +               if (window->res->flags & IORESOURCE_BUS) {
> >>>>>> +                       found = true;
> >>>>>> +                       break;
> >>>>>> +               }
> >>>>>> +
> >>>>>> +       host->bus = __pci_create_root_bus(host);
> >>>>>> +       if (!host->bus) {
> >>>>>> +               pci_free_host_bridge(host);
> >>>>>>                 return NULL;
> >>>>>> +       }
> >>>>>>
> >>>>>>         if (!found) {
> >>>>>> -               dev_info(&b->dev,
> >>>>>> +               dev_info(&host->bus->dev,
> >>>>>>                  "No busn resource found for root bus, will use [bus %02x-ff]\n",
> >>>>>>                         PCI_BUSNUM(db));
> >>>>>> -               pci_bus_insert_busn_res(b, PCI_BUSNUM(db), 255);
> >>>>>> +               pci_bus_insert_busn_res(host->bus, PCI_BUSNUM(db), 255);
> >>>>>>         }
> >>>>>>
> >>>>>> -       max = pci_scan_child_bus(b);
> >>>>>> -
> >>>>>> +       max = pci_scan_child_bus(host->bus);
> >>>>>>         if (!found)
> >>>>>> -               pci_bus_update_busn_res_end(b, max);
> >>>>>> +               pci_bus_update_busn_res_end(host->bus, max);
> >>>>>>
> >>>>>> -       return b;
> >>>>>> +       return host->bus;
> >>>>>>  }
> >>>>>>  EXPORT_SYMBOL(pci_scan_root_bus);
> >>>>>>
> >>>>>> diff --git a/include/linux/pci.h b/include/linux/pci.h
> >>>>>> index 8b11b38..daa7f40 100644
> >>>>>> --- a/include/linux/pci.h
> >>>>>> +++ b/include/linux/pci.h
> >>>>>> @@ -402,7 +402,12 @@ struct pci_host_bridge_window {
> >>>>>>  struct pci_host_bridge {
> >>>>>>         struct device dev;
> >>>>>>         struct pci_bus *bus;            /* root bus */
> >>>>>> +       struct list_head list;
> >>>>>>         struct list_head windows;       /* pci_host_bridge_windows */
> >>>>>> +       int busnum;
> >>>>>> +       int domain;
> >>>>>> +       void *sysdata;
> >>>>>> +       struct pci_ops *ops;
> >>>>>>         void (*release_fn)(struct pci_host_bridge *);
> >>>>>>         void *release_data;
> >>>>>>  };
> >>>>>> @@ -413,7 +418,9 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
> >>>>>>                      void *release_data);
> >>>>>>
> >>>>>>  int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge);
> >>>>>> -
> >>>>>> +struct pci_host_bridge *pci_create_host_bridge(
> >>>>>> +               struct device *parent, u32 db, struct pci_ops *ops,
> >>>>>> +               void *sys, struct list_head *resources);
> >>>>>>  /*
> >>>>>>   * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
> >>>>>>   * to P2P or CardBus bridge windows) go in a table.  Additional ones (for
> >>>>>> @@ -770,6 +777,8 @@ void pci_bus_add_devices(const struct pci_bus *bus);
> >>>>>>  struct pci_bus *pci_create_root_bus(struct device *parent, u32 bus,
> >>>>>>                                     struct pci_ops *ops, void *sysdata,
> >>>>>>                                     struct list_head *resources);
> >>>>>> +struct pci_bus *__pci_create_root_bus(struct pci_host_bridge *host);
> >>>>>> +void pci_free_host_bridge(struct pci_host_bridge *host);
> >>>>>>  int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
> >>>>>>  int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
> >>>>>>  void pci_bus_release_busn_res(struct pci_bus *b);
> >>>>>> --
> >>>>>> 1.7.1
> >>>>>>
> >>>>>> --
> >>>>>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> >>>>>> the body of a message to majordomo@vger.kernel.org
> >>>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >>>>>>
> >>>>>
> >>>>
> >>>>
> >>>> --
> >>>> Thanks!
> >>>> Yijing
> >>>>
> >>>> --
> >>>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> >>>> the body of a message to majordomo@vger.kernel.org
> >>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >>>>
> >>>
> >>
> >>
> >> --
> >> Thanks!
> >> Yijing
> >>
> >>
> >
> 
> 
> --
> Thanks!
> Yijing
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯


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

end of thread, other threads:[~2014-11-21  9:53 UTC | newest]

Thread overview: 65+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-17 10:21 [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Yijing Wang
2014-11-17 10:21 ` [RFC PATCH 01/16] PCI: Enhance pci_scan_root_bus() to support default IO/MEM resources Yijing Wang
2014-11-17 10:08   ` Arnd Bergmann
2014-11-18  7:44     ` Yijing Wang
2014-11-18  9:36       ` Arnd Bergmann
2014-11-18 11:46         ` Yijing Wang
2014-11-18 14:23           ` Liviu Dudau
2014-11-19  1:15             ` Yijing Wang
2014-11-17 10:21 ` [RFC PATCH 02/16] PCI: Use pci_scan_root_bus() instead of pci_scan_bus() Yijing Wang
2014-11-18 14:28   ` Liviu Dudau
2014-11-19  1:19     ` Yijing Wang
2014-11-17 10:21 ` [RFC PATCH 03/16] PCI: Clean up pci_scan_bus() Yijing Wang
2014-11-17 10:21 ` [RFC PATCH 04/16] PCI: Rip out pci_bus_add_devices() from pci_scan_root_bus() Yijing Wang
2014-11-18 14:34   ` Liviu Dudau
2014-11-19  1:21     ` Yijing Wang
2014-11-17 10:21 ` [RFC PATCH 05/16] PCI: Use pci_scan_root_bus() instead of pci_scan_bus_parented() Yijing Wang
2014-11-17 10:21 ` [RFC PATCH 06/16] PCI: Use u32 type to combine PCI domain and bus number Yijing Wang
2014-11-17 10:21 ` [RFC PATCH 07/16] PCI: Separate pci_host_bridge creation out of pci_create_root_bus() Yijing Wang
2014-11-17 10:56   ` Arnd Bergmann
2014-11-18  8:32     ` Yijing Wang
2014-11-18  9:30       ` Arnd Bergmann
2014-11-18 11:44         ` Yijing Wang
2014-11-18 12:25           ` Arnd Bergmann
2014-11-18 12:41             ` Yijing Wang
2014-11-18 14:48       ` Liviu Dudau
2014-11-19  2:24         ` Yijing Wang
2014-11-19 16:29           ` Liviu Dudau
2014-11-20  2:00             ` Yijing Wang
2014-11-18 15:30   ` Liviu Dudau
2014-11-19  1:42     ` Yijing Wang
2014-11-19 16:37       ` Liviu Dudau
2014-11-20  2:47         ` Yijing Wang
2014-11-20  9:47           ` Liviu Dudau
2014-11-21  2:53             ` Yijing Wang
2014-11-21  9:53               ` Liviu Dudau
2014-11-17 10:21 ` [RFC PATCH 08/16] PCI: Introduce pci_scan_host_bridge() and pci_host_info Yijing Wang
2014-11-18 15:42   ` Liviu Dudau
2014-11-19  2:09     ` Yijing Wang
2014-11-19 16:41       ` Liviu Dudau
2014-11-20  2:54         ` Yijing Wang
2014-11-17 10:21 ` [RFC PATCH 09/16] PCI: Associate .get_msi_ctrl() with pci_host_bridge Yijing Wang
2014-11-17 15:03   ` Lorenzo Pieralisi
2014-11-17 10:21 ` [RFC PATCH 10/16] PCI: Add of_scan_bus() to pci_host_info Yijing Wang
2014-11-17 10:21 ` [RFC PATCH 11/16] x86/PCI: Use pci_scan_host_bridge() instead of pci_create_root_bus() Yijing Wang
2014-11-17 10:21 ` [RFC PATCH 12/16] ia64/PCI: Remove the redundant bus variable Yijing Wang
2014-11-17 10:21 ` [RFC PATCH 13/16] ia64/PCI: Use pci_scan_host_bridge() to refactor pci_acpi_scan_root() Yijing Wang
2014-11-17 10:21 ` [RFC PATCH 14/16] arm/PCI: Introduce pci_get_domain_nr() Yijing Wang
2014-11-17 12:08   ` Lorenzo Pieralisi
2014-11-18  0:55     ` Yijing Wang
2014-11-17 10:21 ` [RFC PATCH 15/16] arm/PCI: Use pci_scan_host_bridge() instead of pci_scan_root_bus() Yijing Wang
2014-11-17 10:21 ` [RFC PATCH 16/16] powerpc/PCI: Use pci_scan_host_bridge() to scan PCI bus Yijing Wang
2014-11-17 14:13 ` [RFC PATCH 00/16] Refine PCI host bridge scan interfaces Arnd Bergmann
2014-11-18 11:17   ` Yijing Wang
2014-11-18 11:30     ` Arnd Bergmann
2014-11-18 11:45       ` Lorenzo Pieralisi
2014-11-18 12:14         ` Yijing Wang
2014-11-18 12:17       ` Yijing Wang
2014-11-18 12:27         ` Arnd Bergmann
2014-11-20 12:01           ` Tomasz Nowicki
2014-11-20 13:15             ` Arnd Bergmann
2014-11-20 11:54   ` Tomasz Nowicki
2014-11-20 12:08     ` Liviu Dudau
2014-11-20 12:53       ` Tomasz Nowicki
2014-11-20 16:39         ` Liviu Dudau
2014-11-21  2:58           ` Yijing Wang

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