All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v7 0/6] PCI: hisi: Add PCIe host support for HiSilicon SoC Hip05
@ 2015-08-17 11:55 ` Zhou Wang
  0 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: Bjorn Helgaas, jingoohan1-Re5JQEeQqe8AvxtiuMwx3w, Pratyush Anand,
	Arnd Bergmann, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	lorenzo.pieralisi-5wv7dgnIgG8, james.morse-5wv7dgnIgG8,
	Liviu.Dudau-5wv7dgnIgG8, jason-NLaQJdtUoK4Be96aLqz0jA,
	robh-DgEjT+Ai2ygdnm+yROfE0A
  Cc: linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q,
	zhudacai-C8/M+/jPZTeaMJb+Lgu22Q,
	zhangjukuo-hv44wF8Li93QT0dZR+AlfA,
	qiuzhenfa-C8/M+/jPZTeaMJb+Lgu22Q,
	liudongdong3-hv44wF8Li93QT0dZR+AlfA,
	qiujiang-hv44wF8Li93QT0dZR+AlfA, xuwei5-C8/M+/jPZTeaMJb+Lgu22Q,
	liguozhu-C8/M+/jPZTeaMJb+Lgu22Q, Zhou Wang

This patchset adds PCIe host support for HiSilicon SoC Hip05. The PCIe hosts
use PCIe IP core from Synopsys, So this driver is base on designware PCIe driver.

Hip05 is an ARMv8 architecture SoC. It should be able to use ARM64 PCIe API in
designeware PCIe driver. So this patch also adds ARM64 support for designware
pcie.

This patchset is based on v4.2-rc1.

Change from v6:
- Add Pratyush's Acked-by for 1/6 and 2/6.
- Add James' Tested-by for 3/6.

Change from v5:
- Merge 1/6 in this series, discussion about this can be found in [1]

Change from v4:
- Change the author of 1/5 to Gabriele.
- Modify problems in 3/5 pointed by Bjorn.
- Modify spelling problems in 4/5.

Change from v3:
- Change 1/5 to what Gabriele suggested.
- Use win->__res.start to get *_mod_base in 2/5, this fix a bug in v3 series.

Change from v2:
- Move struct pci_dev *dev and struct pci_sys_data *sys in
  pcibios_align_resource in 1/5.
- Add Gabriele's codes in 2/5 which delete unnecessary information parse and
  use of_pci_get_host_bridge_resources for both ARM32 and ARM64.
- Add maintainer patch 5/5.

Change from RFC v1:
- Add 1/4 patch by Arnd which removes align_resource callback in ARM
  pcibios_align_resource.
- Change head file in pcie-designware from asm/hardirq.h to linux/hardirq.h.
- Set pp->root_bus_nr = 0 in dra7xx, exynos, imx6, keystone, layerscape,
  spear13xx.
- Remove unnecessary parentheses of some macros in pcie-hisi.
- Use macro to replace some magic values.
- Merge two loops together and add some comments about it in context_config
  function in pcie-hisi.
- Modify some value of items in pcie node example in binding document. 

Change from RFC:
- delete dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci,
  merge related operations into dw_pcie_host_init.

Link of v6:
- http://www.spinics.net/lists/linux-pci/msg43669.html
Link of v5:
- http://www.spinics.net/lists/devicetree/msg87959.html
Link of v4:
- http://www.spinics.net/lists/arm-kernel/msg433050.html
Link of v3:
- http://www.spinics.net/lists/linux-pci/msg42539.html
Link of v2:
- http://www.spinics.net/lists/linux-pci/msg41844.html
Link of RFC v1:
- http://www.spinics.net/lists/linux-pci/msg41305.html
Link of RFC:
- http://www.spinics.net/lists/linux-pci/msg40434.html

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-July/359741.html

Zhou Wang (4):
  PCI: designware: Add ARM64 support
  PCI: hisi: Add PCIe host support for HiSilicon SoC Hip05
  Documentation: DT: Add HiSilicon PCIe host binding
  MAINTAINERS: Add pcie-hisi maintainer

gabriele paoloni (2):
  PCI: designware: move calculation of bus addresses to DRA7xx
  ARM/PCI: remove align_resource in pci_sys_data

 .../devicetree/bindings/pci/hisilicon-pcie.txt     |  46 ++++
 MAINTAINERS                                        |   7 +
 arch/arm/include/asm/mach/pci.h                    |   5 -
 arch/arm/kernel/bios32.c                           |  12 +-
 drivers/pci/host/Kconfig                           |   8 +
 drivers/pci/host/Makefile                          |   1 +
 drivers/pci/host/pci-dra7xx.c                      |  14 ++
 drivers/pci/host/pci-exynos.c                      |   2 +-
 drivers/pci/host/pci-imx6.c                        |   2 +-
 drivers/pci/host/pci-keystone-dw.c                 |   2 +-
 drivers/pci/host/pci-keystone.c                    |   2 +-
 drivers/pci/host/pci-layerscape.c                  |   2 +-
 drivers/pci/host/pcie-designware.c                 | 236 ++++++-------------
 drivers/pci/host/pcie-designware.h                 |  14 +-
 drivers/pci/host/pcie-hisi.c                       | 254 +++++++++++++++++++++
 drivers/pci/host/pcie-spear13xx.c                  |   2 +-
 16 files changed, 425 insertions(+), 184 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
 create mode 100644 drivers/pci/host/pcie-hisi.c

-- 
1.9.1

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

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

* [PATCH v7 0/6] PCI: hisi: Add PCIe host support for HiSilicon SoC Hip05
@ 2015-08-17 11:55 ` Zhou Wang
  0 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, gabriele.paoloni, lorenzo.pieralisi,
	james.morse, Liviu.Dudau, jason, robh
  Cc: linux-pci, linux-arm-kernel, devicetree, yuanzhichang, zhudacai,
	zhangjukuo, qiuzhenfa, liudongdong3, qiujiang, xuwei5, liguozhu,
	Zhou Wang

This patchset adds PCIe host support for HiSilicon SoC Hip05. The PCIe hosts
use PCIe IP core from Synopsys, So this driver is base on designware PCIe driver.

Hip05 is an ARMv8 architecture SoC. It should be able to use ARM64 PCIe API in
designeware PCIe driver. So this patch also adds ARM64 support for designware
pcie.

This patchset is based on v4.2-rc1.

Change from v6:
- Add Pratyush's Acked-by for 1/6 and 2/6.
- Add James' Tested-by for 3/6.

Change from v5:
- Merge 1/6 in this series, discussion about this can be found in [1]

Change from v4:
- Change the author of 1/5 to Gabriele.
- Modify problems in 3/5 pointed by Bjorn.
- Modify spelling problems in 4/5.

Change from v3:
- Change 1/5 to what Gabriele suggested.
- Use win->__res.start to get *_mod_base in 2/5, this fix a bug in v3 series.

Change from v2:
- Move struct pci_dev *dev and struct pci_sys_data *sys in
  pcibios_align_resource in 1/5.
- Add Gabriele's codes in 2/5 which delete unnecessary information parse and
  use of_pci_get_host_bridge_resources for both ARM32 and ARM64.
- Add maintainer patch 5/5.

Change from RFC v1:
- Add 1/4 patch by Arnd which removes align_resource callback in ARM
  pcibios_align_resource.
- Change head file in pcie-designware from asm/hardirq.h to linux/hardirq.h.
- Set pp->root_bus_nr = 0 in dra7xx, exynos, imx6, keystone, layerscape,
  spear13xx.
- Remove unnecessary parentheses of some macros in pcie-hisi.
- Use macro to replace some magic values.
- Merge two loops together and add some comments about it in context_config
  function in pcie-hisi.
- Modify some value of items in pcie node example in binding document. 

Change from RFC:
- delete dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci,
  merge related operations into dw_pcie_host_init.

Link of v6:
- http://www.spinics.net/lists/linux-pci/msg43669.html
Link of v5:
- http://www.spinics.net/lists/devicetree/msg87959.html
Link of v4:
- http://www.spinics.net/lists/arm-kernel/msg433050.html
Link of v3:
- http://www.spinics.net/lists/linux-pci/msg42539.html
Link of v2:
- http://www.spinics.net/lists/linux-pci/msg41844.html
Link of RFC v1:
- http://www.spinics.net/lists/linux-pci/msg41305.html
Link of RFC:
- http://www.spinics.net/lists/linux-pci/msg40434.html

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-July/359741.html

Zhou Wang (4):
  PCI: designware: Add ARM64 support
  PCI: hisi: Add PCIe host support for HiSilicon SoC Hip05
  Documentation: DT: Add HiSilicon PCIe host binding
  MAINTAINERS: Add pcie-hisi maintainer

gabriele paoloni (2):
  PCI: designware: move calculation of bus addresses to DRA7xx
  ARM/PCI: remove align_resource in pci_sys_data

 .../devicetree/bindings/pci/hisilicon-pcie.txt     |  46 ++++
 MAINTAINERS                                        |   7 +
 arch/arm/include/asm/mach/pci.h                    |   5 -
 arch/arm/kernel/bios32.c                           |  12 +-
 drivers/pci/host/Kconfig                           |   8 +
 drivers/pci/host/Makefile                          |   1 +
 drivers/pci/host/pci-dra7xx.c                      |  14 ++
 drivers/pci/host/pci-exynos.c                      |   2 +-
 drivers/pci/host/pci-imx6.c                        |   2 +-
 drivers/pci/host/pci-keystone-dw.c                 |   2 +-
 drivers/pci/host/pci-keystone.c                    |   2 +-
 drivers/pci/host/pci-layerscape.c                  |   2 +-
 drivers/pci/host/pcie-designware.c                 | 236 ++++++-------------
 drivers/pci/host/pcie-designware.h                 |  14 +-
 drivers/pci/host/pcie-hisi.c                       | 254 +++++++++++++++++++++
 drivers/pci/host/pcie-spear13xx.c                  |   2 +-
 16 files changed, 425 insertions(+), 184 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
 create mode 100644 drivers/pci/host/pcie-hisi.c

-- 
1.9.1


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

* [PATCH v7 0/6] PCI: hisi: Add PCIe host support for HiSilicon SoC Hip05
@ 2015-08-17 11:55 ` Zhou Wang
  0 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset adds PCIe host support for HiSilicon SoC Hip05. The PCIe hosts
use PCIe IP core from Synopsys, So this driver is base on designware PCIe driver.

Hip05 is an ARMv8 architecture SoC. It should be able to use ARM64 PCIe API in
designeware PCIe driver. So this patch also adds ARM64 support for designware
pcie.

This patchset is based on v4.2-rc1.

Change from v6:
- Add Pratyush's Acked-by for 1/6 and 2/6.
- Add James' Tested-by for 3/6.

Change from v5:
- Merge 1/6 in this series, discussion about this can be found in [1]

Change from v4:
- Change the author of 1/5 to Gabriele.
- Modify problems in 3/5 pointed by Bjorn.
- Modify spelling problems in 4/5.

Change from v3:
- Change 1/5 to what Gabriele suggested.
- Use win->__res.start to get *_mod_base in 2/5, this fix a bug in v3 series.

Change from v2:
- Move struct pci_dev *dev and struct pci_sys_data *sys in
  pcibios_align_resource in 1/5.
- Add Gabriele's codes in 2/5 which delete unnecessary information parse and
  use of_pci_get_host_bridge_resources for both ARM32 and ARM64.
- Add maintainer patch 5/5.

Change from RFC v1:
- Add 1/4 patch by Arnd which removes align_resource callback in ARM
  pcibios_align_resource.
- Change head file in pcie-designware from asm/hardirq.h to linux/hardirq.h.
- Set pp->root_bus_nr = 0 in dra7xx, exynos, imx6, keystone, layerscape,
  spear13xx.
- Remove unnecessary parentheses of some macros in pcie-hisi.
- Use macro to replace some magic values.
- Merge two loops together and add some comments about it in context_config
  function in pcie-hisi.
- Modify some value of items in pcie node example in binding document. 

Change from RFC:
- delete dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci,
  merge related operations into dw_pcie_host_init.

Link of v6:
- http://www.spinics.net/lists/linux-pci/msg43669.html
Link of v5:
- http://www.spinics.net/lists/devicetree/msg87959.html
Link of v4:
- http://www.spinics.net/lists/arm-kernel/msg433050.html
Link of v3:
- http://www.spinics.net/lists/linux-pci/msg42539.html
Link of v2:
- http://www.spinics.net/lists/linux-pci/msg41844.html
Link of RFC v1:
- http://www.spinics.net/lists/linux-pci/msg41305.html
Link of RFC:
- http://www.spinics.net/lists/linux-pci/msg40434.html

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-July/359741.html

Zhou Wang (4):
  PCI: designware: Add ARM64 support
  PCI: hisi: Add PCIe host support for HiSilicon SoC Hip05
  Documentation: DT: Add HiSilicon PCIe host binding
  MAINTAINERS: Add pcie-hisi maintainer

gabriele paoloni (2):
  PCI: designware: move calculation of bus addresses to DRA7xx
  ARM/PCI: remove align_resource in pci_sys_data

 .../devicetree/bindings/pci/hisilicon-pcie.txt     |  46 ++++
 MAINTAINERS                                        |   7 +
 arch/arm/include/asm/mach/pci.h                    |   5 -
 arch/arm/kernel/bios32.c                           |  12 +-
 drivers/pci/host/Kconfig                           |   8 +
 drivers/pci/host/Makefile                          |   1 +
 drivers/pci/host/pci-dra7xx.c                      |  14 ++
 drivers/pci/host/pci-exynos.c                      |   2 +-
 drivers/pci/host/pci-imx6.c                        |   2 +-
 drivers/pci/host/pci-keystone-dw.c                 |   2 +-
 drivers/pci/host/pci-keystone.c                    |   2 +-
 drivers/pci/host/pci-layerscape.c                  |   2 +-
 drivers/pci/host/pcie-designware.c                 | 236 ++++++-------------
 drivers/pci/host/pcie-designware.h                 |  14 +-
 drivers/pci/host/pcie-hisi.c                       | 254 +++++++++++++++++++++
 drivers/pci/host/pcie-spear13xx.c                  |   2 +-
 16 files changed, 425 insertions(+), 184 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
 create mode 100644 drivers/pci/host/pcie-hisi.c

-- 
1.9.1

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

* [PATCH v7 1/6] PCI: designware: move calculation of bus addresses to DRA7xx
  2015-08-17 11:55 ` Zhou Wang
  (?)
@ 2015-08-17 11:55     ` Zhou Wang
  -1 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: Bjorn Helgaas, jingoohan1-Re5JQEeQqe8AvxtiuMwx3w, Pratyush Anand,
	Arnd Bergmann, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	lorenzo.pieralisi-5wv7dgnIgG8, james.morse-5wv7dgnIgG8,
	Liviu.Dudau-5wv7dgnIgG8, jason-NLaQJdtUoK4Be96aLqz0jA,
	robh-DgEjT+Ai2ygdnm+yROfE0A
  Cc: linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q,
	zhudacai-C8/M+/jPZTeaMJb+Lgu22Q,
	zhangjukuo-hv44wF8Li93QT0dZR+AlfA,
	qiuzhenfa-C8/M+/jPZTeaMJb+Lgu22Q,
	liudongdong3-hv44wF8Li93QT0dZR+AlfA,
	qiujiang-hv44wF8Li93QT0dZR+AlfA, xuwei5-C8/M+/jPZTeaMJb+Lgu22Q,
	liguozhu-C8/M+/jPZTeaMJb+Lgu22Q, Zhou Wang

From: gabriele paoloni <gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>

Commit f4c55c5a3f7f "PCI: designware: Program ATU with untranslated
address" added the calculation of PCI BUS addresses in designware,
storing them in new fields added in "struct pcie_port". This
calculation is done for every designware user even if is only
applicable to DRA7xx.
This patch moves the calculation of the bus addresses to the DRA7xx
driver and is needed to allow the rework of designware to use
the new DT parsing API.

Signed-off-by: Gabriele Paoloni <gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
Signed-off-by: Zhou Wang <wangzhou1-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
Acked-by: Pratyush Anand <pratyush.anand-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/pci/host/pci-dra7xx.c      | 13 +++++++++++++
 drivers/pci/host/pcie-designware.c | 15 ++++-----------
 2 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
index 80db09e..18ae7ff 100644
--- a/drivers/pci/host/pci-dra7xx.c
+++ b/drivers/pci/host/pci-dra7xx.c
@@ -61,6 +61,7 @@
 
 #define	PCIECTRL_DRA7XX_CONF_PHY_CS			0x010C
 #define	LINK_UP						BIT(16)
+#define	CPU_TO_BUS_ADDR					0x0FFFFFFF
 
 struct dra7xx_pcie {
 	void __iomem		*base;
@@ -139,6 +140,18 @@ static void dra7xx_pcie_enable_interrupts(struct pcie_port *pp)
 static void dra7xx_pcie_host_init(struct pcie_port *pp)
 {
 	dw_pcie_setup_rc(pp);
+
+	if (pp->io_mod_base)
+		pp->io_mod_base &= CPU_TO_BUS_ADDR;
+
+	if (pp->mem_mod_base)
+		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
+
+	if (pp->cfg0_mod_base) {
+		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
+		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
+	}
+
 	dra7xx_pcie_establish_link(pp);
 	if (IS_ENABLED(CONFIG_PCI_MSI))
 		dw_pcie_msi_init(pp);
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 69486be..c5d407c 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -366,14 +366,10 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	struct of_pci_range range;
 	struct of_pci_range_parser parser;
 	struct resource *cfg_res;
-	u32 val, na, ns;
+	u32 val, ns;
 	const __be32 *addrp;
 	int i, index, ret;
 
-	/* Find the address cell size and the number of cells in order to get
-	 * the untranslated address.
-	 */
-	of_property_read_u32(np, "#address-cells", &na);
 	ns = of_n_size_cells(np);
 
 	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
@@ -416,8 +412,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
 			pp->io_base = range.cpu_addr;
 
 			/* Find the untranslated IO space address */
-			pp->io_mod_base = of_read_number(parser.range -
-							 parser.np + na, ns);
+			pp->io_mod_base = range.cpu_addr;
 		}
 		if (restype == IORESOURCE_MEM) {
 			of_pci_range_to_resource(&range, np, &pp->mem);
@@ -426,8 +421,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
 			pp->mem_bus_addr = range.pci_addr;
 
 			/* Find the untranslated MEM space address */
-			pp->mem_mod_base = of_read_number(parser.range -
-							  parser.np + na, ns);
+			pp->mem_mod_base = range.cpu_addr;
 		}
 		if (restype == 0) {
 			of_pci_range_to_resource(&range, np, &pp->cfg);
@@ -437,8 +431,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
 			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
 
 			/* Find the untranslated configuration space address */
-			pp->cfg0_mod_base = of_read_number(parser.range -
-							   parser.np + na, ns);
+			pp->cfg0_mod_base = range.cpu_addr;
 			pp->cfg1_mod_base = pp->cfg0_mod_base +
 					    pp->cfg0_size;
 		}
-- 
1.9.1

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

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

* [PATCH v7 1/6] PCI: designware: move calculation of bus addresses to DRA7xx
@ 2015-08-17 11:55     ` Zhou Wang
  0 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, gabriele.paoloni, lorenzo.pieralisi,
	james.morse, Liviu.Dudau, jason, robh
  Cc: linux-pci, linux-arm-kernel, devicetree, yuanzhichang, zhudacai,
	zhangjukuo, qiuzhenfa, liudongdong3, qiujiang, xuwei5, liguozhu,
	Zhou Wang

From: gabriele paoloni <gabriele.paoloni@huawei.com>

Commit f4c55c5a3f7f "PCI: designware: Program ATU with untranslated
address" added the calculation of PCI BUS addresses in designware,
storing them in new fields added in "struct pcie_port". This
calculation is done for every designware user even if is only
applicable to DRA7xx.
This patch moves the calculation of the bus addresses to the DRA7xx
driver and is needed to allow the rework of designware to use
the new DT parsing API.

Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
Acked-by: Pratyush Anand <pratyush.anand@gmail.com>
---
 drivers/pci/host/pci-dra7xx.c      | 13 +++++++++++++
 drivers/pci/host/pcie-designware.c | 15 ++++-----------
 2 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
index 80db09e..18ae7ff 100644
--- a/drivers/pci/host/pci-dra7xx.c
+++ b/drivers/pci/host/pci-dra7xx.c
@@ -61,6 +61,7 @@
 
 #define	PCIECTRL_DRA7XX_CONF_PHY_CS			0x010C
 #define	LINK_UP						BIT(16)
+#define	CPU_TO_BUS_ADDR					0x0FFFFFFF
 
 struct dra7xx_pcie {
 	void __iomem		*base;
@@ -139,6 +140,18 @@ static void dra7xx_pcie_enable_interrupts(struct pcie_port *pp)
 static void dra7xx_pcie_host_init(struct pcie_port *pp)
 {
 	dw_pcie_setup_rc(pp);
+
+	if (pp->io_mod_base)
+		pp->io_mod_base &= CPU_TO_BUS_ADDR;
+
+	if (pp->mem_mod_base)
+		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
+
+	if (pp->cfg0_mod_base) {
+		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
+		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
+	}
+
 	dra7xx_pcie_establish_link(pp);
 	if (IS_ENABLED(CONFIG_PCI_MSI))
 		dw_pcie_msi_init(pp);
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 69486be..c5d407c 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -366,14 +366,10 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	struct of_pci_range range;
 	struct of_pci_range_parser parser;
 	struct resource *cfg_res;
-	u32 val, na, ns;
+	u32 val, ns;
 	const __be32 *addrp;
 	int i, index, ret;
 
-	/* Find the address cell size and the number of cells in order to get
-	 * the untranslated address.
-	 */
-	of_property_read_u32(np, "#address-cells", &na);
 	ns = of_n_size_cells(np);
 
 	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
@@ -416,8 +412,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
 			pp->io_base = range.cpu_addr;
 
 			/* Find the untranslated IO space address */
-			pp->io_mod_base = of_read_number(parser.range -
-							 parser.np + na, ns);
+			pp->io_mod_base = range.cpu_addr;
 		}
 		if (restype == IORESOURCE_MEM) {
 			of_pci_range_to_resource(&range, np, &pp->mem);
@@ -426,8 +421,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
 			pp->mem_bus_addr = range.pci_addr;
 
 			/* Find the untranslated MEM space address */
-			pp->mem_mod_base = of_read_number(parser.range -
-							  parser.np + na, ns);
+			pp->mem_mod_base = range.cpu_addr;
 		}
 		if (restype == 0) {
 			of_pci_range_to_resource(&range, np, &pp->cfg);
@@ -437,8 +431,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
 			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
 
 			/* Find the untranslated configuration space address */
-			pp->cfg0_mod_base = of_read_number(parser.range -
-							   parser.np + na, ns);
+			pp->cfg0_mod_base = range.cpu_addr;
 			pp->cfg1_mod_base = pp->cfg0_mod_base +
 					    pp->cfg0_size;
 		}
-- 
1.9.1


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

* [PATCH v7 1/6] PCI: designware: move calculation of bus addresses to DRA7xx
@ 2015-08-17 11:55     ` Zhou Wang
  0 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: linux-arm-kernel

From: gabriele paoloni <gabriele.paoloni@huawei.com>

Commit f4c55c5a3f7f "PCI: designware: Program ATU with untranslated
address" added the calculation of PCI BUS addresses in designware,
storing them in new fields added in "struct pcie_port". This
calculation is done for every designware user even if is only
applicable to DRA7xx.
This patch moves the calculation of the bus addresses to the DRA7xx
driver and is needed to allow the rework of designware to use
the new DT parsing API.

Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
Acked-by: Pratyush Anand <pratyush.anand@gmail.com>
---
 drivers/pci/host/pci-dra7xx.c      | 13 +++++++++++++
 drivers/pci/host/pcie-designware.c | 15 ++++-----------
 2 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
index 80db09e..18ae7ff 100644
--- a/drivers/pci/host/pci-dra7xx.c
+++ b/drivers/pci/host/pci-dra7xx.c
@@ -61,6 +61,7 @@
 
 #define	PCIECTRL_DRA7XX_CONF_PHY_CS			0x010C
 #define	LINK_UP						BIT(16)
+#define	CPU_TO_BUS_ADDR					0x0FFFFFFF
 
 struct dra7xx_pcie {
 	void __iomem		*base;
@@ -139,6 +140,18 @@ static void dra7xx_pcie_enable_interrupts(struct pcie_port *pp)
 static void dra7xx_pcie_host_init(struct pcie_port *pp)
 {
 	dw_pcie_setup_rc(pp);
+
+	if (pp->io_mod_base)
+		pp->io_mod_base &= CPU_TO_BUS_ADDR;
+
+	if (pp->mem_mod_base)
+		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
+
+	if (pp->cfg0_mod_base) {
+		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
+		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
+	}
+
 	dra7xx_pcie_establish_link(pp);
 	if (IS_ENABLED(CONFIG_PCI_MSI))
 		dw_pcie_msi_init(pp);
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 69486be..c5d407c 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -366,14 +366,10 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	struct of_pci_range range;
 	struct of_pci_range_parser parser;
 	struct resource *cfg_res;
-	u32 val, na, ns;
+	u32 val, ns;
 	const __be32 *addrp;
 	int i, index, ret;
 
-	/* Find the address cell size and the number of cells in order to get
-	 * the untranslated address.
-	 */
-	of_property_read_u32(np, "#address-cells", &na);
 	ns = of_n_size_cells(np);
 
 	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
@@ -416,8 +412,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
 			pp->io_base = range.cpu_addr;
 
 			/* Find the untranslated IO space address */
-			pp->io_mod_base = of_read_number(parser.range -
-							 parser.np + na, ns);
+			pp->io_mod_base = range.cpu_addr;
 		}
 		if (restype == IORESOURCE_MEM) {
 			of_pci_range_to_resource(&range, np, &pp->mem);
@@ -426,8 +421,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
 			pp->mem_bus_addr = range.pci_addr;
 
 			/* Find the untranslated MEM space address */
-			pp->mem_mod_base = of_read_number(parser.range -
-							  parser.np + na, ns);
+			pp->mem_mod_base = range.cpu_addr;
 		}
 		if (restype == 0) {
 			of_pci_range_to_resource(&range, np, &pp->cfg);
@@ -437,8 +431,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
 			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
 
 			/* Find the untranslated configuration space address */
-			pp->cfg0_mod_base = of_read_number(parser.range -
-							   parser.np + na, ns);
+			pp->cfg0_mod_base = range.cpu_addr;
 			pp->cfg1_mod_base = pp->cfg0_mod_base +
 					    pp->cfg0_size;
 		}
-- 
1.9.1

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

* [PATCH v7 2/6] ARM/PCI: remove align_resource in pci_sys_data
  2015-08-17 11:55 ` Zhou Wang
  (?)
@ 2015-08-17 11:55   ` Zhou Wang
  -1 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, gabriele.paoloni, lorenzo.pieralisi,
	james.morse, Liviu.Dudau, jason, robh
  Cc: linux-pci, linux-arm-kernel, devicetree, yuanzhichang, zhudacai,
	zhangjukuo, qiuzhenfa, liudongdong3, qiujiang, xuwei5, liguozhu

From: gabriele paoloni <gabriele.paoloni@huawei.com>

This patch is needed in order to unify the PCIe designware framework for ARM and
ARM64 architectures. In the PCIe designware unification process we are calling
pci_create_root_bus() passing a "sysdata" parameter that is the same for both
ARM and ARM64 and is of type "struct pcie_port*". In the ARM case this will
cause a problem with the function pcibios_align_resource(); in fact this will
cast "dev->sysdata" to "struct pci_sys_data*", whereas designware had passed a
"struct pcie_port*" pointer.

This patch solves the issue by removing "align_resource" from "pci_sys_data"
struct and defining a static global function pointer in "bios32.c"

Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Acked-by: Pratyush Anand <pratyush.anand@gmail.com>
---
 arch/arm/include/asm/mach/pci.h |  5 -----
 arch/arm/kernel/bios32.c        | 12 ++++++++----
 2 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h
index 28b9bb3..8a4e4de 100644
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -58,11 +58,6 @@ struct pci_sys_data {
 					/* IRQ mapping				*/
 	int		(*map_irq)(const struct pci_dev *, u8, u8);
 					/* Resource alignement requirements	*/
-	resource_size_t (*align_resource)(struct pci_dev *dev,
-					  const struct resource *res,
-					  resource_size_t start,
-					  resource_size_t size,
-					  resource_size_t align);
 	void		*private_data;	/* platform controller private data	*/
 };
 
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index fcbbbb1..4cdc64d 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -17,6 +17,11 @@
 #include <asm/mach/pci.h>
 
 static int debug_pci;
+static resource_size_t (*align_resource)(struct pci_dev *dev,
+		  const struct resource *res,
+		  resource_size_t start,
+		  resource_size_t size,
+		  resource_size_t align) = NULL;
 
 #ifdef CONFIG_PCI_MSI
 struct msi_controller *pcibios_msi_controller(struct pci_dev *dev)
@@ -468,7 +473,7 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
 		sys->busnr   = busnr;
 		sys->swizzle = hw->swizzle;
 		sys->map_irq = hw->map_irq;
-		sys->align_resource = hw->align_resource;
+		align_resource = hw->align_resource;
 		INIT_LIST_HEAD(&sys->resources);
 
 		if (hw->private_data)
@@ -589,7 +594,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
 				resource_size_t size, resource_size_t align)
 {
 	struct pci_dev *dev = data;
-	struct pci_sys_data *sys = dev->sysdata;
 	resource_size_t start = res->start;
 
 	if (res->flags & IORESOURCE_IO && start & 0x300)
@@ -597,8 +601,8 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
 
 	start = (start + align - 1) & ~(align - 1);
 
-	if (sys->align_resource)
-		return sys->align_resource(dev, res, start, size, align);
+	if (align_resource)
+		return align_resource(dev, res, start, size, align);
 
 	return start;
 }
-- 
1.9.1

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

* [PATCH v7 2/6] ARM/PCI: remove align_resource in pci_sys_data
@ 2015-08-17 11:55   ` Zhou Wang
  0 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, gabriele.paoloni, lorenzo.pieralisi,
	james.morse, Liviu.Dudau, jason, robh
  Cc: linux-pci, linux-arm-kernel, devicetree, yuanzhichang, zhudacai,
	zhangjukuo, qiuzhenfa, liudongdong3, qiujiang, xuwei5, liguozhu

From: gabriele paoloni <gabriele.paoloni@huawei.com>

This patch is needed in order to unify the PCIe designware framework for ARM and
ARM64 architectures. In the PCIe designware unification process we are calling
pci_create_root_bus() passing a "sysdata" parameter that is the same for both
ARM and ARM64 and is of type "struct pcie_port*". In the ARM case this will
cause a problem with the function pcibios_align_resource(); in fact this will
cast "dev->sysdata" to "struct pci_sys_data*", whereas designware had passed a
"struct pcie_port*" pointer.

This patch solves the issue by removing "align_resource" from "pci_sys_data"
struct and defining a static global function pointer in "bios32.c"

Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Acked-by: Pratyush Anand <pratyush.anand@gmail.com>
---
 arch/arm/include/asm/mach/pci.h |  5 -----
 arch/arm/kernel/bios32.c        | 12 ++++++++----
 2 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h
index 28b9bb3..8a4e4de 100644
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -58,11 +58,6 @@ struct pci_sys_data {
 					/* IRQ mapping				*/
 	int		(*map_irq)(const struct pci_dev *, u8, u8);
 					/* Resource alignement requirements	*/
-	resource_size_t (*align_resource)(struct pci_dev *dev,
-					  const struct resource *res,
-					  resource_size_t start,
-					  resource_size_t size,
-					  resource_size_t align);
 	void		*private_data;	/* platform controller private data	*/
 };
 
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index fcbbbb1..4cdc64d 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -17,6 +17,11 @@
 #include <asm/mach/pci.h>
 
 static int debug_pci;
+static resource_size_t (*align_resource)(struct pci_dev *dev,
+		  const struct resource *res,
+		  resource_size_t start,
+		  resource_size_t size,
+		  resource_size_t align) = NULL;
 
 #ifdef CONFIG_PCI_MSI
 struct msi_controller *pcibios_msi_controller(struct pci_dev *dev)
@@ -468,7 +473,7 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
 		sys->busnr   = busnr;
 		sys->swizzle = hw->swizzle;
 		sys->map_irq = hw->map_irq;
-		sys->align_resource = hw->align_resource;
+		align_resource = hw->align_resource;
 		INIT_LIST_HEAD(&sys->resources);
 
 		if (hw->private_data)
@@ -589,7 +594,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
 				resource_size_t size, resource_size_t align)
 {
 	struct pci_dev *dev = data;
-	struct pci_sys_data *sys = dev->sysdata;
 	resource_size_t start = res->start;
 
 	if (res->flags & IORESOURCE_IO && start & 0x300)
@@ -597,8 +601,8 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
 
 	start = (start + align - 1) & ~(align - 1);
 
-	if (sys->align_resource)
-		return sys->align_resource(dev, res, start, size, align);
+	if (align_resource)
+		return align_resource(dev, res, start, size, align);
 
 	return start;
 }
-- 
1.9.1


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

* [PATCH v7 2/6] ARM/PCI: remove align_resource in pci_sys_data
@ 2015-08-17 11:55   ` Zhou Wang
  0 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: linux-arm-kernel

From: gabriele paoloni <gabriele.paoloni@huawei.com>

This patch is needed in order to unify the PCIe designware framework for ARM and
ARM64 architectures. In the PCIe designware unification process we are calling
pci_create_root_bus() passing a "sysdata" parameter that is the same for both
ARM and ARM64 and is of type "struct pcie_port*". In the ARM case this will
cause a problem with the function pcibios_align_resource(); in fact this will
cast "dev->sysdata" to "struct pci_sys_data*", whereas designware had passed a
"struct pcie_port*" pointer.

This patch solves the issue by removing "align_resource" from "pci_sys_data"
struct and defining a static global function pointer in "bios32.c"

Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Acked-by: Pratyush Anand <pratyush.anand@gmail.com>
---
 arch/arm/include/asm/mach/pci.h |  5 -----
 arch/arm/kernel/bios32.c        | 12 ++++++++----
 2 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h
index 28b9bb3..8a4e4de 100644
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -58,11 +58,6 @@ struct pci_sys_data {
 					/* IRQ mapping				*/
 	int		(*map_irq)(const struct pci_dev *, u8, u8);
 					/* Resource alignement requirements	*/
-	resource_size_t (*align_resource)(struct pci_dev *dev,
-					  const struct resource *res,
-					  resource_size_t start,
-					  resource_size_t size,
-					  resource_size_t align);
 	void		*private_data;	/* platform controller private data	*/
 };
 
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index fcbbbb1..4cdc64d 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -17,6 +17,11 @@
 #include <asm/mach/pci.h>
 
 static int debug_pci;
+static resource_size_t (*align_resource)(struct pci_dev *dev,
+		  const struct resource *res,
+		  resource_size_t start,
+		  resource_size_t size,
+		  resource_size_t align) = NULL;
 
 #ifdef CONFIG_PCI_MSI
 struct msi_controller *pcibios_msi_controller(struct pci_dev *dev)
@@ -468,7 +473,7 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
 		sys->busnr   = busnr;
 		sys->swizzle = hw->swizzle;
 		sys->map_irq = hw->map_irq;
-		sys->align_resource = hw->align_resource;
+		align_resource = hw->align_resource;
 		INIT_LIST_HEAD(&sys->resources);
 
 		if (hw->private_data)
@@ -589,7 +594,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
 				resource_size_t size, resource_size_t align)
 {
 	struct pci_dev *dev = data;
-	struct pci_sys_data *sys = dev->sysdata;
 	resource_size_t start = res->start;
 
 	if (res->flags & IORESOURCE_IO && start & 0x300)
@@ -597,8 +601,8 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
 
 	start = (start + align - 1) & ~(align - 1);
 
-	if (sys->align_resource)
-		return sys->align_resource(dev, res, start, size, align);
+	if (align_resource)
+		return align_resource(dev, res, start, size, align);
 
 	return start;
 }
-- 
1.9.1

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

* [PATCH v7 3/6] PCI: designware: Add ARM64 support
  2015-08-17 11:55 ` Zhou Wang
  (?)
@ 2015-08-17 11:55   ` Zhou Wang
  -1 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, gabriele.paoloni, lorenzo.pieralisi,
	james.morse, Liviu.Dudau, jason, robh
  Cc: linux-pci, linux-arm-kernel, devicetree, yuanzhichang, zhudacai,
	zhangjukuo, qiuzhenfa, liudongdong3, qiujiang, xuwei5, liguozhu,
	Zhou Wang

This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete
function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci,
move related operations to dw_pcie_host_init.

In past, we use:
pci_common_init_dev
	-> pcibios_init_hw
		-> hw->scan (dw_pcie_scan_bus)
to pass 0 to root_bus_nr in struct pcie_port. This patch set pp->root_bus_nr = 0
in each PCIe host driver which is based on pcie-designware.

This patch also try to use of_pci_get_host_bridge_resources for ARM32 and ARM64
according to the suggestion for Gabriele[1]

Finally this patch reverts commit f4c55c5a3f7f "PCI: designware: Program ATU
with untranslated address" based on 1/6 in this series. we delete *_mod_base in
pcie-designware. This was discussed in [2]

I have compiled the driver with multi_v7_defconfig. However, I don't have
ARM32 PCIe related board to do test. It will be appreciated if someone could
help to test it.

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Tested-By: James Morse <james.morse@arm.com>

[1] http://www.spinics.net/lists/linux-pci/msg42194.html
[2] http://www.spinics.net/lists/arm-kernel/msg436779.html
---
 drivers/pci/host/pci-dra7xx.c      |  15 +--
 drivers/pci/host/pci-exynos.c      |   2 +-
 drivers/pci/host/pci-imx6.c        |   2 +-
 drivers/pci/host/pci-keystone-dw.c |   2 +-
 drivers/pci/host/pci-keystone.c    |   2 +-
 drivers/pci/host/pci-layerscape.c  |   2 +-
 drivers/pci/host/pcie-designware.c | 229 ++++++++++++-------------------------
 drivers/pci/host/pcie-designware.h |  14 +--
 drivers/pci/host/pcie-spear13xx.c  |   2 +-
 9 files changed, 95 insertions(+), 175 deletions(-)

diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
index 18ae7ff..1268c69 100644
--- a/drivers/pci/host/pci-dra7xx.c
+++ b/drivers/pci/host/pci-dra7xx.c
@@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp)
 {
 	dw_pcie_setup_rc(pp);
 
-	if (pp->io_mod_base)
-		pp->io_mod_base &= CPU_TO_BUS_ADDR;
+	if (pp->io_base)
+		pp->io_base &= CPU_TO_BUS_ADDR;
 
-	if (pp->mem_mod_base)
-		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
+	if (pp->mem_base)
+		pp->mem_base &= CPU_TO_BUS_ADDR;
 
-	if (pp->cfg0_mod_base) {
-		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
-		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
+	if (pp->cfg0_base) {
+		pp->cfg0_base &= CPU_TO_BUS_ADDR;
+		pp->cfg1_base &= CPU_TO_BUS_ADDR;
 	}
 
 	dra7xx_pcie_establish_link(pp);
@@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
 
 	pp = &dra7xx->pp;
 	pp->dev = dev;
+	pp->root_bus_nr = 0;
 	pp->ops = &dra7xx_pcie_host_ops;
 
 	pp->irq = platform_get_irq(pdev, 1);
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
index f9f468d..9771bb0 100644
--- a/drivers/pci/host/pci-exynos.c
+++ b/drivers/pci/host/pci-exynos.c
@@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &exynos_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index 233a196..bec256c 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &imx6_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c
index f34892e..b1e4135 100644
--- a/drivers/pci/host/pci-keystone-dw.c
+++ b/drivers/pci/host/pci-keystone-dw.c
@@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void __iomem *reg_virt)
 void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
 {
 	struct pcie_port *pp = &ks_pcie->pp;
-	u32 start = pp->mem.start, end = pp->mem.end;
+	u32 start = pp->mem->start, end = pp->mem->end;
 	int i, tr_size;
 
 	/* Disable BARs for inbound access */
diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
index 734da58..8113832 100644
--- a/drivers/pci/host/pci-keystone.c
+++ b/drivers/pci/host/pci-keystone.c
@@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
 			return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &keystone_pcie_host_ops;
 	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
 	if (ret) {
diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
index b2328ea1..79ff08c 100644
--- a/drivers/pci/host/pci-layerscape.c
+++ b/drivers/pci/host/pci-layerscape.c
@@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
 	pp = &pcie->pp;
 	pp->dev = pcie->dev;
 	pp->dbi_base = pcie->dbi;
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &ls_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index c5d407c..e71a88e 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/hardirq.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
@@ -69,16 +70,7 @@
 #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
 #define PCIE_ATU_UPPER_TARGET		0x91C
 
-static struct hw_pci dw_pci;
-
-static unsigned long global_io_offset;
-
-static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
-{
-	BUG_ON(!sys->private_data);
-
-	return sys->private_data;
-}
+static struct pci_ops dw_pcie_ops;
 
 int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
 {
@@ -255,7 +247,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
 static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
 {
 	int irq, pos0, i;
-	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
+	struct pcie_port *pp = desc->dev->bus->sysdata;
 
 	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
 				       order_base_2(no_irqs));
@@ -298,7 +290,7 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
 {
 	int irq, pos;
 	struct msi_msg msg;
-	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
+	struct pcie_port *pp = pdev->bus->sysdata;
 
 	if (desc->msi_attrib.is_msix)
 		return -EINVAL;
@@ -327,7 +319,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
 {
 	struct irq_data *data = irq_get_irq_data(irq);
 	struct msi_desc *msi = irq_data_get_msi(data);
-	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
+	struct pcie_port *pp = msi->dev->bus->sysdata;
 
 	clear_irq_range(pp, irq, 1, data->hwirq);
 }
@@ -363,14 +355,12 @@ int dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);
-	struct of_pci_range range;
-	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
 	struct resource *cfg_res;
-	u32 val, ns;
-	const __be32 *addrp;
-	int i, index, ret;
-
-	ns = of_n_size_cells(np);
+	LIST_HEAD(res);
+	u32 val;
+	int i, ret;
+	struct resource_entry *win;
 
 	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
 	if (cfg_res) {
@@ -378,85 +368,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
 		pp->cfg1_size = resource_size(cfg_res)/2;
 		pp->cfg0_base = cfg_res->start;
 		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
-
-		/* Find the untranslated configuration space address */
-		index = of_property_match_string(np, "reg-names", "config");
-		addrp = of_get_address(np, index, NULL, NULL);
-		pp->cfg0_mod_base = of_read_number(addrp, ns);
-		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
 	} else {
 		dev_err(pp->dev, "missing *config* reg space\n");
 	}
 
-	if (of_pci_range_parser_init(&parser, np)) {
-		dev_err(pp->dev, "missing ranges property\n");
-		return -EINVAL;
-	}
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
+	if (ret)
+		return ret;
 
 	/* Get the I/O and memory ranges from DT */
-	for_each_of_pci_range(&parser, &range) {
-		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
-
-		if (restype == IORESOURCE_IO) {
-			of_pci_range_to_resource(&range, np, &pp->io);
-			pp->io.name = "I/O";
-			pp->io.start = max_t(resource_size_t,
-					     PCIBIOS_MIN_IO,
-					     range.pci_addr + global_io_offset);
-			pp->io.end = min_t(resource_size_t,
-					   IO_SPACE_LIMIT,
-					   range.pci_addr + range.size
-					   + global_io_offset - 1);
-			pp->io_size = resource_size(&pp->io);
-			pp->io_bus_addr = range.pci_addr;
-			pp->io_base = range.cpu_addr;
-
-			/* Find the untranslated IO space address */
-			pp->io_mod_base = range.cpu_addr;
-		}
-		if (restype == IORESOURCE_MEM) {
-			of_pci_range_to_resource(&range, np, &pp->mem);
-			pp->mem.name = "MEM";
-			pp->mem_size = resource_size(&pp->mem);
-			pp->mem_bus_addr = range.pci_addr;
-
-			/* Find the untranslated MEM space address */
-			pp->mem_mod_base = range.cpu_addr;
-		}
-		if (restype == 0) {
-			of_pci_range_to_resource(&range, np, &pp->cfg);
-			pp->cfg0_size = resource_size(&pp->cfg)/2;
-			pp->cfg1_size = resource_size(&pp->cfg)/2;
-			pp->cfg0_base = pp->cfg.start;
-			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
-
-			/* Find the untranslated configuration space address */
-			pp->cfg0_mod_base = range.cpu_addr;
-			pp->cfg1_mod_base = pp->cfg0_mod_base +
-					    pp->cfg0_size;
+	resource_list_for_each_entry(win, &res) {
+		switch (resource_type(win->res)) {
+		case IORESOURCE_IO:
+			pp->io = win->res;
+			pp->io->name = "I/O";
+			pp->io_size = resource_size(pp->io);
+			pp->io_bus_addr = pp->io->start - win->offset;
+			ret = pci_remap_iospace(pp->io, pp->io_base);
+			if (ret) {
+				dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
+					 ret, pp->io);
+				continue;
+			}
+			break;
+		case IORESOURCE_MEM:
+			pp->mem = win->res;
+			pp->mem->name = "MEM";
+			pp->mem_size = resource_size(pp->mem);
+			pp->mem_bus_addr = pp->mem->start - win->offset;
+			break;
+		case 0:
+			pp->cfg = win->res;
+			pp->cfg0_size = resource_size(pp->cfg)/2;
+			pp->cfg1_size = resource_size(pp->cfg)/2;
+			pp->cfg0_base = pp->cfg->start;
+			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
+			break;
+		case IORESOURCE_BUS:
+			pp->busn = win->res;
+			break;
+		default:
+			continue;
 		}
 	}
 
-	ret = of_pci_parse_bus_range(np, &pp->busn);
-	if (ret < 0) {
-		pp->busn.name = np->name;
-		pp->busn.start = 0;
-		pp->busn.end = 0xff;
-		pp->busn.flags = IORESOURCE_BUS;
-		dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n",
-			ret, &pp->busn);
-	}
-
 	if (!pp->dbi_base) {
-		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
-					resource_size(&pp->cfg));
+		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
+					resource_size(pp->cfg));
 		if (!pp->dbi_base) {
 			dev_err(pp->dev, "error with ioremap\n");
 			return -ENOMEM;
 		}
 	}
 
-	pp->mem_base = pp->mem.start;
+	pp->mem_base = pp->mem->start;
 
 	if (!pp->va_cfg0_base) {
 		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
@@ -505,7 +470,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
 
 	if (!pp->ops->rd_other_conf)
 		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
-					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
+					  PCIE_ATU_TYPE_MEM, pp->mem_base,
 					  pp->mem_bus_addr, pp->mem_size);
 
 	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
@@ -517,15 +482,29 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	val |= PORT_LOGIC_SPEED_CHANGE;
 	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+				  pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
+#else
 	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
+
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
 
-	pci_common_init_dev(pp->dev, &dw_pci);
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -544,12 +523,12 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 
 	if (bus->parent->number == pp->root_bus_nr) {
 		type = PCIE_ATU_TYPE_CFG0;
-		cpu_addr = pp->cfg0_mod_base;
+		cpu_addr = pp->cfg0_base;
 		cfg_size = pp->cfg0_size;
 		va_cfg_base = pp->va_cfg0_base;
 	} else {
 		type = PCIE_ATU_TYPE_CFG1;
-		cpu_addr = pp->cfg1_mod_base;
+		cpu_addr = pp->cfg1_base;
 		cfg_size = pp->cfg1_size;
 		va_cfg_base = pp->va_cfg1_base;
 	}
@@ -559,7 +538,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 				  busdev, cfg_size);
 	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
 	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
-				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
+				  PCIE_ATU_TYPE_IO, pp->io_base,
 				  pp->io_bus_addr, pp->io_size);
 
 	return ret;
@@ -579,12 +558,12 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 
 	if (bus->parent->number == pp->root_bus_nr) {
 		type = PCIE_ATU_TYPE_CFG0;
-		cpu_addr = pp->cfg0_mod_base;
+		cpu_addr = pp->cfg0_base;
 		cfg_size = pp->cfg0_size;
 		va_cfg_base = pp->va_cfg0_base;
 	} else {
 		type = PCIE_ATU_TYPE_CFG1;
-		cpu_addr = pp->cfg1_mod_base;
+		cpu_addr = pp->cfg1_base;
 		cfg_size = pp->cfg1_size;
 		va_cfg_base = pp->va_cfg1_base;
 	}
@@ -594,7 +573,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 				  busdev, cfg_size);
 	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
 	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
-				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
+				  PCIE_ATU_TYPE_IO, pp->io_base,
 				  pp->io_bus_addr, pp->io_size);
 
 	return ret;
@@ -626,7 +605,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
 static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
@@ -650,7 +629,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 			int where, int size, u32 val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
@@ -674,62 +653,6 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
-{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
-{
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_scan_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;
-}
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
-	.map_irq	= dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
 	u32 val;
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
index d0bbd27..264c969 100644
--- a/drivers/pci/host/pcie-designware.h
+++ b/drivers/pci/host/pcie-designware.h
@@ -27,25 +27,21 @@ struct pcie_port {
 	u8			root_bus_nr;
 	void __iomem		*dbi_base;
 	u64			cfg0_base;
-	u64			cfg0_mod_base;
 	void __iomem		*va_cfg0_base;
 	u32			cfg0_size;
 	u64			cfg1_base;
-	u64			cfg1_mod_base;
 	void __iomem		*va_cfg1_base;
 	u32			cfg1_size;
-	u64			io_base;
-	u64			io_mod_base;
+	resource_size_t		io_base;
 	phys_addr_t		io_bus_addr;
 	u32			io_size;
 	u64			mem_base;
-	u64			mem_mod_base;
 	phys_addr_t		mem_bus_addr;
 	u32			mem_size;
-	struct resource		cfg;
-	struct resource		io;
-	struct resource		mem;
-	struct resource		busn;
+	struct resource		*cfg;
+	struct resource		*io;
+	struct resource		*mem;
+	struct resource		*busn;
 	int			irq;
 	u32			lanes;
 	struct pcie_host_ops	*ops;
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
index c49fbdc..03eb204 100644
--- a/drivers/pci/host/pcie-spear13xx.c
+++ b/drivers/pci/host/pcie-spear13xx.c
@@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
 		return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &spear13xx_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
-- 
1.9.1

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

* [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-17 11:55   ` Zhou Wang
  0 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, gabriele.paoloni, lorenzo.pieralisi,
	james.morse, Liviu.Dudau, jason, robh
  Cc: linux-pci, linux-arm-kernel, devicetree, yuanzhichang, zhudacai,
	zhangjukuo, qiuzhenfa, liudongdong3, qiujiang, xuwei5, liguozhu,
	Zhou Wang

This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete
function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci,
move related operations to dw_pcie_host_init.

In past, we use:
pci_common_init_dev
	-> pcibios_init_hw
		-> hw->scan (dw_pcie_scan_bus)
to pass 0 to root_bus_nr in struct pcie_port. This patch set pp->root_bus_nr = 0
in each PCIe host driver which is based on pcie-designware.

This patch also try to use of_pci_get_host_bridge_resources for ARM32 and ARM64
according to the suggestion for Gabriele[1]

Finally this patch reverts commit f4c55c5a3f7f "PCI: designware: Program ATU
with untranslated address" based on 1/6 in this series. we delete *_mod_base in
pcie-designware. This was discussed in [2]

I have compiled the driver with multi_v7_defconfig. However, I don't have
ARM32 PCIe related board to do test. It will be appreciated if someone could
help to test it.

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Tested-By: James Morse <james.morse@arm.com>

[1] http://www.spinics.net/lists/linux-pci/msg42194.html
[2] http://www.spinics.net/lists/arm-kernel/msg436779.html
---
 drivers/pci/host/pci-dra7xx.c      |  15 +--
 drivers/pci/host/pci-exynos.c      |   2 +-
 drivers/pci/host/pci-imx6.c        |   2 +-
 drivers/pci/host/pci-keystone-dw.c |   2 +-
 drivers/pci/host/pci-keystone.c    |   2 +-
 drivers/pci/host/pci-layerscape.c  |   2 +-
 drivers/pci/host/pcie-designware.c | 229 ++++++++++++-------------------------
 drivers/pci/host/pcie-designware.h |  14 +--
 drivers/pci/host/pcie-spear13xx.c  |   2 +-
 9 files changed, 95 insertions(+), 175 deletions(-)

diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
index 18ae7ff..1268c69 100644
--- a/drivers/pci/host/pci-dra7xx.c
+++ b/drivers/pci/host/pci-dra7xx.c
@@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp)
 {
 	dw_pcie_setup_rc(pp);
 
-	if (pp->io_mod_base)
-		pp->io_mod_base &= CPU_TO_BUS_ADDR;
+	if (pp->io_base)
+		pp->io_base &= CPU_TO_BUS_ADDR;
 
-	if (pp->mem_mod_base)
-		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
+	if (pp->mem_base)
+		pp->mem_base &= CPU_TO_BUS_ADDR;
 
-	if (pp->cfg0_mod_base) {
-		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
-		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
+	if (pp->cfg0_base) {
+		pp->cfg0_base &= CPU_TO_BUS_ADDR;
+		pp->cfg1_base &= CPU_TO_BUS_ADDR;
 	}
 
 	dra7xx_pcie_establish_link(pp);
@@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
 
 	pp = &dra7xx->pp;
 	pp->dev = dev;
+	pp->root_bus_nr = 0;
 	pp->ops = &dra7xx_pcie_host_ops;
 
 	pp->irq = platform_get_irq(pdev, 1);
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
index f9f468d..9771bb0 100644
--- a/drivers/pci/host/pci-exynos.c
+++ b/drivers/pci/host/pci-exynos.c
@@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &exynos_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index 233a196..bec256c 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &imx6_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c
index f34892e..b1e4135 100644
--- a/drivers/pci/host/pci-keystone-dw.c
+++ b/drivers/pci/host/pci-keystone-dw.c
@@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void __iomem *reg_virt)
 void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
 {
 	struct pcie_port *pp = &ks_pcie->pp;
-	u32 start = pp->mem.start, end = pp->mem.end;
+	u32 start = pp->mem->start, end = pp->mem->end;
 	int i, tr_size;
 
 	/* Disable BARs for inbound access */
diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
index 734da58..8113832 100644
--- a/drivers/pci/host/pci-keystone.c
+++ b/drivers/pci/host/pci-keystone.c
@@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
 			return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &keystone_pcie_host_ops;
 	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
 	if (ret) {
diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
index b2328ea1..79ff08c 100644
--- a/drivers/pci/host/pci-layerscape.c
+++ b/drivers/pci/host/pci-layerscape.c
@@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
 	pp = &pcie->pp;
 	pp->dev = pcie->dev;
 	pp->dbi_base = pcie->dbi;
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &ls_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index c5d407c..e71a88e 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/hardirq.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
@@ -69,16 +70,7 @@
 #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
 #define PCIE_ATU_UPPER_TARGET		0x91C
 
-static struct hw_pci dw_pci;
-
-static unsigned long global_io_offset;
-
-static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
-{
-	BUG_ON(!sys->private_data);
-
-	return sys->private_data;
-}
+static struct pci_ops dw_pcie_ops;
 
 int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
 {
@@ -255,7 +247,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
 static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
 {
 	int irq, pos0, i;
-	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
+	struct pcie_port *pp = desc->dev->bus->sysdata;
 
 	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
 				       order_base_2(no_irqs));
@@ -298,7 +290,7 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
 {
 	int irq, pos;
 	struct msi_msg msg;
-	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
+	struct pcie_port *pp = pdev->bus->sysdata;
 
 	if (desc->msi_attrib.is_msix)
 		return -EINVAL;
@@ -327,7 +319,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
 {
 	struct irq_data *data = irq_get_irq_data(irq);
 	struct msi_desc *msi = irq_data_get_msi(data);
-	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
+	struct pcie_port *pp = msi->dev->bus->sysdata;
 
 	clear_irq_range(pp, irq, 1, data->hwirq);
 }
@@ -363,14 +355,12 @@ int dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);
-	struct of_pci_range range;
-	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
 	struct resource *cfg_res;
-	u32 val, ns;
-	const __be32 *addrp;
-	int i, index, ret;
-
-	ns = of_n_size_cells(np);
+	LIST_HEAD(res);
+	u32 val;
+	int i, ret;
+	struct resource_entry *win;
 
 	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
 	if (cfg_res) {
@@ -378,85 +368,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
 		pp->cfg1_size = resource_size(cfg_res)/2;
 		pp->cfg0_base = cfg_res->start;
 		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
-
-		/* Find the untranslated configuration space address */
-		index = of_property_match_string(np, "reg-names", "config");
-		addrp = of_get_address(np, index, NULL, NULL);
-		pp->cfg0_mod_base = of_read_number(addrp, ns);
-		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
 	} else {
 		dev_err(pp->dev, "missing *config* reg space\n");
 	}
 
-	if (of_pci_range_parser_init(&parser, np)) {
-		dev_err(pp->dev, "missing ranges property\n");
-		return -EINVAL;
-	}
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
+	if (ret)
+		return ret;
 
 	/* Get the I/O and memory ranges from DT */
-	for_each_of_pci_range(&parser, &range) {
-		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
-
-		if (restype == IORESOURCE_IO) {
-			of_pci_range_to_resource(&range, np, &pp->io);
-			pp->io.name = "I/O";
-			pp->io.start = max_t(resource_size_t,
-					     PCIBIOS_MIN_IO,
-					     range.pci_addr + global_io_offset);
-			pp->io.end = min_t(resource_size_t,
-					   IO_SPACE_LIMIT,
-					   range.pci_addr + range.size
-					   + global_io_offset - 1);
-			pp->io_size = resource_size(&pp->io);
-			pp->io_bus_addr = range.pci_addr;
-			pp->io_base = range.cpu_addr;
-
-			/* Find the untranslated IO space address */
-			pp->io_mod_base = range.cpu_addr;
-		}
-		if (restype == IORESOURCE_MEM) {
-			of_pci_range_to_resource(&range, np, &pp->mem);
-			pp->mem.name = "MEM";
-			pp->mem_size = resource_size(&pp->mem);
-			pp->mem_bus_addr = range.pci_addr;
-
-			/* Find the untranslated MEM space address */
-			pp->mem_mod_base = range.cpu_addr;
-		}
-		if (restype == 0) {
-			of_pci_range_to_resource(&range, np, &pp->cfg);
-			pp->cfg0_size = resource_size(&pp->cfg)/2;
-			pp->cfg1_size = resource_size(&pp->cfg)/2;
-			pp->cfg0_base = pp->cfg.start;
-			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
-
-			/* Find the untranslated configuration space address */
-			pp->cfg0_mod_base = range.cpu_addr;
-			pp->cfg1_mod_base = pp->cfg0_mod_base +
-					    pp->cfg0_size;
+	resource_list_for_each_entry(win, &res) {
+		switch (resource_type(win->res)) {
+		case IORESOURCE_IO:
+			pp->io = win->res;
+			pp->io->name = "I/O";
+			pp->io_size = resource_size(pp->io);
+			pp->io_bus_addr = pp->io->start - win->offset;
+			ret = pci_remap_iospace(pp->io, pp->io_base);
+			if (ret) {
+				dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
+					 ret, pp->io);
+				continue;
+			}
+			break;
+		case IORESOURCE_MEM:
+			pp->mem = win->res;
+			pp->mem->name = "MEM";
+			pp->mem_size = resource_size(pp->mem);
+			pp->mem_bus_addr = pp->mem->start - win->offset;
+			break;
+		case 0:
+			pp->cfg = win->res;
+			pp->cfg0_size = resource_size(pp->cfg)/2;
+			pp->cfg1_size = resource_size(pp->cfg)/2;
+			pp->cfg0_base = pp->cfg->start;
+			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
+			break;
+		case IORESOURCE_BUS:
+			pp->busn = win->res;
+			break;
+		default:
+			continue;
 		}
 	}
 
-	ret = of_pci_parse_bus_range(np, &pp->busn);
-	if (ret < 0) {
-		pp->busn.name = np->name;
-		pp->busn.start = 0;
-		pp->busn.end = 0xff;
-		pp->busn.flags = IORESOURCE_BUS;
-		dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n",
-			ret, &pp->busn);
-	}
-
 	if (!pp->dbi_base) {
-		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
-					resource_size(&pp->cfg));
+		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
+					resource_size(pp->cfg));
 		if (!pp->dbi_base) {
 			dev_err(pp->dev, "error with ioremap\n");
 			return -ENOMEM;
 		}
 	}
 
-	pp->mem_base = pp->mem.start;
+	pp->mem_base = pp->mem->start;
 
 	if (!pp->va_cfg0_base) {
 		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
@@ -505,7 +470,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
 
 	if (!pp->ops->rd_other_conf)
 		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
-					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
+					  PCIE_ATU_TYPE_MEM, pp->mem_base,
 					  pp->mem_bus_addr, pp->mem_size);
 
 	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
@@ -517,15 +482,29 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	val |= PORT_LOGIC_SPEED_CHANGE;
 	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+				  pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
+#else
 	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
+
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
 
-	pci_common_init_dev(pp->dev, &dw_pci);
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -544,12 +523,12 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 
 	if (bus->parent->number == pp->root_bus_nr) {
 		type = PCIE_ATU_TYPE_CFG0;
-		cpu_addr = pp->cfg0_mod_base;
+		cpu_addr = pp->cfg0_base;
 		cfg_size = pp->cfg0_size;
 		va_cfg_base = pp->va_cfg0_base;
 	} else {
 		type = PCIE_ATU_TYPE_CFG1;
-		cpu_addr = pp->cfg1_mod_base;
+		cpu_addr = pp->cfg1_base;
 		cfg_size = pp->cfg1_size;
 		va_cfg_base = pp->va_cfg1_base;
 	}
@@ -559,7 +538,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 				  busdev, cfg_size);
 	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
 	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
-				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
+				  PCIE_ATU_TYPE_IO, pp->io_base,
 				  pp->io_bus_addr, pp->io_size);
 
 	return ret;
@@ -579,12 +558,12 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 
 	if (bus->parent->number == pp->root_bus_nr) {
 		type = PCIE_ATU_TYPE_CFG0;
-		cpu_addr = pp->cfg0_mod_base;
+		cpu_addr = pp->cfg0_base;
 		cfg_size = pp->cfg0_size;
 		va_cfg_base = pp->va_cfg0_base;
 	} else {
 		type = PCIE_ATU_TYPE_CFG1;
-		cpu_addr = pp->cfg1_mod_base;
+		cpu_addr = pp->cfg1_base;
 		cfg_size = pp->cfg1_size;
 		va_cfg_base = pp->va_cfg1_base;
 	}
@@ -594,7 +573,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 				  busdev, cfg_size);
 	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
 	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
-				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
+				  PCIE_ATU_TYPE_IO, pp->io_base,
 				  pp->io_bus_addr, pp->io_size);
 
 	return ret;
@@ -626,7 +605,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
 static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
@@ -650,7 +629,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 			int where, int size, u32 val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
@@ -674,62 +653,6 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
-{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
-{
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_scan_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;
-}
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
-	.map_irq	= dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
 	u32 val;
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
index d0bbd27..264c969 100644
--- a/drivers/pci/host/pcie-designware.h
+++ b/drivers/pci/host/pcie-designware.h
@@ -27,25 +27,21 @@ struct pcie_port {
 	u8			root_bus_nr;
 	void __iomem		*dbi_base;
 	u64			cfg0_base;
-	u64			cfg0_mod_base;
 	void __iomem		*va_cfg0_base;
 	u32			cfg0_size;
 	u64			cfg1_base;
-	u64			cfg1_mod_base;
 	void __iomem		*va_cfg1_base;
 	u32			cfg1_size;
-	u64			io_base;
-	u64			io_mod_base;
+	resource_size_t		io_base;
 	phys_addr_t		io_bus_addr;
 	u32			io_size;
 	u64			mem_base;
-	u64			mem_mod_base;
 	phys_addr_t		mem_bus_addr;
 	u32			mem_size;
-	struct resource		cfg;
-	struct resource		io;
-	struct resource		mem;
-	struct resource		busn;
+	struct resource		*cfg;
+	struct resource		*io;
+	struct resource		*mem;
+	struct resource		*busn;
 	int			irq;
 	u32			lanes;
 	struct pcie_host_ops	*ops;
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
index c49fbdc..03eb204 100644
--- a/drivers/pci/host/pcie-spear13xx.c
+++ b/drivers/pci/host/pcie-spear13xx.c
@@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
 		return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &spear13xx_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
-- 
1.9.1


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

* [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-17 11:55   ` Zhou Wang
  0 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: linux-arm-kernel

This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete
function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci,
move related operations to dw_pcie_host_init.

In past, we use:
pci_common_init_dev
	-> pcibios_init_hw
		-> hw->scan (dw_pcie_scan_bus)
to pass 0 to root_bus_nr in struct pcie_port. This patch set pp->root_bus_nr = 0
in each PCIe host driver which is based on pcie-designware.

This patch also try to use of_pci_get_host_bridge_resources for ARM32 and ARM64
according to the suggestion for Gabriele[1]

Finally this patch reverts commit f4c55c5a3f7f "PCI: designware: Program ATU
with untranslated address" based on 1/6 in this series. we delete *_mod_base in
pcie-designware. This was discussed in [2]

I have compiled the driver with multi_v7_defconfig. However, I don't have
ARM32 PCIe related board to do test. It will be appreciated if someone could
help to test it.

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Tested-By: James Morse <james.morse@arm.com>

[1] http://www.spinics.net/lists/linux-pci/msg42194.html
[2] http://www.spinics.net/lists/arm-kernel/msg436779.html
---
 drivers/pci/host/pci-dra7xx.c      |  15 +--
 drivers/pci/host/pci-exynos.c      |   2 +-
 drivers/pci/host/pci-imx6.c        |   2 +-
 drivers/pci/host/pci-keystone-dw.c |   2 +-
 drivers/pci/host/pci-keystone.c    |   2 +-
 drivers/pci/host/pci-layerscape.c  |   2 +-
 drivers/pci/host/pcie-designware.c | 229 ++++++++++++-------------------------
 drivers/pci/host/pcie-designware.h |  14 +--
 drivers/pci/host/pcie-spear13xx.c  |   2 +-
 9 files changed, 95 insertions(+), 175 deletions(-)

diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
index 18ae7ff..1268c69 100644
--- a/drivers/pci/host/pci-dra7xx.c
+++ b/drivers/pci/host/pci-dra7xx.c
@@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp)
 {
 	dw_pcie_setup_rc(pp);
 
-	if (pp->io_mod_base)
-		pp->io_mod_base &= CPU_TO_BUS_ADDR;
+	if (pp->io_base)
+		pp->io_base &= CPU_TO_BUS_ADDR;
 
-	if (pp->mem_mod_base)
-		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
+	if (pp->mem_base)
+		pp->mem_base &= CPU_TO_BUS_ADDR;
 
-	if (pp->cfg0_mod_base) {
-		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
-		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
+	if (pp->cfg0_base) {
+		pp->cfg0_base &= CPU_TO_BUS_ADDR;
+		pp->cfg1_base &= CPU_TO_BUS_ADDR;
 	}
 
 	dra7xx_pcie_establish_link(pp);
@@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
 
 	pp = &dra7xx->pp;
 	pp->dev = dev;
+	pp->root_bus_nr = 0;
 	pp->ops = &dra7xx_pcie_host_ops;
 
 	pp->irq = platform_get_irq(pdev, 1);
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
index f9f468d..9771bb0 100644
--- a/drivers/pci/host/pci-exynos.c
+++ b/drivers/pci/host/pci-exynos.c
@@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &exynos_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index 233a196..bec256c 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &imx6_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c
index f34892e..b1e4135 100644
--- a/drivers/pci/host/pci-keystone-dw.c
+++ b/drivers/pci/host/pci-keystone-dw.c
@@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void __iomem *reg_virt)
 void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
 {
 	struct pcie_port *pp = &ks_pcie->pp;
-	u32 start = pp->mem.start, end = pp->mem.end;
+	u32 start = pp->mem->start, end = pp->mem->end;
 	int i, tr_size;
 
 	/* Disable BARs for inbound access */
diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
index 734da58..8113832 100644
--- a/drivers/pci/host/pci-keystone.c
+++ b/drivers/pci/host/pci-keystone.c
@@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
 			return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &keystone_pcie_host_ops;
 	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
 	if (ret) {
diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
index b2328ea1..79ff08c 100644
--- a/drivers/pci/host/pci-layerscape.c
+++ b/drivers/pci/host/pci-layerscape.c
@@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
 	pp = &pcie->pp;
 	pp->dev = pcie->dev;
 	pp->dbi_base = pcie->dbi;
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &ls_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index c5d407c..e71a88e 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/hardirq.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
@@ -69,16 +70,7 @@
 #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
 #define PCIE_ATU_UPPER_TARGET		0x91C
 
-static struct hw_pci dw_pci;
-
-static unsigned long global_io_offset;
-
-static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
-{
-	BUG_ON(!sys->private_data);
-
-	return sys->private_data;
-}
+static struct pci_ops dw_pcie_ops;
 
 int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
 {
@@ -255,7 +247,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
 static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
 {
 	int irq, pos0, i;
-	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
+	struct pcie_port *pp = desc->dev->bus->sysdata;
 
 	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
 				       order_base_2(no_irqs));
@@ -298,7 +290,7 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
 {
 	int irq, pos;
 	struct msi_msg msg;
-	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
+	struct pcie_port *pp = pdev->bus->sysdata;
 
 	if (desc->msi_attrib.is_msix)
 		return -EINVAL;
@@ -327,7 +319,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
 {
 	struct irq_data *data = irq_get_irq_data(irq);
 	struct msi_desc *msi = irq_data_get_msi(data);
-	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
+	struct pcie_port *pp = msi->dev->bus->sysdata;
 
 	clear_irq_range(pp, irq, 1, data->hwirq);
 }
@@ -363,14 +355,12 @@ int dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);
-	struct of_pci_range range;
-	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
 	struct resource *cfg_res;
-	u32 val, ns;
-	const __be32 *addrp;
-	int i, index, ret;
-
-	ns = of_n_size_cells(np);
+	LIST_HEAD(res);
+	u32 val;
+	int i, ret;
+	struct resource_entry *win;
 
 	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
 	if (cfg_res) {
@@ -378,85 +368,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
 		pp->cfg1_size = resource_size(cfg_res)/2;
 		pp->cfg0_base = cfg_res->start;
 		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
-
-		/* Find the untranslated configuration space address */
-		index = of_property_match_string(np, "reg-names", "config");
-		addrp = of_get_address(np, index, NULL, NULL);
-		pp->cfg0_mod_base = of_read_number(addrp, ns);
-		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
 	} else {
 		dev_err(pp->dev, "missing *config* reg space\n");
 	}
 
-	if (of_pci_range_parser_init(&parser, np)) {
-		dev_err(pp->dev, "missing ranges property\n");
-		return -EINVAL;
-	}
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
+	if (ret)
+		return ret;
 
 	/* Get the I/O and memory ranges from DT */
-	for_each_of_pci_range(&parser, &range) {
-		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
-
-		if (restype == IORESOURCE_IO) {
-			of_pci_range_to_resource(&range, np, &pp->io);
-			pp->io.name = "I/O";
-			pp->io.start = max_t(resource_size_t,
-					     PCIBIOS_MIN_IO,
-					     range.pci_addr + global_io_offset);
-			pp->io.end = min_t(resource_size_t,
-					   IO_SPACE_LIMIT,
-					   range.pci_addr + range.size
-					   + global_io_offset - 1);
-			pp->io_size = resource_size(&pp->io);
-			pp->io_bus_addr = range.pci_addr;
-			pp->io_base = range.cpu_addr;
-
-			/* Find the untranslated IO space address */
-			pp->io_mod_base = range.cpu_addr;
-		}
-		if (restype == IORESOURCE_MEM) {
-			of_pci_range_to_resource(&range, np, &pp->mem);
-			pp->mem.name = "MEM";
-			pp->mem_size = resource_size(&pp->mem);
-			pp->mem_bus_addr = range.pci_addr;
-
-			/* Find the untranslated MEM space address */
-			pp->mem_mod_base = range.cpu_addr;
-		}
-		if (restype == 0) {
-			of_pci_range_to_resource(&range, np, &pp->cfg);
-			pp->cfg0_size = resource_size(&pp->cfg)/2;
-			pp->cfg1_size = resource_size(&pp->cfg)/2;
-			pp->cfg0_base = pp->cfg.start;
-			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
-
-			/* Find the untranslated configuration space address */
-			pp->cfg0_mod_base = range.cpu_addr;
-			pp->cfg1_mod_base = pp->cfg0_mod_base +
-					    pp->cfg0_size;
+	resource_list_for_each_entry(win, &res) {
+		switch (resource_type(win->res)) {
+		case IORESOURCE_IO:
+			pp->io = win->res;
+			pp->io->name = "I/O";
+			pp->io_size = resource_size(pp->io);
+			pp->io_bus_addr = pp->io->start - win->offset;
+			ret = pci_remap_iospace(pp->io, pp->io_base);
+			if (ret) {
+				dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
+					 ret, pp->io);
+				continue;
+			}
+			break;
+		case IORESOURCE_MEM:
+			pp->mem = win->res;
+			pp->mem->name = "MEM";
+			pp->mem_size = resource_size(pp->mem);
+			pp->mem_bus_addr = pp->mem->start - win->offset;
+			break;
+		case 0:
+			pp->cfg = win->res;
+			pp->cfg0_size = resource_size(pp->cfg)/2;
+			pp->cfg1_size = resource_size(pp->cfg)/2;
+			pp->cfg0_base = pp->cfg->start;
+			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
+			break;
+		case IORESOURCE_BUS:
+			pp->busn = win->res;
+			break;
+		default:
+			continue;
 		}
 	}
 
-	ret = of_pci_parse_bus_range(np, &pp->busn);
-	if (ret < 0) {
-		pp->busn.name = np->name;
-		pp->busn.start = 0;
-		pp->busn.end = 0xff;
-		pp->busn.flags = IORESOURCE_BUS;
-		dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n",
-			ret, &pp->busn);
-	}
-
 	if (!pp->dbi_base) {
-		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
-					resource_size(&pp->cfg));
+		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
+					resource_size(pp->cfg));
 		if (!pp->dbi_base) {
 			dev_err(pp->dev, "error with ioremap\n");
 			return -ENOMEM;
 		}
 	}
 
-	pp->mem_base = pp->mem.start;
+	pp->mem_base = pp->mem->start;
 
 	if (!pp->va_cfg0_base) {
 		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
@@ -505,7 +470,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
 
 	if (!pp->ops->rd_other_conf)
 		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
-					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
+					  PCIE_ATU_TYPE_MEM, pp->mem_base,
 					  pp->mem_bus_addr, pp->mem_size);
 
 	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
@@ -517,15 +482,29 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	val |= PORT_LOGIC_SPEED_CHANGE;
 	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
+	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+				  pp, &res);
+	if (!bus)
+		return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
+#else
 	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
+
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
 
-	pci_common_init_dev(pp->dev, &dw_pci);
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -544,12 +523,12 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 
 	if (bus->parent->number == pp->root_bus_nr) {
 		type = PCIE_ATU_TYPE_CFG0;
-		cpu_addr = pp->cfg0_mod_base;
+		cpu_addr = pp->cfg0_base;
 		cfg_size = pp->cfg0_size;
 		va_cfg_base = pp->va_cfg0_base;
 	} else {
 		type = PCIE_ATU_TYPE_CFG1;
-		cpu_addr = pp->cfg1_mod_base;
+		cpu_addr = pp->cfg1_base;
 		cfg_size = pp->cfg1_size;
 		va_cfg_base = pp->va_cfg1_base;
 	}
@@ -559,7 +538,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 				  busdev, cfg_size);
 	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
 	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
-				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
+				  PCIE_ATU_TYPE_IO, pp->io_base,
 				  pp->io_bus_addr, pp->io_size);
 
 	return ret;
@@ -579,12 +558,12 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 
 	if (bus->parent->number == pp->root_bus_nr) {
 		type = PCIE_ATU_TYPE_CFG0;
-		cpu_addr = pp->cfg0_mod_base;
+		cpu_addr = pp->cfg0_base;
 		cfg_size = pp->cfg0_size;
 		va_cfg_base = pp->va_cfg0_base;
 	} else {
 		type = PCIE_ATU_TYPE_CFG1;
-		cpu_addr = pp->cfg1_mod_base;
+		cpu_addr = pp->cfg1_base;
 		cfg_size = pp->cfg1_size;
 		va_cfg_base = pp->va_cfg1_base;
 	}
@@ -594,7 +573,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 				  busdev, cfg_size);
 	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
 	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
-				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
+				  PCIE_ATU_TYPE_IO, pp->io_base,
 				  pp->io_bus_addr, pp->io_size);
 
 	return ret;
@@ -626,7 +605,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
 static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
@@ -650,7 +629,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 			int where, int size, u32 val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
@@ -674,62 +653,6 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
-{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
-{
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_scan_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;
-}
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
-	.map_irq	= dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
 	u32 val;
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
index d0bbd27..264c969 100644
--- a/drivers/pci/host/pcie-designware.h
+++ b/drivers/pci/host/pcie-designware.h
@@ -27,25 +27,21 @@ struct pcie_port {
 	u8			root_bus_nr;
 	void __iomem		*dbi_base;
 	u64			cfg0_base;
-	u64			cfg0_mod_base;
 	void __iomem		*va_cfg0_base;
 	u32			cfg0_size;
 	u64			cfg1_base;
-	u64			cfg1_mod_base;
 	void __iomem		*va_cfg1_base;
 	u32			cfg1_size;
-	u64			io_base;
-	u64			io_mod_base;
+	resource_size_t		io_base;
 	phys_addr_t		io_bus_addr;
 	u32			io_size;
 	u64			mem_base;
-	u64			mem_mod_base;
 	phys_addr_t		mem_bus_addr;
 	u32			mem_size;
-	struct resource		cfg;
-	struct resource		io;
-	struct resource		mem;
-	struct resource		busn;
+	struct resource		*cfg;
+	struct resource		*io;
+	struct resource		*mem;
+	struct resource		*busn;
 	int			irq;
 	u32			lanes;
 	struct pcie_host_ops	*ops;
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
index c49fbdc..03eb204 100644
--- a/drivers/pci/host/pcie-spear13xx.c
+++ b/drivers/pci/host/pcie-spear13xx.c
@@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
 		return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = 0;
 	pp->ops = &spear13xx_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
-- 
1.9.1

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

* [PATCH v7 4/6] PCI: hisi: Add PCIe host support for HiSilicon SoC Hip05
  2015-08-17 11:55 ` Zhou Wang
  (?)
@ 2015-08-17 11:55   ` Zhou Wang
  -1 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, gabriele.paoloni, lorenzo.pieralisi,
	james.morse, Liviu.Dudau, jason, robh
  Cc: linux-pci, linux-arm-kernel, devicetree, yuanzhichang, zhudacai,
	zhangjukuo, qiuzhenfa, liudongdong3, qiujiang, xuwei5, liguozhu,
	Zhou Wang

This patch adds PCIe host support for HiSilicon SoC Hip05.

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
---
 drivers/pci/host/Kconfig     |   8 ++
 drivers/pci/host/Makefile    |   1 +
 drivers/pci/host/pcie-hisi.c | 254 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 263 insertions(+)
 create mode 100644 drivers/pci/host/pcie-hisi.c

diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index c132bdd..cd2b80b 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -145,4 +145,12 @@ config PCIE_IPROC_BCMA
 	  Say Y here if you want to use the Broadcom iProc PCIe controller
 	  through the BCMA bus interface
 
+config PCI_HISI
+	depends on OF && ARM64
+	bool "HiSilicon SoC HIP05 PCIe controller"
+	select PCIEPORTBUS
+	select PCIE_DW
+	help
+	  Say Y here if you want PCIe controller support on HiSilicon HIP05 SoC
+
 endmenu
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index 140d66f..ea1dbf2 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
 obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o
 obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o
 obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o
+obj-$(CONFIG_PCI_HISI) += pcie-hisi.o
diff --git a/drivers/pci/host/pcie-hisi.c b/drivers/pci/host/pcie-hisi.c
new file mode 100644
index 0000000..7dcacf1
--- /dev/null
+++ b/drivers/pci/host/pcie-hisi.c
@@ -0,0 +1,254 @@
+/*
+ * PCIe host controller driver for HiSilicon Hip05 SoC
+ *
+ * Copyright (C) 2015 HiSilicon Co., Ltd. http://www.hisilicon.com
+ *
+ * Author: Zhou Wang <wangzhou1@hisilicon.com>
+ *         Dacai Zhu <zhudacai@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_pci.h>
+#include <linux/platform_device.h>
+
+#include "pcie-designware.h"
+
+#define PCIE_SUBCTRL_MODE_REG                           0x2800
+#define PCIE_SUBCTRL_SYS_STATE4_REG                     0x6818
+#define PCIE_SLV_DBI_MODE                               0x0
+#define PCIE_SLV_SYSCTRL_MODE                           0x1
+#define PCIE_SLV_CONTENT_MODE                           0x2
+#define PCIE_SLV_MSI_ASID                               0x10
+#define PCIE_LTSSM_LINKUP_STATE                         0x11
+#define PCIE_LTSSM_STATE_MASK                           0x3F
+#define PCIE_MSI_ASID_ENABLE                            (0x1 << 12)
+#define PCIE_MSI_ASID_VALUE                             (0x1 << 16)
+#define PCIE_MSI_TRANS_ENABLE                           (0x1 << 12)
+#define PCIE_MSI_TRANS_REG                              0x1c8
+#define PCIE_MSI_LOW_ADDRESS                            0x1b4
+#define PCIE_MSI_HIGH_ADDRESS                           0x1c4
+#define PCIE_MSI_ADDRESS_VAL                            0xb7010040
+
+#define to_hisi_pcie(x)	container_of(x, struct hisi_pcie, pp)
+
+struct hisi_pcie {
+	void __iomem *subctrl_base;
+	void __iomem *reg_base;
+	struct msi_controller *msi;
+	u32 port_id;
+	struct pcie_port pp;
+};
+
+static inline void hisi_pcie_subctrl_writel(struct hisi_pcie *pcie,
+					    u32 val, u32 reg)
+{
+	writel(val, pcie->subctrl_base + reg);
+}
+
+static inline u32 hisi_pcie_subctrl_readl(struct hisi_pcie *pcie, u32 reg)
+{
+	return readl(pcie->subctrl_base + reg);
+}
+
+static inline void hisi_pcie_apb_writel(struct hisi_pcie *pcie,
+					u32 val, u32 reg)
+{
+	writel(val, pcie->reg_base + reg);
+}
+
+static inline u32 hisi_pcie_apb_readl(struct hisi_pcie *pcie, u32 reg)
+{
+	return readl(pcie->reg_base + reg);
+}
+
+/*
+ * Change mode to indicate the same reg_base to base of PCIe host configure
+ * registers, base of RC configure space or base of vmid/asid context table
+ */
+static void hisi_pcie_change_apb_mode(struct hisi_pcie *pcie, u32 mode)
+{
+	u32 val;
+	u32 bit_mask;
+	u32 bit_shift;
+	u32 port_id = pcie->port_id;
+	u32 reg = PCIE_SUBCTRL_MODE_REG + 0x100 * port_id;
+
+	if ((port_id == 1) || (port_id == 2)) {
+		bit_mask = 0xc;
+		bit_shift = 0x2;
+	} else {
+		bit_mask = 0x6;
+		bit_shift = 0x1;
+	}
+
+	val = hisi_pcie_subctrl_readl(pcie, reg);
+	val = (val & (~bit_mask)) | (mode << bit_shift);
+	hisi_pcie_subctrl_writel(pcie, val, reg);
+}
+
+/* Configure vmid/asid table in PCIe host */
+static void hisi_pcie_config_context(struct hisi_pcie *pcie)
+{
+	int i;
+
+	hisi_pcie_change_apb_mode(pcie, PCIE_SLV_CONTENT_MODE);
+
+	/*
+	 * init vmid and asid tables for all PCIe devices as 0
+	 * vmid table: 0 ~ 0x3ff, asid table: 0x400 ~ 0x7ff
+	 */
+	for (i = 0; i < 0x800; i++)
+		hisi_pcie_apb_writel(pcie, 0x0, i * 4);
+
+	hisi_pcie_change_apb_mode(pcie, PCIE_SLV_SYSCTRL_MODE);
+
+	hisi_pcie_apb_writel(pcie, PCIE_MSI_ADDRESS_VAL, PCIE_MSI_LOW_ADDRESS);
+	hisi_pcie_apb_writel(pcie, 0x0, PCIE_MSI_HIGH_ADDRESS);
+	hisi_pcie_apb_writel(pcie, PCIE_MSI_ASID_ENABLE | PCIE_MSI_ASID_VALUE,
+			     PCIE_SLV_MSI_ASID);
+	hisi_pcie_apb_writel(pcie, PCIE_MSI_TRANS_ENABLE, PCIE_MSI_TRANS_REG);
+
+	hisi_pcie_change_apb_mode(pcie, PCIE_SLV_DBI_MODE);
+}
+
+static int hisi_pcie_link_up(struct pcie_port *pp)
+{
+	u32 val;
+	struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
+
+	val = hisi_pcie_subctrl_readl(hisi_pcie, PCIE_SUBCTRL_SYS_STATE4_REG +
+				      0x100 * hisi_pcie->port_id);
+
+	return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE);
+}
+
+static
+int hisi_pcie_msi_host_init(struct pcie_port *pp, struct msi_controller *chip)
+{
+	struct device_node *msi_node;
+	struct irq_domain *irq_domain;
+	struct device_node *np = pp->dev->of_node;
+
+	msi_node = of_parse_phandle(np, "msi-parent", 0);
+	if (!msi_node) {
+		dev_err(pp->dev, "failed to find msi-parent\n");
+		return -ENODEV;
+	}
+
+	irq_domain = irq_find_host(msi_node);
+	if (!irq_domain) {
+		dev_err(pp->dev, "failed to find irq domain\n");
+		return -ENODEV;
+	}
+
+	pp->irq_domain = irq_domain;
+
+	return 0;
+}
+
+static struct pcie_host_ops hisi_pcie_host_ops = {
+	.link_up = hisi_pcie_link_up,
+	.msi_host_init = hisi_pcie_msi_host_init,
+};
+
+static int __init hisi_add_pcie_port(struct pcie_port *pp,
+				     struct platform_device *pdev)
+{
+	int ret;
+	u32 port_id;
+	struct resource busn;
+	struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
+
+	if (of_property_read_u32(pdev->dev.of_node, "port-id", &port_id)) {
+		dev_err(&pdev->dev, "failed to read port-id\n");
+		return -EINVAL;
+	}
+	if (port_id > 3) {
+		dev_err(&pdev->dev, "Invalid port-id: %d\n", port_id);
+		return -EINVAL;
+	}
+
+	hisi_pcie->port_id = port_id;
+
+	if (of_pci_parse_bus_range(pdev->dev.of_node, &busn)) {
+		dev_err(&pdev->dev, "failed to parse bus-ranges\n");
+		return -EINVAL;
+	}
+
+	pp->root_bus_nr = busn.start;
+	pp->ops = &hisi_pcie_host_ops;
+
+	hisi_pcie_config_context(hisi_pcie);
+
+	ret = dw_pcie_host_init(pp);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to initialize host\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int __init hisi_pcie_probe(struct platform_device *pdev)
+{
+	struct hisi_pcie *hisi_pcie;
+	struct pcie_port *pp;
+	struct resource *reg;
+	struct resource *subctrl;
+	int ret;
+
+	hisi_pcie = devm_kzalloc(&pdev->dev, sizeof(*hisi_pcie), GFP_KERNEL);
+	if (!hisi_pcie)
+		return -ENOMEM;
+
+	pp = &hisi_pcie->pp;
+	pp->dev = &pdev->dev;
+
+	subctrl = platform_get_resource_byname(pdev, IORESOURCE_MEM, "subctrl");
+	hisi_pcie->subctrl_base = devm_ioremap_nocache(&pdev->dev,
+					subctrl->start, resource_size(subctrl));
+	if (IS_ERR(hisi_pcie->subctrl_base)) {
+		dev_err(pp->dev, "cannot get subctrl base\n");
+		return PTR_ERR(hisi_pcie->subctrl_base);
+	}
+
+	reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbi");
+	hisi_pcie->reg_base = devm_ioremap_resource(&pdev->dev, reg);
+	if (IS_ERR(hisi_pcie->reg_base)) {
+		dev_err(pp->dev, "cannot get rc_dbi base\n");
+		return PTR_ERR(hisi_pcie->reg_base);
+	}
+
+	hisi_pcie->pp.dbi_base = hisi_pcie->reg_base;
+
+	ret = hisi_add_pcie_port(pp, pdev);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, hisi_pcie);
+
+	return 0;
+}
+
+static const struct of_device_id hisi_pcie_of_match[] = {
+	{.compatible = "hisilicon,hip05-pcie",},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, hisi_pcie_of_match);
+
+static struct platform_driver hisi_pcie_driver = {
+	.probe  = hisi_pcie_probe,
+	.driver = {
+		   .name = "hisi-pcie",
+		   .of_match_table = hisi_pcie_of_match,
+	},
+};
+
+module_platform_driver(hisi_pcie_driver);
-- 
1.9.1

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

* [PATCH v7 4/6] PCI: hisi: Add PCIe host support for HiSilicon SoC Hip05
@ 2015-08-17 11:55   ` Zhou Wang
  0 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, gabriele.paoloni, lorenzo.pieralisi,
	james.morse, Liviu.Dudau, jason, robh
  Cc: linux-pci, linux-arm-kernel, devicetree, yuanzhichang, zhudacai,
	zhangjukuo, qiuzhenfa, liudongdong3, qiujiang, xuwei5, liguozhu,
	Zhou Wang

This patch adds PCIe host support for HiSilicon SoC Hip05.

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
---
 drivers/pci/host/Kconfig     |   8 ++
 drivers/pci/host/Makefile    |   1 +
 drivers/pci/host/pcie-hisi.c | 254 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 263 insertions(+)
 create mode 100644 drivers/pci/host/pcie-hisi.c

diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index c132bdd..cd2b80b 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -145,4 +145,12 @@ config PCIE_IPROC_BCMA
 	  Say Y here if you want to use the Broadcom iProc PCIe controller
 	  through the BCMA bus interface
 
+config PCI_HISI
+	depends on OF && ARM64
+	bool "HiSilicon SoC HIP05 PCIe controller"
+	select PCIEPORTBUS
+	select PCIE_DW
+	help
+	  Say Y here if you want PCIe controller support on HiSilicon HIP05 SoC
+
 endmenu
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index 140d66f..ea1dbf2 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
 obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o
 obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o
 obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o
+obj-$(CONFIG_PCI_HISI) += pcie-hisi.o
diff --git a/drivers/pci/host/pcie-hisi.c b/drivers/pci/host/pcie-hisi.c
new file mode 100644
index 0000000..7dcacf1
--- /dev/null
+++ b/drivers/pci/host/pcie-hisi.c
@@ -0,0 +1,254 @@
+/*
+ * PCIe host controller driver for HiSilicon Hip05 SoC
+ *
+ * Copyright (C) 2015 HiSilicon Co., Ltd. http://www.hisilicon.com
+ *
+ * Author: Zhou Wang <wangzhou1@hisilicon.com>
+ *         Dacai Zhu <zhudacai@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_pci.h>
+#include <linux/platform_device.h>
+
+#include "pcie-designware.h"
+
+#define PCIE_SUBCTRL_MODE_REG                           0x2800
+#define PCIE_SUBCTRL_SYS_STATE4_REG                     0x6818
+#define PCIE_SLV_DBI_MODE                               0x0
+#define PCIE_SLV_SYSCTRL_MODE                           0x1
+#define PCIE_SLV_CONTENT_MODE                           0x2
+#define PCIE_SLV_MSI_ASID                               0x10
+#define PCIE_LTSSM_LINKUP_STATE                         0x11
+#define PCIE_LTSSM_STATE_MASK                           0x3F
+#define PCIE_MSI_ASID_ENABLE                            (0x1 << 12)
+#define PCIE_MSI_ASID_VALUE                             (0x1 << 16)
+#define PCIE_MSI_TRANS_ENABLE                           (0x1 << 12)
+#define PCIE_MSI_TRANS_REG                              0x1c8
+#define PCIE_MSI_LOW_ADDRESS                            0x1b4
+#define PCIE_MSI_HIGH_ADDRESS                           0x1c4
+#define PCIE_MSI_ADDRESS_VAL                            0xb7010040
+
+#define to_hisi_pcie(x)	container_of(x, struct hisi_pcie, pp)
+
+struct hisi_pcie {
+	void __iomem *subctrl_base;
+	void __iomem *reg_base;
+	struct msi_controller *msi;
+	u32 port_id;
+	struct pcie_port pp;
+};
+
+static inline void hisi_pcie_subctrl_writel(struct hisi_pcie *pcie,
+					    u32 val, u32 reg)
+{
+	writel(val, pcie->subctrl_base + reg);
+}
+
+static inline u32 hisi_pcie_subctrl_readl(struct hisi_pcie *pcie, u32 reg)
+{
+	return readl(pcie->subctrl_base + reg);
+}
+
+static inline void hisi_pcie_apb_writel(struct hisi_pcie *pcie,
+					u32 val, u32 reg)
+{
+	writel(val, pcie->reg_base + reg);
+}
+
+static inline u32 hisi_pcie_apb_readl(struct hisi_pcie *pcie, u32 reg)
+{
+	return readl(pcie->reg_base + reg);
+}
+
+/*
+ * Change mode to indicate the same reg_base to base of PCIe host configure
+ * registers, base of RC configure space or base of vmid/asid context table
+ */
+static void hisi_pcie_change_apb_mode(struct hisi_pcie *pcie, u32 mode)
+{
+	u32 val;
+	u32 bit_mask;
+	u32 bit_shift;
+	u32 port_id = pcie->port_id;
+	u32 reg = PCIE_SUBCTRL_MODE_REG + 0x100 * port_id;
+
+	if ((port_id == 1) || (port_id == 2)) {
+		bit_mask = 0xc;
+		bit_shift = 0x2;
+	} else {
+		bit_mask = 0x6;
+		bit_shift = 0x1;
+	}
+
+	val = hisi_pcie_subctrl_readl(pcie, reg);
+	val = (val & (~bit_mask)) | (mode << bit_shift);
+	hisi_pcie_subctrl_writel(pcie, val, reg);
+}
+
+/* Configure vmid/asid table in PCIe host */
+static void hisi_pcie_config_context(struct hisi_pcie *pcie)
+{
+	int i;
+
+	hisi_pcie_change_apb_mode(pcie, PCIE_SLV_CONTENT_MODE);
+
+	/*
+	 * init vmid and asid tables for all PCIe devices as 0
+	 * vmid table: 0 ~ 0x3ff, asid table: 0x400 ~ 0x7ff
+	 */
+	for (i = 0; i < 0x800; i++)
+		hisi_pcie_apb_writel(pcie, 0x0, i * 4);
+
+	hisi_pcie_change_apb_mode(pcie, PCIE_SLV_SYSCTRL_MODE);
+
+	hisi_pcie_apb_writel(pcie, PCIE_MSI_ADDRESS_VAL, PCIE_MSI_LOW_ADDRESS);
+	hisi_pcie_apb_writel(pcie, 0x0, PCIE_MSI_HIGH_ADDRESS);
+	hisi_pcie_apb_writel(pcie, PCIE_MSI_ASID_ENABLE | PCIE_MSI_ASID_VALUE,
+			     PCIE_SLV_MSI_ASID);
+	hisi_pcie_apb_writel(pcie, PCIE_MSI_TRANS_ENABLE, PCIE_MSI_TRANS_REG);
+
+	hisi_pcie_change_apb_mode(pcie, PCIE_SLV_DBI_MODE);
+}
+
+static int hisi_pcie_link_up(struct pcie_port *pp)
+{
+	u32 val;
+	struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
+
+	val = hisi_pcie_subctrl_readl(hisi_pcie, PCIE_SUBCTRL_SYS_STATE4_REG +
+				      0x100 * hisi_pcie->port_id);
+
+	return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE);
+}
+
+static
+int hisi_pcie_msi_host_init(struct pcie_port *pp, struct msi_controller *chip)
+{
+	struct device_node *msi_node;
+	struct irq_domain *irq_domain;
+	struct device_node *np = pp->dev->of_node;
+
+	msi_node = of_parse_phandle(np, "msi-parent", 0);
+	if (!msi_node) {
+		dev_err(pp->dev, "failed to find msi-parent\n");
+		return -ENODEV;
+	}
+
+	irq_domain = irq_find_host(msi_node);
+	if (!irq_domain) {
+		dev_err(pp->dev, "failed to find irq domain\n");
+		return -ENODEV;
+	}
+
+	pp->irq_domain = irq_domain;
+
+	return 0;
+}
+
+static struct pcie_host_ops hisi_pcie_host_ops = {
+	.link_up = hisi_pcie_link_up,
+	.msi_host_init = hisi_pcie_msi_host_init,
+};
+
+static int __init hisi_add_pcie_port(struct pcie_port *pp,
+				     struct platform_device *pdev)
+{
+	int ret;
+	u32 port_id;
+	struct resource busn;
+	struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
+
+	if (of_property_read_u32(pdev->dev.of_node, "port-id", &port_id)) {
+		dev_err(&pdev->dev, "failed to read port-id\n");
+		return -EINVAL;
+	}
+	if (port_id > 3) {
+		dev_err(&pdev->dev, "Invalid port-id: %d\n", port_id);
+		return -EINVAL;
+	}
+
+	hisi_pcie->port_id = port_id;
+
+	if (of_pci_parse_bus_range(pdev->dev.of_node, &busn)) {
+		dev_err(&pdev->dev, "failed to parse bus-ranges\n");
+		return -EINVAL;
+	}
+
+	pp->root_bus_nr = busn.start;
+	pp->ops = &hisi_pcie_host_ops;
+
+	hisi_pcie_config_context(hisi_pcie);
+
+	ret = dw_pcie_host_init(pp);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to initialize host\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int __init hisi_pcie_probe(struct platform_device *pdev)
+{
+	struct hisi_pcie *hisi_pcie;
+	struct pcie_port *pp;
+	struct resource *reg;
+	struct resource *subctrl;
+	int ret;
+
+	hisi_pcie = devm_kzalloc(&pdev->dev, sizeof(*hisi_pcie), GFP_KERNEL);
+	if (!hisi_pcie)
+		return -ENOMEM;
+
+	pp = &hisi_pcie->pp;
+	pp->dev = &pdev->dev;
+
+	subctrl = platform_get_resource_byname(pdev, IORESOURCE_MEM, "subctrl");
+	hisi_pcie->subctrl_base = devm_ioremap_nocache(&pdev->dev,
+					subctrl->start, resource_size(subctrl));
+	if (IS_ERR(hisi_pcie->subctrl_base)) {
+		dev_err(pp->dev, "cannot get subctrl base\n");
+		return PTR_ERR(hisi_pcie->subctrl_base);
+	}
+
+	reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbi");
+	hisi_pcie->reg_base = devm_ioremap_resource(&pdev->dev, reg);
+	if (IS_ERR(hisi_pcie->reg_base)) {
+		dev_err(pp->dev, "cannot get rc_dbi base\n");
+		return PTR_ERR(hisi_pcie->reg_base);
+	}
+
+	hisi_pcie->pp.dbi_base = hisi_pcie->reg_base;
+
+	ret = hisi_add_pcie_port(pp, pdev);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, hisi_pcie);
+
+	return 0;
+}
+
+static const struct of_device_id hisi_pcie_of_match[] = {
+	{.compatible = "hisilicon,hip05-pcie",},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, hisi_pcie_of_match);
+
+static struct platform_driver hisi_pcie_driver = {
+	.probe  = hisi_pcie_probe,
+	.driver = {
+		   .name = "hisi-pcie",
+		   .of_match_table = hisi_pcie_of_match,
+	},
+};
+
+module_platform_driver(hisi_pcie_driver);
-- 
1.9.1


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

* [PATCH v7 4/6] PCI: hisi: Add PCIe host support for HiSilicon SoC Hip05
@ 2015-08-17 11:55   ` Zhou Wang
  0 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds PCIe host support for HiSilicon SoC Hip05.

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
---
 drivers/pci/host/Kconfig     |   8 ++
 drivers/pci/host/Makefile    |   1 +
 drivers/pci/host/pcie-hisi.c | 254 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 263 insertions(+)
 create mode 100644 drivers/pci/host/pcie-hisi.c

diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index c132bdd..cd2b80b 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -145,4 +145,12 @@ config PCIE_IPROC_BCMA
 	  Say Y here if you want to use the Broadcom iProc PCIe controller
 	  through the BCMA bus interface
 
+config PCI_HISI
+	depends on OF && ARM64
+	bool "HiSilicon SoC HIP05 PCIe controller"
+	select PCIEPORTBUS
+	select PCIE_DW
+	help
+	  Say Y here if you want PCIe controller support on HiSilicon HIP05 SoC
+
 endmenu
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index 140d66f..ea1dbf2 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
 obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o
 obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o
 obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o
+obj-$(CONFIG_PCI_HISI) += pcie-hisi.o
diff --git a/drivers/pci/host/pcie-hisi.c b/drivers/pci/host/pcie-hisi.c
new file mode 100644
index 0000000..7dcacf1
--- /dev/null
+++ b/drivers/pci/host/pcie-hisi.c
@@ -0,0 +1,254 @@
+/*
+ * PCIe host controller driver for HiSilicon Hip05 SoC
+ *
+ * Copyright (C) 2015 HiSilicon Co., Ltd. http://www.hisilicon.com
+ *
+ * Author: Zhou Wang <wangzhou1@hisilicon.com>
+ *         Dacai Zhu <zhudacai@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_pci.h>
+#include <linux/platform_device.h>
+
+#include "pcie-designware.h"
+
+#define PCIE_SUBCTRL_MODE_REG                           0x2800
+#define PCIE_SUBCTRL_SYS_STATE4_REG                     0x6818
+#define PCIE_SLV_DBI_MODE                               0x0
+#define PCIE_SLV_SYSCTRL_MODE                           0x1
+#define PCIE_SLV_CONTENT_MODE                           0x2
+#define PCIE_SLV_MSI_ASID                               0x10
+#define PCIE_LTSSM_LINKUP_STATE                         0x11
+#define PCIE_LTSSM_STATE_MASK                           0x3F
+#define PCIE_MSI_ASID_ENABLE                            (0x1 << 12)
+#define PCIE_MSI_ASID_VALUE                             (0x1 << 16)
+#define PCIE_MSI_TRANS_ENABLE                           (0x1 << 12)
+#define PCIE_MSI_TRANS_REG                              0x1c8
+#define PCIE_MSI_LOW_ADDRESS                            0x1b4
+#define PCIE_MSI_HIGH_ADDRESS                           0x1c4
+#define PCIE_MSI_ADDRESS_VAL                            0xb7010040
+
+#define to_hisi_pcie(x)	container_of(x, struct hisi_pcie, pp)
+
+struct hisi_pcie {
+	void __iomem *subctrl_base;
+	void __iomem *reg_base;
+	struct msi_controller *msi;
+	u32 port_id;
+	struct pcie_port pp;
+};
+
+static inline void hisi_pcie_subctrl_writel(struct hisi_pcie *pcie,
+					    u32 val, u32 reg)
+{
+	writel(val, pcie->subctrl_base + reg);
+}
+
+static inline u32 hisi_pcie_subctrl_readl(struct hisi_pcie *pcie, u32 reg)
+{
+	return readl(pcie->subctrl_base + reg);
+}
+
+static inline void hisi_pcie_apb_writel(struct hisi_pcie *pcie,
+					u32 val, u32 reg)
+{
+	writel(val, pcie->reg_base + reg);
+}
+
+static inline u32 hisi_pcie_apb_readl(struct hisi_pcie *pcie, u32 reg)
+{
+	return readl(pcie->reg_base + reg);
+}
+
+/*
+ * Change mode to indicate the same reg_base to base of PCIe host configure
+ * registers, base of RC configure space or base of vmid/asid context table
+ */
+static void hisi_pcie_change_apb_mode(struct hisi_pcie *pcie, u32 mode)
+{
+	u32 val;
+	u32 bit_mask;
+	u32 bit_shift;
+	u32 port_id = pcie->port_id;
+	u32 reg = PCIE_SUBCTRL_MODE_REG + 0x100 * port_id;
+
+	if ((port_id == 1) || (port_id == 2)) {
+		bit_mask = 0xc;
+		bit_shift = 0x2;
+	} else {
+		bit_mask = 0x6;
+		bit_shift = 0x1;
+	}
+
+	val = hisi_pcie_subctrl_readl(pcie, reg);
+	val = (val & (~bit_mask)) | (mode << bit_shift);
+	hisi_pcie_subctrl_writel(pcie, val, reg);
+}
+
+/* Configure vmid/asid table in PCIe host */
+static void hisi_pcie_config_context(struct hisi_pcie *pcie)
+{
+	int i;
+
+	hisi_pcie_change_apb_mode(pcie, PCIE_SLV_CONTENT_MODE);
+
+	/*
+	 * init vmid and asid tables for all PCIe devices as 0
+	 * vmid table: 0 ~ 0x3ff, asid table: 0x400 ~ 0x7ff
+	 */
+	for (i = 0; i < 0x800; i++)
+		hisi_pcie_apb_writel(pcie, 0x0, i * 4);
+
+	hisi_pcie_change_apb_mode(pcie, PCIE_SLV_SYSCTRL_MODE);
+
+	hisi_pcie_apb_writel(pcie, PCIE_MSI_ADDRESS_VAL, PCIE_MSI_LOW_ADDRESS);
+	hisi_pcie_apb_writel(pcie, 0x0, PCIE_MSI_HIGH_ADDRESS);
+	hisi_pcie_apb_writel(pcie, PCIE_MSI_ASID_ENABLE | PCIE_MSI_ASID_VALUE,
+			     PCIE_SLV_MSI_ASID);
+	hisi_pcie_apb_writel(pcie, PCIE_MSI_TRANS_ENABLE, PCIE_MSI_TRANS_REG);
+
+	hisi_pcie_change_apb_mode(pcie, PCIE_SLV_DBI_MODE);
+}
+
+static int hisi_pcie_link_up(struct pcie_port *pp)
+{
+	u32 val;
+	struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
+
+	val = hisi_pcie_subctrl_readl(hisi_pcie, PCIE_SUBCTRL_SYS_STATE4_REG +
+				      0x100 * hisi_pcie->port_id);
+
+	return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE);
+}
+
+static
+int hisi_pcie_msi_host_init(struct pcie_port *pp, struct msi_controller *chip)
+{
+	struct device_node *msi_node;
+	struct irq_domain *irq_domain;
+	struct device_node *np = pp->dev->of_node;
+
+	msi_node = of_parse_phandle(np, "msi-parent", 0);
+	if (!msi_node) {
+		dev_err(pp->dev, "failed to find msi-parent\n");
+		return -ENODEV;
+	}
+
+	irq_domain = irq_find_host(msi_node);
+	if (!irq_domain) {
+		dev_err(pp->dev, "failed to find irq domain\n");
+		return -ENODEV;
+	}
+
+	pp->irq_domain = irq_domain;
+
+	return 0;
+}
+
+static struct pcie_host_ops hisi_pcie_host_ops = {
+	.link_up = hisi_pcie_link_up,
+	.msi_host_init = hisi_pcie_msi_host_init,
+};
+
+static int __init hisi_add_pcie_port(struct pcie_port *pp,
+				     struct platform_device *pdev)
+{
+	int ret;
+	u32 port_id;
+	struct resource busn;
+	struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
+
+	if (of_property_read_u32(pdev->dev.of_node, "port-id", &port_id)) {
+		dev_err(&pdev->dev, "failed to read port-id\n");
+		return -EINVAL;
+	}
+	if (port_id > 3) {
+		dev_err(&pdev->dev, "Invalid port-id: %d\n", port_id);
+		return -EINVAL;
+	}
+
+	hisi_pcie->port_id = port_id;
+
+	if (of_pci_parse_bus_range(pdev->dev.of_node, &busn)) {
+		dev_err(&pdev->dev, "failed to parse bus-ranges\n");
+		return -EINVAL;
+	}
+
+	pp->root_bus_nr = busn.start;
+	pp->ops = &hisi_pcie_host_ops;
+
+	hisi_pcie_config_context(hisi_pcie);
+
+	ret = dw_pcie_host_init(pp);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to initialize host\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int __init hisi_pcie_probe(struct platform_device *pdev)
+{
+	struct hisi_pcie *hisi_pcie;
+	struct pcie_port *pp;
+	struct resource *reg;
+	struct resource *subctrl;
+	int ret;
+
+	hisi_pcie = devm_kzalloc(&pdev->dev, sizeof(*hisi_pcie), GFP_KERNEL);
+	if (!hisi_pcie)
+		return -ENOMEM;
+
+	pp = &hisi_pcie->pp;
+	pp->dev = &pdev->dev;
+
+	subctrl = platform_get_resource_byname(pdev, IORESOURCE_MEM, "subctrl");
+	hisi_pcie->subctrl_base = devm_ioremap_nocache(&pdev->dev,
+					subctrl->start, resource_size(subctrl));
+	if (IS_ERR(hisi_pcie->subctrl_base)) {
+		dev_err(pp->dev, "cannot get subctrl base\n");
+		return PTR_ERR(hisi_pcie->subctrl_base);
+	}
+
+	reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbi");
+	hisi_pcie->reg_base = devm_ioremap_resource(&pdev->dev, reg);
+	if (IS_ERR(hisi_pcie->reg_base)) {
+		dev_err(pp->dev, "cannot get rc_dbi base\n");
+		return PTR_ERR(hisi_pcie->reg_base);
+	}
+
+	hisi_pcie->pp.dbi_base = hisi_pcie->reg_base;
+
+	ret = hisi_add_pcie_port(pp, pdev);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, hisi_pcie);
+
+	return 0;
+}
+
+static const struct of_device_id hisi_pcie_of_match[] = {
+	{.compatible = "hisilicon,hip05-pcie",},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, hisi_pcie_of_match);
+
+static struct platform_driver hisi_pcie_driver = {
+	.probe  = hisi_pcie_probe,
+	.driver = {
+		   .name = "hisi-pcie",
+		   .of_match_table = hisi_pcie_of_match,
+	},
+};
+
+module_platform_driver(hisi_pcie_driver);
-- 
1.9.1

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

* [PATCH v7 5/6] Documentation: DT: Add HiSilicon PCIe host binding
  2015-08-17 11:55 ` Zhou Wang
  (?)
@ 2015-08-17 11:55   ` Zhou Wang
  -1 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, gabriele.paoloni, lorenzo.pieralisi,
	james.morse, Liviu.Dudau, jason, robh
  Cc: linux-pci, linux-arm-kernel, devicetree, yuanzhichang, zhudacai,
	zhangjukuo, qiuzhenfa, liudongdong3, qiujiang, xuwei5, liguozhu,
	Zhou Wang

This patch adds related DTS binding document for HiSilicon PCIe host driver.

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
---
 .../devicetree/bindings/pci/hisilicon-pcie.txt     | 46 ++++++++++++++++++++++
 1 file changed, 46 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/hisilicon-pcie.txt

diff --git a/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
new file mode 100644
index 0000000..2afc9d1
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
@@ -0,0 +1,46 @@
+HiSilicon PCIe host bridge DT description
+
+HiSilicon PCIe host controller is based on Designware PCI core.
+It shares common functions with PCIe Designware core driver and inherits
+common properties defined in
+Documentation/devicetree/bindings/pci/designware-pci.txt.
+
+Additional properties are described here:
+
+Required properties:
+- compatible: Should contain "hisilicon,hip05-pcie".
+- reg: Should contain rc_dbi, subctrl, config registers location and length.
+- reg-names: Must include the following entries:
+  "rc_dbi": controller configuration registers;
+  "subctrl": whole PCIe hosts configuration registers;
+  "config": PCIe configuration space registers.
+- msi-parent: Should be its_pcie which is an ITS receiving MSI interrupts.
+- port-id: Should be 0, 1, 2 or 3.
+
+Optional properties:
+- status: Either "ok" or "disabled".
+- dma-coherent: Present if DMA operations are coherent.
+
+Example:
+	pcie@0xb0080000 {
+		compatible = "hisilicon,hip05-pcie", "snps,dw-pcie";
+		reg = <0 0xb0080000 0 0x10000>, <0 0xb0000000 0 0x10000>,
+		      <0x220 0x00000000 0 0x2000>;
+		reg-names = "rc_dbi", "subctrl", "config";
+		bus-range = <0  15>;
+		msi-parent = <&its_pcie>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		device_type = "pci";
+		dma-coherent;
+		ranges = <0x82000000 0 0x00000000 0x220 0x00000000 0 0x10000000>;
+		num-lanes = <8>;
+		port-id = <1>;
+		#interrupts-cells = <1>;
+		interrupts-map-mask = <0xf800 0 0 7>;
+		interrupts-map = <0x0 0 0 1 &mbigen_pcie 1 10
+				  0x0 0 0 2 &mbigen_pcie 2 11
+				  0x0 0 0 3 &mbigen_pcie 3 12
+				  0x0 0 0 4 &mbigen_pcie 4 13>;
+		status = "ok";
+	};
-- 
1.9.1

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

* [PATCH v7 5/6] Documentation: DT: Add HiSilicon PCIe host binding
@ 2015-08-17 11:55   ` Zhou Wang
  0 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, gabriele.paoloni, lorenzo.pieralisi,
	james.morse, Liviu.Dudau, jason, robh
  Cc: linux-pci, linux-arm-kernel, devicetree, yuanzhichang, zhudacai,
	zhangjukuo, qiuzhenfa, liudongdong3, qiujiang, xuwei5, liguozhu,
	Zhou Wang

This patch adds related DTS binding document for HiSilicon PCIe host driver.

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
---
 .../devicetree/bindings/pci/hisilicon-pcie.txt     | 46 ++++++++++++++++++++++
 1 file changed, 46 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/hisilicon-pcie.txt

diff --git a/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
new file mode 100644
index 0000000..2afc9d1
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
@@ -0,0 +1,46 @@
+HiSilicon PCIe host bridge DT description
+
+HiSilicon PCIe host controller is based on Designware PCI core.
+It shares common functions with PCIe Designware core driver and inherits
+common properties defined in
+Documentation/devicetree/bindings/pci/designware-pci.txt.
+
+Additional properties are described here:
+
+Required properties:
+- compatible: Should contain "hisilicon,hip05-pcie".
+- reg: Should contain rc_dbi, subctrl, config registers location and length.
+- reg-names: Must include the following entries:
+  "rc_dbi": controller configuration registers;
+  "subctrl": whole PCIe hosts configuration registers;
+  "config": PCIe configuration space registers.
+- msi-parent: Should be its_pcie which is an ITS receiving MSI interrupts.
+- port-id: Should be 0, 1, 2 or 3.
+
+Optional properties:
+- status: Either "ok" or "disabled".
+- dma-coherent: Present if DMA operations are coherent.
+
+Example:
+	pcie@0xb0080000 {
+		compatible = "hisilicon,hip05-pcie", "snps,dw-pcie";
+		reg = <0 0xb0080000 0 0x10000>, <0 0xb0000000 0 0x10000>,
+		      <0x220 0x00000000 0 0x2000>;
+		reg-names = "rc_dbi", "subctrl", "config";
+		bus-range = <0  15>;
+		msi-parent = <&its_pcie>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		device_type = "pci";
+		dma-coherent;
+		ranges = <0x82000000 0 0x00000000 0x220 0x00000000 0 0x10000000>;
+		num-lanes = <8>;
+		port-id = <1>;
+		#interrupts-cells = <1>;
+		interrupts-map-mask = <0xf800 0 0 7>;
+		interrupts-map = <0x0 0 0 1 &mbigen_pcie 1 10
+				  0x0 0 0 2 &mbigen_pcie 2 11
+				  0x0 0 0 3 &mbigen_pcie 3 12
+				  0x0 0 0 4 &mbigen_pcie 4 13>;
+		status = "ok";
+	};
-- 
1.9.1


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

* [PATCH v7 5/6] Documentation: DT: Add HiSilicon PCIe host binding
@ 2015-08-17 11:55   ` Zhou Wang
  0 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds related DTS binding document for HiSilicon PCIe host driver.

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
---
 .../devicetree/bindings/pci/hisilicon-pcie.txt     | 46 ++++++++++++++++++++++
 1 file changed, 46 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/hisilicon-pcie.txt

diff --git a/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
new file mode 100644
index 0000000..2afc9d1
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
@@ -0,0 +1,46 @@
+HiSilicon PCIe host bridge DT description
+
+HiSilicon PCIe host controller is based on Designware PCI core.
+It shares common functions with PCIe Designware core driver and inherits
+common properties defined in
+Documentation/devicetree/bindings/pci/designware-pci.txt.
+
+Additional properties are described here:
+
+Required properties:
+- compatible: Should contain "hisilicon,hip05-pcie".
+- reg: Should contain rc_dbi, subctrl, config registers location and length.
+- reg-names: Must include the following entries:
+  "rc_dbi": controller configuration registers;
+  "subctrl": whole PCIe hosts configuration registers;
+  "config": PCIe configuration space registers.
+- msi-parent: Should be its_pcie which is an ITS receiving MSI interrupts.
+- port-id: Should be 0, 1, 2 or 3.
+
+Optional properties:
+- status: Either "ok" or "disabled".
+- dma-coherent: Present if DMA operations are coherent.
+
+Example:
+	pcie at 0xb0080000 {
+		compatible = "hisilicon,hip05-pcie", "snps,dw-pcie";
+		reg = <0 0xb0080000 0 0x10000>, <0 0xb0000000 0 0x10000>,
+		      <0x220 0x00000000 0 0x2000>;
+		reg-names = "rc_dbi", "subctrl", "config";
+		bus-range = <0  15>;
+		msi-parent = <&its_pcie>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		device_type = "pci";
+		dma-coherent;
+		ranges = <0x82000000 0 0x00000000 0x220 0x00000000 0 0x10000000>;
+		num-lanes = <8>;
+		port-id = <1>;
+		#interrupts-cells = <1>;
+		interrupts-map-mask = <0xf800 0 0 7>;
+		interrupts-map = <0x0 0 0 1 &mbigen_pcie 1 10
+				  0x0 0 0 2 &mbigen_pcie 2 11
+				  0x0 0 0 3 &mbigen_pcie 3 12
+				  0x0 0 0 4 &mbigen_pcie 4 13>;
+		status = "ok";
+	};
-- 
1.9.1

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

* [PATCH v7 6/6] MAINTAINERS: Add pcie-hisi maintainer
  2015-08-17 11:55 ` Zhou Wang
  (?)
@ 2015-08-17 11:55   ` Zhou Wang
  -1 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, gabriele.paoloni, lorenzo.pieralisi,
	james.morse, Liviu.Dudau, jason, robh
  Cc: linux-pci, linux-arm-kernel, devicetree, yuanzhichang, zhudacai,
	zhangjukuo, qiuzhenfa, liudongdong3, qiujiang, xuwei5, liguozhu,
	Zhou Wang

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8133cef..7cd8e47 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7854,6 +7854,13 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/pci/xgene-pci-msi.txt
 F:	drivers/pci/host/pci-xgene-msi.c
 
+PCIE DRIVER FOR HISILICON
+M:	Zhou Wang <wangzhou1@hisilicon.com>
+L:	linux-pci@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
+F:	drivers/pci/host/pcie-hisi.c
+
 PCMCIA SUBSYSTEM
 P:	Linux PCMCIA Team
 L:	linux-pcmcia@lists.infradead.org
-- 
1.9.1

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

* [PATCH v7 6/6] MAINTAINERS: Add pcie-hisi maintainer
@ 2015-08-17 11:55   ` Zhou Wang
  0 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, gabriele.paoloni, lorenzo.pieralisi,
	james.morse, Liviu.Dudau, jason, robh
  Cc: linux-pci, linux-arm-kernel, devicetree, yuanzhichang, zhudacai,
	zhangjukuo, qiuzhenfa, liudongdong3, qiujiang, xuwei5, liguozhu,
	Zhou Wang

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8133cef..7cd8e47 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7854,6 +7854,13 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/pci/xgene-pci-msi.txt
 F:	drivers/pci/host/pci-xgene-msi.c
 
+PCIE DRIVER FOR HISILICON
+M:	Zhou Wang <wangzhou1@hisilicon.com>
+L:	linux-pci@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
+F:	drivers/pci/host/pcie-hisi.c
+
 PCMCIA SUBSYSTEM
 P:	Linux PCMCIA Team
 L:	linux-pcmcia@lists.infradead.org
-- 
1.9.1


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

* [PATCH v7 6/6] MAINTAINERS: Add pcie-hisi maintainer
@ 2015-08-17 11:55   ` Zhou Wang
  0 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-17 11:55 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8133cef..7cd8e47 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7854,6 +7854,13 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/pci/xgene-pci-msi.txt
 F:	drivers/pci/host/pci-xgene-msi.c
 
+PCIE DRIVER FOR HISILICON
+M:	Zhou Wang <wangzhou1@hisilicon.com>
+L:	linux-pci at vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
+F:	drivers/pci/host/pcie-hisi.c
+
 PCMCIA SUBSYSTEM
 P:	Linux PCMCIA Team
 L:	linux-pcmcia at lists.infradead.org
-- 
1.9.1

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

* Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
  2015-08-17 11:55   ` Zhou Wang
  (?)
@ 2015-08-19 12:20     ` Zhou Wang
  -1 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-19 12:20 UTC (permalink / raw)
  To: Zhou Wang
  Cc: Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, gabriele.paoloni, lorenzo.pieralisi,
	james.morse, Liviu.Dudau, jason, robh, linux-pci,
	linux-arm-kernel, devicetree, yuanzhichang, zhudacai, zhangjukuo,
	qiuzhenfa, liudongdong3, qiujiang, xuwei5, liguozhu

Hi Pratyush and Jingoo,

what is your opinion about this patch? It will be very appreciated if you
could take a look at it.

Thanks,
Zhou

On 2015/8/17 19:55, Zhou Wang wrote:
> This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete
> function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci,
> move related operations to dw_pcie_host_init.
> 
> In past, we use:
> pci_common_init_dev
> 	-> pcibios_init_hw
> 		-> hw->scan (dw_pcie_scan_bus)
> to pass 0 to root_bus_nr in struct pcie_port. This patch set pp->root_bus_nr = 0
> in each PCIe host driver which is based on pcie-designware.
> 
> This patch also try to use of_pci_get_host_bridge_resources for ARM32 and ARM64
> according to the suggestion for Gabriele[1]
> 
> Finally this patch reverts commit f4c55c5a3f7f "PCI: designware: Program ATU
> with untranslated address" based on 1/6 in this series. we delete *_mod_base in
> pcie-designware. This was discussed in [2]
> 
> I have compiled the driver with multi_v7_defconfig. However, I don't have
> ARM32 PCIe related board to do test. It will be appreciated if someone could
> help to test it.
> 
> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Tested-By: James Morse <james.morse@arm.com>
> 
> [1] http://www.spinics.net/lists/linux-pci/msg42194.html
> [2] http://www.spinics.net/lists/arm-kernel/msg436779.html
> ---
>  drivers/pci/host/pci-dra7xx.c      |  15 +--
>  drivers/pci/host/pci-exynos.c      |   2 +-
>  drivers/pci/host/pci-imx6.c        |   2 +-
>  drivers/pci/host/pci-keystone-dw.c |   2 +-
>  drivers/pci/host/pci-keystone.c    |   2 +-
>  drivers/pci/host/pci-layerscape.c  |   2 +-
>  drivers/pci/host/pcie-designware.c | 229 ++++++++++++-------------------------
>  drivers/pci/host/pcie-designware.h |  14 +--
>  drivers/pci/host/pcie-spear13xx.c  |   2 +-
>  9 files changed, 95 insertions(+), 175 deletions(-)
> 
> diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
> index 18ae7ff..1268c69 100644
> --- a/drivers/pci/host/pci-dra7xx.c
> +++ b/drivers/pci/host/pci-dra7xx.c
> @@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp)
>  {
>  	dw_pcie_setup_rc(pp);
>  
> -	if (pp->io_mod_base)
> -		pp->io_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->io_base)
> +		pp->io_base &= CPU_TO_BUS_ADDR;
>  
> -	if (pp->mem_mod_base)
> -		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->mem_base)
> +		pp->mem_base &= CPU_TO_BUS_ADDR;
>  
> -	if (pp->cfg0_mod_base) {
> -		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
> -		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->cfg0_base) {
> +		pp->cfg0_base &= CPU_TO_BUS_ADDR;
> +		pp->cfg1_base &= CPU_TO_BUS_ADDR;
>  	}
>  
>  	dra7xx_pcie_establish_link(pp);
> @@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
>  
>  	pp = &dra7xx->pp;
>  	pp->dev = dev;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &dra7xx_pcie_host_ops;
>  
>  	pp->irq = platform_get_irq(pdev, 1);
> diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
> index f9f468d..9771bb0 100644
> --- a/drivers/pci/host/pci-exynos.c
> +++ b/drivers/pci/host/pci-exynos.c
> @@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
>  		}
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &exynos_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
> index 233a196..bec256c 100644
> --- a/drivers/pci/host/pci-imx6.c
> +++ b/drivers/pci/host/pci-imx6.c
> @@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
>  		}
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &imx6_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c
> index f34892e..b1e4135 100644
> --- a/drivers/pci/host/pci-keystone-dw.c
> +++ b/drivers/pci/host/pci-keystone-dw.c
> @@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void __iomem *reg_virt)
>  void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
>  {
>  	struct pcie_port *pp = &ks_pcie->pp;
> -	u32 start = pp->mem.start, end = pp->mem.end;
> +	u32 start = pp->mem->start, end = pp->mem->end;
>  	int i, tr_size;
>  
>  	/* Disable BARs for inbound access */
> diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
> index 734da58..8113832 100644
> --- a/drivers/pci/host/pci-keystone.c
> +++ b/drivers/pci/host/pci-keystone.c
> @@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
>  			return ret;
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &keystone_pcie_host_ops;
>  	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
>  	if (ret) {
> diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
> index b2328ea1..79ff08c 100644
> --- a/drivers/pci/host/pci-layerscape.c
> +++ b/drivers/pci/host/pci-layerscape.c
> @@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
>  	pp = &pcie->pp;
>  	pp->dev = pcie->dev;
>  	pp->dbi_base = pcie->dbi;
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &ls_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
> index c5d407c..e71a88e 100644
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c
> @@ -11,6 +11,7 @@
>   * published by the Free Software Foundation.
>   */
>  
> +#include <linux/hardirq.h>
>  #include <linux/irq.h>
>  #include <linux/irqdomain.h>
>  #include <linux/kernel.h>
> @@ -69,16 +70,7 @@
>  #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
>  #define PCIE_ATU_UPPER_TARGET		0x91C
>  
> -static struct hw_pci dw_pci;
> -
> -static unsigned long global_io_offset;
> -
> -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
> -{
> -	BUG_ON(!sys->private_data);
> -
> -	return sys->private_data;
> -}
> +static struct pci_ops dw_pcie_ops;
>  
>  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
>  {
> @@ -255,7 +247,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
>  static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
>  {
>  	int irq, pos0, i;
> -	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
> +	struct pcie_port *pp = desc->dev->bus->sysdata;
>  
>  	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
>  				       order_base_2(no_irqs));
> @@ -298,7 +290,7 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
>  {
>  	int irq, pos;
>  	struct msi_msg msg;
> -	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
> +	struct pcie_port *pp = pdev->bus->sysdata;
>  
>  	if (desc->msi_attrib.is_msix)
>  		return -EINVAL;
> @@ -327,7 +319,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
>  {
>  	struct irq_data *data = irq_get_irq_data(irq);
>  	struct msi_desc *msi = irq_data_get_msi(data);
> -	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
> +	struct pcie_port *pp = msi->dev->bus->sysdata;
>  
>  	clear_irq_range(pp, irq, 1, data->hwirq);
>  }
> @@ -363,14 +355,12 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  {
>  	struct device_node *np = pp->dev->of_node;
>  	struct platform_device *pdev = to_platform_device(pp->dev);
> -	struct of_pci_range range;
> -	struct of_pci_range_parser parser;
> +	struct pci_bus *bus;
>  	struct resource *cfg_res;
> -	u32 val, ns;
> -	const __be32 *addrp;
> -	int i, index, ret;
> -
> -	ns = of_n_size_cells(np);
> +	LIST_HEAD(res);
> +	u32 val;
> +	int i, ret;
> +	struct resource_entry *win;
>  
>  	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
>  	if (cfg_res) {
> @@ -378,85 +368,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  		pp->cfg1_size = resource_size(cfg_res)/2;
>  		pp->cfg0_base = cfg_res->start;
>  		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
> -
> -		/* Find the untranslated configuration space address */
> -		index = of_property_match_string(np, "reg-names", "config");
> -		addrp = of_get_address(np, index, NULL, NULL);
> -		pp->cfg0_mod_base = of_read_number(addrp, ns);
> -		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
>  	} else {
>  		dev_err(pp->dev, "missing *config* reg space\n");
>  	}
>  
> -	if (of_pci_range_parser_init(&parser, np)) {
> -		dev_err(pp->dev, "missing ranges property\n");
> -		return -EINVAL;
> -	}
> +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
> +	if (ret)
> +		return ret;
>  
>  	/* Get the I/O and memory ranges from DT */
> -	for_each_of_pci_range(&parser, &range) {
> -		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
> -
> -		if (restype == IORESOURCE_IO) {
> -			of_pci_range_to_resource(&range, np, &pp->io);
> -			pp->io.name = "I/O";
> -			pp->io.start = max_t(resource_size_t,
> -					     PCIBIOS_MIN_IO,
> -					     range.pci_addr + global_io_offset);
> -			pp->io.end = min_t(resource_size_t,
> -					   IO_SPACE_LIMIT,
> -					   range.pci_addr + range.size
> -					   + global_io_offset - 1);
> -			pp->io_size = resource_size(&pp->io);
> -			pp->io_bus_addr = range.pci_addr;
> -			pp->io_base = range.cpu_addr;
> -
> -			/* Find the untranslated IO space address */
> -			pp->io_mod_base = range.cpu_addr;
> -		}
> -		if (restype == IORESOURCE_MEM) {
> -			of_pci_range_to_resource(&range, np, &pp->mem);
> -			pp->mem.name = "MEM";
> -			pp->mem_size = resource_size(&pp->mem);
> -			pp->mem_bus_addr = range.pci_addr;
> -
> -			/* Find the untranslated MEM space address */
> -			pp->mem_mod_base = range.cpu_addr;
> -		}
> -		if (restype == 0) {
> -			of_pci_range_to_resource(&range, np, &pp->cfg);
> -			pp->cfg0_size = resource_size(&pp->cfg)/2;
> -			pp->cfg1_size = resource_size(&pp->cfg)/2;
> -			pp->cfg0_base = pp->cfg.start;
> -			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
> -
> -			/* Find the untranslated configuration space address */
> -			pp->cfg0_mod_base = range.cpu_addr;
> -			pp->cfg1_mod_base = pp->cfg0_mod_base +
> -					    pp->cfg0_size;
> +	resource_list_for_each_entry(win, &res) {
> +		switch (resource_type(win->res)) {
> +		case IORESOURCE_IO:
> +			pp->io = win->res;
> +			pp->io->name = "I/O";
> +			pp->io_size = resource_size(pp->io);
> +			pp->io_bus_addr = pp->io->start - win->offset;
> +			ret = pci_remap_iospace(pp->io, pp->io_base);
> +			if (ret) {
> +				dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
> +					 ret, pp->io);
> +				continue;
> +			}
> +			break;
> +		case IORESOURCE_MEM:
> +			pp->mem = win->res;
> +			pp->mem->name = "MEM";
> +			pp->mem_size = resource_size(pp->mem);
> +			pp->mem_bus_addr = pp->mem->start - win->offset;
> +			break;
> +		case 0:
> +			pp->cfg = win->res;
> +			pp->cfg0_size = resource_size(pp->cfg)/2;
> +			pp->cfg1_size = resource_size(pp->cfg)/2;
> +			pp->cfg0_base = pp->cfg->start;
> +			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
> +			break;
> +		case IORESOURCE_BUS:
> +			pp->busn = win->res;
> +			break;
> +		default:
> +			continue;
>  		}
>  	}
>  
> -	ret = of_pci_parse_bus_range(np, &pp->busn);
> -	if (ret < 0) {
> -		pp->busn.name = np->name;
> -		pp->busn.start = 0;
> -		pp->busn.end = 0xff;
> -		pp->busn.flags = IORESOURCE_BUS;
> -		dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n",
> -			ret, &pp->busn);
> -	}
> -
>  	if (!pp->dbi_base) {
> -		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
> -					resource_size(&pp->cfg));
> +		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
> +					resource_size(pp->cfg));
>  		if (!pp->dbi_base) {
>  			dev_err(pp->dev, "error with ioremap\n");
>  			return -ENOMEM;
>  		}
>  	}
>  
> -	pp->mem_base = pp->mem.start;
> +	pp->mem_base = pp->mem->start;
>  
>  	if (!pp->va_cfg0_base) {
>  		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
> @@ -505,7 +470,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  
>  	if (!pp->ops->rd_other_conf)
>  		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
> -					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
> +					  PCIE_ATU_TYPE_MEM, pp->mem_base,
>  					  pp->mem_bus_addr, pp->mem_size);
>  
>  	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
> @@ -517,15 +482,29 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  	val |= PORT_LOGIC_SPEED_CHANGE;
>  	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
>  
> -#ifdef CONFIG_PCI_MSI
> +	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
> +				  pp, &res);
> +	if (!bus)
> +		return -ENOMEM;
> +
> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> +	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
> +#else
>  	dw_pcie_msi_chip.dev = pp->dev;
> -	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> +	bus->msi = &dw_pcie_msi_chip;
>  #endif
>  
> -	dw_pci.nr_controllers = 1;
> -	dw_pci.private_data = (void **)&pp;
> +	pci_scan_child_bus(bus);
> +	if (pp->ops->scan_bus)
> +		pp->ops->scan_bus(pp);
> +
> +#ifdef CONFIG_ARM
> +	/* support old dtbs that incorrectly describe IRQs */
> +	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
> +#endif
>  
> -	pci_common_init_dev(pp->dev, &dw_pci);
> +	pci_assign_unassigned_bus_resources(bus);
> +	pci_bus_add_devices(bus);
>  
>  	return 0;
>  }
> @@ -544,12 +523,12 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  
>  	if (bus->parent->number == pp->root_bus_nr) {
>  		type = PCIE_ATU_TYPE_CFG0;
> -		cpu_addr = pp->cfg0_mod_base;
> +		cpu_addr = pp->cfg0_base;
>  		cfg_size = pp->cfg0_size;
>  		va_cfg_base = pp->va_cfg0_base;
>  	} else {
>  		type = PCIE_ATU_TYPE_CFG1;
> -		cpu_addr = pp->cfg1_mod_base;
> +		cpu_addr = pp->cfg1_base;
>  		cfg_size = pp->cfg1_size;
>  		va_cfg_base = pp->va_cfg1_base;
>  	}
> @@ -559,7 +538,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  				  busdev, cfg_size);
>  	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
>  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> +				  PCIE_ATU_TYPE_IO, pp->io_base,
>  				  pp->io_bus_addr, pp->io_size);
>  
>  	return ret;
> @@ -579,12 +558,12 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  
>  	if (bus->parent->number == pp->root_bus_nr) {
>  		type = PCIE_ATU_TYPE_CFG0;
> -		cpu_addr = pp->cfg0_mod_base;
> +		cpu_addr = pp->cfg0_base;
>  		cfg_size = pp->cfg0_size;
>  		va_cfg_base = pp->va_cfg0_base;
>  	} else {
>  		type = PCIE_ATU_TYPE_CFG1;
> -		cpu_addr = pp->cfg1_mod_base;
> +		cpu_addr = pp->cfg1_base;
>  		cfg_size = pp->cfg1_size;
>  		va_cfg_base = pp->va_cfg1_base;
>  	}
> @@ -594,7 +573,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  				  busdev, cfg_size);
>  	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
>  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> +				  PCIE_ATU_TYPE_IO, pp->io_base,
>  				  pp->io_bus_addr, pp->io_size);
>  
>  	return ret;
> @@ -626,7 +605,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
>  static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
>  			int size, u32 *val)
>  {
> -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> +	struct pcie_port *pp = bus->sysdata;
>  	int ret;
>  
>  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
> @@ -650,7 +629,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
>  static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
>  			int where, int size, u32 val)
>  {
> -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> +	struct pcie_port *pp = bus->sysdata;
>  	int ret;
>  
>  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
> @@ -674,62 +653,6 @@ static struct pci_ops dw_pcie_ops = {
>  	.write = dw_pcie_wr_conf,
>  };
>  
> -static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
> -{
> -	struct pcie_port *pp;
> -
> -	pp = sys_to_pcie(sys);
> -
> -	if (global_io_offset < SZ_1M && pp->io_size > 0) {
> -		sys->io_offset = global_io_offset - pp->io_bus_addr;
> -		pci_ioremap_io(global_io_offset, pp->io_base);
> -		global_io_offset += SZ_64K;
> -		pci_add_resource_offset(&sys->resources, &pp->io,
> -					sys->io_offset);
> -	}
> -
> -	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
> -	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
> -	pci_add_resource(&sys->resources, &pp->busn);
> -
> -	return 1;
> -}
> -
> -static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
> -{
> -	struct pci_bus *bus;
> -	struct pcie_port *pp = sys_to_pcie(sys);
> -
> -	pp->root_bus_nr = sys->busnr;
> -	bus = pci_scan_root_bus(pp->dev, sys->busnr,
> -				  &dw_pcie_ops, sys, &sys->resources);
> -	if (!bus)
> -		return NULL;
> -
> -	if (bus && pp->ops->scan_bus)
> -		pp->ops->scan_bus(pp);
> -
> -	return bus;
> -}
> -
> -static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> -{
> -	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
> -	int irq;
> -
> -	irq = of_irq_parse_and_map_pci(dev, slot, pin);
> -	if (!irq)
> -		irq = pp->irq;
> -
> -	return irq;
> -}
> -
> -static struct hw_pci dw_pci = {
> -	.setup		= dw_pcie_setup,
> -	.scan		= dw_pcie_scan_bus,
> -	.map_irq	= dw_pcie_map_irq,
> -};
> -
>  void dw_pcie_setup_rc(struct pcie_port *pp)
>  {
>  	u32 val;
> diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
> index d0bbd27..264c969 100644
> --- a/drivers/pci/host/pcie-designware.h
> +++ b/drivers/pci/host/pcie-designware.h
> @@ -27,25 +27,21 @@ struct pcie_port {
>  	u8			root_bus_nr;
>  	void __iomem		*dbi_base;
>  	u64			cfg0_base;
> -	u64			cfg0_mod_base;
>  	void __iomem		*va_cfg0_base;
>  	u32			cfg0_size;
>  	u64			cfg1_base;
> -	u64			cfg1_mod_base;
>  	void __iomem		*va_cfg1_base;
>  	u32			cfg1_size;
> -	u64			io_base;
> -	u64			io_mod_base;
> +	resource_size_t		io_base;
>  	phys_addr_t		io_bus_addr;
>  	u32			io_size;
>  	u64			mem_base;
> -	u64			mem_mod_base;
>  	phys_addr_t		mem_bus_addr;
>  	u32			mem_size;
> -	struct resource		cfg;
> -	struct resource		io;
> -	struct resource		mem;
> -	struct resource		busn;
> +	struct resource		*cfg;
> +	struct resource		*io;
> +	struct resource		*mem;
> +	struct resource		*busn;
>  	int			irq;
>  	u32			lanes;
>  	struct pcie_host_ops	*ops;
> diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
> index c49fbdc..03eb204 100644
> --- a/drivers/pci/host/pcie-spear13xx.c
> +++ b/drivers/pci/host/pcie-spear13xx.c
> @@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
>  		return ret;
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &spear13xx_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> 

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

* Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-19 12:20     ` Zhou Wang
  0 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-19 12:20 UTC (permalink / raw)
  To: Zhou Wang
  Cc: Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, gabriele.paoloni, lorenzo.pieralisi,
	james.morse, Liviu.Dudau, jason, robh, linux-pci,
	linux-arm-kernel, devicetree, yuanzhichang, zhudacai, zhangjukuo,
	qiuzhenfa, liudongdong3, qiujiang, xuwei5, liguozhu

Hi Pratyush and Jingoo,

what is your opinion about this patch? It will be very appreciated if you
could take a look at it.

Thanks,
Zhou

On 2015/8/17 19:55, Zhou Wang wrote:
> This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete
> function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci,
> move related operations to dw_pcie_host_init.
> 
> In past, we use:
> pci_common_init_dev
> 	-> pcibios_init_hw
> 		-> hw->scan (dw_pcie_scan_bus)
> to pass 0 to root_bus_nr in struct pcie_port. This patch set pp->root_bus_nr = 0
> in each PCIe host driver which is based on pcie-designware.
> 
> This patch also try to use of_pci_get_host_bridge_resources for ARM32 and ARM64
> according to the suggestion for Gabriele[1]
> 
> Finally this patch reverts commit f4c55c5a3f7f "PCI: designware: Program ATU
> with untranslated address" based on 1/6 in this series. we delete *_mod_base in
> pcie-designware. This was discussed in [2]
> 
> I have compiled the driver with multi_v7_defconfig. However, I don't have
> ARM32 PCIe related board to do test. It will be appreciated if someone could
> help to test it.
> 
> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Tested-By: James Morse <james.morse@arm.com>
> 
> [1] http://www.spinics.net/lists/linux-pci/msg42194.html
> [2] http://www.spinics.net/lists/arm-kernel/msg436779.html
> ---
>  drivers/pci/host/pci-dra7xx.c      |  15 +--
>  drivers/pci/host/pci-exynos.c      |   2 +-
>  drivers/pci/host/pci-imx6.c        |   2 +-
>  drivers/pci/host/pci-keystone-dw.c |   2 +-
>  drivers/pci/host/pci-keystone.c    |   2 +-
>  drivers/pci/host/pci-layerscape.c  |   2 +-
>  drivers/pci/host/pcie-designware.c | 229 ++++++++++++-------------------------
>  drivers/pci/host/pcie-designware.h |  14 +--
>  drivers/pci/host/pcie-spear13xx.c  |   2 +-
>  9 files changed, 95 insertions(+), 175 deletions(-)
> 
> diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
> index 18ae7ff..1268c69 100644
> --- a/drivers/pci/host/pci-dra7xx.c
> +++ b/drivers/pci/host/pci-dra7xx.c
> @@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp)
>  {
>  	dw_pcie_setup_rc(pp);
>  
> -	if (pp->io_mod_base)
> -		pp->io_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->io_base)
> +		pp->io_base &= CPU_TO_BUS_ADDR;
>  
> -	if (pp->mem_mod_base)
> -		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->mem_base)
> +		pp->mem_base &= CPU_TO_BUS_ADDR;
>  
> -	if (pp->cfg0_mod_base) {
> -		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
> -		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->cfg0_base) {
> +		pp->cfg0_base &= CPU_TO_BUS_ADDR;
> +		pp->cfg1_base &= CPU_TO_BUS_ADDR;
>  	}
>  
>  	dra7xx_pcie_establish_link(pp);
> @@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
>  
>  	pp = &dra7xx->pp;
>  	pp->dev = dev;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &dra7xx_pcie_host_ops;
>  
>  	pp->irq = platform_get_irq(pdev, 1);
> diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
> index f9f468d..9771bb0 100644
> --- a/drivers/pci/host/pci-exynos.c
> +++ b/drivers/pci/host/pci-exynos.c
> @@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
>  		}
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &exynos_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
> index 233a196..bec256c 100644
> --- a/drivers/pci/host/pci-imx6.c
> +++ b/drivers/pci/host/pci-imx6.c
> @@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
>  		}
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &imx6_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c
> index f34892e..b1e4135 100644
> --- a/drivers/pci/host/pci-keystone-dw.c
> +++ b/drivers/pci/host/pci-keystone-dw.c
> @@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void __iomem *reg_virt)
>  void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
>  {
>  	struct pcie_port *pp = &ks_pcie->pp;
> -	u32 start = pp->mem.start, end = pp->mem.end;
> +	u32 start = pp->mem->start, end = pp->mem->end;
>  	int i, tr_size;
>  
>  	/* Disable BARs for inbound access */
> diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
> index 734da58..8113832 100644
> --- a/drivers/pci/host/pci-keystone.c
> +++ b/drivers/pci/host/pci-keystone.c
> @@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
>  			return ret;
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &keystone_pcie_host_ops;
>  	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
>  	if (ret) {
> diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
> index b2328ea1..79ff08c 100644
> --- a/drivers/pci/host/pci-layerscape.c
> +++ b/drivers/pci/host/pci-layerscape.c
> @@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
>  	pp = &pcie->pp;
>  	pp->dev = pcie->dev;
>  	pp->dbi_base = pcie->dbi;
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &ls_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
> index c5d407c..e71a88e 100644
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c
> @@ -11,6 +11,7 @@
>   * published by the Free Software Foundation.
>   */
>  
> +#include <linux/hardirq.h>
>  #include <linux/irq.h>
>  #include <linux/irqdomain.h>
>  #include <linux/kernel.h>
> @@ -69,16 +70,7 @@
>  #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
>  #define PCIE_ATU_UPPER_TARGET		0x91C
>  
> -static struct hw_pci dw_pci;
> -
> -static unsigned long global_io_offset;
> -
> -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
> -{
> -	BUG_ON(!sys->private_data);
> -
> -	return sys->private_data;
> -}
> +static struct pci_ops dw_pcie_ops;
>  
>  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
>  {
> @@ -255,7 +247,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
>  static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
>  {
>  	int irq, pos0, i;
> -	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
> +	struct pcie_port *pp = desc->dev->bus->sysdata;
>  
>  	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
>  				       order_base_2(no_irqs));
> @@ -298,7 +290,7 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
>  {
>  	int irq, pos;
>  	struct msi_msg msg;
> -	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
> +	struct pcie_port *pp = pdev->bus->sysdata;
>  
>  	if (desc->msi_attrib.is_msix)
>  		return -EINVAL;
> @@ -327,7 +319,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
>  {
>  	struct irq_data *data = irq_get_irq_data(irq);
>  	struct msi_desc *msi = irq_data_get_msi(data);
> -	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
> +	struct pcie_port *pp = msi->dev->bus->sysdata;
>  
>  	clear_irq_range(pp, irq, 1, data->hwirq);
>  }
> @@ -363,14 +355,12 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  {
>  	struct device_node *np = pp->dev->of_node;
>  	struct platform_device *pdev = to_platform_device(pp->dev);
> -	struct of_pci_range range;
> -	struct of_pci_range_parser parser;
> +	struct pci_bus *bus;
>  	struct resource *cfg_res;
> -	u32 val, ns;
> -	const __be32 *addrp;
> -	int i, index, ret;
> -
> -	ns = of_n_size_cells(np);
> +	LIST_HEAD(res);
> +	u32 val;
> +	int i, ret;
> +	struct resource_entry *win;
>  
>  	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
>  	if (cfg_res) {
> @@ -378,85 +368,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  		pp->cfg1_size = resource_size(cfg_res)/2;
>  		pp->cfg0_base = cfg_res->start;
>  		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
> -
> -		/* Find the untranslated configuration space address */
> -		index = of_property_match_string(np, "reg-names", "config");
> -		addrp = of_get_address(np, index, NULL, NULL);
> -		pp->cfg0_mod_base = of_read_number(addrp, ns);
> -		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
>  	} else {
>  		dev_err(pp->dev, "missing *config* reg space\n");
>  	}
>  
> -	if (of_pci_range_parser_init(&parser, np)) {
> -		dev_err(pp->dev, "missing ranges property\n");
> -		return -EINVAL;
> -	}
> +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
> +	if (ret)
> +		return ret;
>  
>  	/* Get the I/O and memory ranges from DT */
> -	for_each_of_pci_range(&parser, &range) {
> -		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
> -
> -		if (restype == IORESOURCE_IO) {
> -			of_pci_range_to_resource(&range, np, &pp->io);
> -			pp->io.name = "I/O";
> -			pp->io.start = max_t(resource_size_t,
> -					     PCIBIOS_MIN_IO,
> -					     range.pci_addr + global_io_offset);
> -			pp->io.end = min_t(resource_size_t,
> -					   IO_SPACE_LIMIT,
> -					   range.pci_addr + range.size
> -					   + global_io_offset - 1);
> -			pp->io_size = resource_size(&pp->io);
> -			pp->io_bus_addr = range.pci_addr;
> -			pp->io_base = range.cpu_addr;
> -
> -			/* Find the untranslated IO space address */
> -			pp->io_mod_base = range.cpu_addr;
> -		}
> -		if (restype == IORESOURCE_MEM) {
> -			of_pci_range_to_resource(&range, np, &pp->mem);
> -			pp->mem.name = "MEM";
> -			pp->mem_size = resource_size(&pp->mem);
> -			pp->mem_bus_addr = range.pci_addr;
> -
> -			/* Find the untranslated MEM space address */
> -			pp->mem_mod_base = range.cpu_addr;
> -		}
> -		if (restype == 0) {
> -			of_pci_range_to_resource(&range, np, &pp->cfg);
> -			pp->cfg0_size = resource_size(&pp->cfg)/2;
> -			pp->cfg1_size = resource_size(&pp->cfg)/2;
> -			pp->cfg0_base = pp->cfg.start;
> -			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
> -
> -			/* Find the untranslated configuration space address */
> -			pp->cfg0_mod_base = range.cpu_addr;
> -			pp->cfg1_mod_base = pp->cfg0_mod_base +
> -					    pp->cfg0_size;
> +	resource_list_for_each_entry(win, &res) {
> +		switch (resource_type(win->res)) {
> +		case IORESOURCE_IO:
> +			pp->io = win->res;
> +			pp->io->name = "I/O";
> +			pp->io_size = resource_size(pp->io);
> +			pp->io_bus_addr = pp->io->start - win->offset;
> +			ret = pci_remap_iospace(pp->io, pp->io_base);
> +			if (ret) {
> +				dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
> +					 ret, pp->io);
> +				continue;
> +			}
> +			break;
> +		case IORESOURCE_MEM:
> +			pp->mem = win->res;
> +			pp->mem->name = "MEM";
> +			pp->mem_size = resource_size(pp->mem);
> +			pp->mem_bus_addr = pp->mem->start - win->offset;
> +			break;
> +		case 0:
> +			pp->cfg = win->res;
> +			pp->cfg0_size = resource_size(pp->cfg)/2;
> +			pp->cfg1_size = resource_size(pp->cfg)/2;
> +			pp->cfg0_base = pp->cfg->start;
> +			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
> +			break;
> +		case IORESOURCE_BUS:
> +			pp->busn = win->res;
> +			break;
> +		default:
> +			continue;
>  		}
>  	}
>  
> -	ret = of_pci_parse_bus_range(np, &pp->busn);
> -	if (ret < 0) {
> -		pp->busn.name = np->name;
> -		pp->busn.start = 0;
> -		pp->busn.end = 0xff;
> -		pp->busn.flags = IORESOURCE_BUS;
> -		dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n",
> -			ret, &pp->busn);
> -	}
> -
>  	if (!pp->dbi_base) {
> -		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
> -					resource_size(&pp->cfg));
> +		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
> +					resource_size(pp->cfg));
>  		if (!pp->dbi_base) {
>  			dev_err(pp->dev, "error with ioremap\n");
>  			return -ENOMEM;
>  		}
>  	}
>  
> -	pp->mem_base = pp->mem.start;
> +	pp->mem_base = pp->mem->start;
>  
>  	if (!pp->va_cfg0_base) {
>  		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
> @@ -505,7 +470,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  
>  	if (!pp->ops->rd_other_conf)
>  		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
> -					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
> +					  PCIE_ATU_TYPE_MEM, pp->mem_base,
>  					  pp->mem_bus_addr, pp->mem_size);
>  
>  	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
> @@ -517,15 +482,29 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  	val |= PORT_LOGIC_SPEED_CHANGE;
>  	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
>  
> -#ifdef CONFIG_PCI_MSI
> +	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
> +				  pp, &res);
> +	if (!bus)
> +		return -ENOMEM;
> +
> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> +	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
> +#else
>  	dw_pcie_msi_chip.dev = pp->dev;
> -	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> +	bus->msi = &dw_pcie_msi_chip;
>  #endif
>  
> -	dw_pci.nr_controllers = 1;
> -	dw_pci.private_data = (void **)&pp;
> +	pci_scan_child_bus(bus);
> +	if (pp->ops->scan_bus)
> +		pp->ops->scan_bus(pp);
> +
> +#ifdef CONFIG_ARM
> +	/* support old dtbs that incorrectly describe IRQs */
> +	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
> +#endif
>  
> -	pci_common_init_dev(pp->dev, &dw_pci);
> +	pci_assign_unassigned_bus_resources(bus);
> +	pci_bus_add_devices(bus);
>  
>  	return 0;
>  }
> @@ -544,12 +523,12 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  
>  	if (bus->parent->number == pp->root_bus_nr) {
>  		type = PCIE_ATU_TYPE_CFG0;
> -		cpu_addr = pp->cfg0_mod_base;
> +		cpu_addr = pp->cfg0_base;
>  		cfg_size = pp->cfg0_size;
>  		va_cfg_base = pp->va_cfg0_base;
>  	} else {
>  		type = PCIE_ATU_TYPE_CFG1;
> -		cpu_addr = pp->cfg1_mod_base;
> +		cpu_addr = pp->cfg1_base;
>  		cfg_size = pp->cfg1_size;
>  		va_cfg_base = pp->va_cfg1_base;
>  	}
> @@ -559,7 +538,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  				  busdev, cfg_size);
>  	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
>  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> +				  PCIE_ATU_TYPE_IO, pp->io_base,
>  				  pp->io_bus_addr, pp->io_size);
>  
>  	return ret;
> @@ -579,12 +558,12 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  
>  	if (bus->parent->number == pp->root_bus_nr) {
>  		type = PCIE_ATU_TYPE_CFG0;
> -		cpu_addr = pp->cfg0_mod_base;
> +		cpu_addr = pp->cfg0_base;
>  		cfg_size = pp->cfg0_size;
>  		va_cfg_base = pp->va_cfg0_base;
>  	} else {
>  		type = PCIE_ATU_TYPE_CFG1;
> -		cpu_addr = pp->cfg1_mod_base;
> +		cpu_addr = pp->cfg1_base;
>  		cfg_size = pp->cfg1_size;
>  		va_cfg_base = pp->va_cfg1_base;
>  	}
> @@ -594,7 +573,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  				  busdev, cfg_size);
>  	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
>  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> +				  PCIE_ATU_TYPE_IO, pp->io_base,
>  				  pp->io_bus_addr, pp->io_size);
>  
>  	return ret;
> @@ -626,7 +605,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
>  static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
>  			int size, u32 *val)
>  {
> -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> +	struct pcie_port *pp = bus->sysdata;
>  	int ret;
>  
>  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
> @@ -650,7 +629,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
>  static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
>  			int where, int size, u32 val)
>  {
> -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> +	struct pcie_port *pp = bus->sysdata;
>  	int ret;
>  
>  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
> @@ -674,62 +653,6 @@ static struct pci_ops dw_pcie_ops = {
>  	.write = dw_pcie_wr_conf,
>  };
>  
> -static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
> -{
> -	struct pcie_port *pp;
> -
> -	pp = sys_to_pcie(sys);
> -
> -	if (global_io_offset < SZ_1M && pp->io_size > 0) {
> -		sys->io_offset = global_io_offset - pp->io_bus_addr;
> -		pci_ioremap_io(global_io_offset, pp->io_base);
> -		global_io_offset += SZ_64K;
> -		pci_add_resource_offset(&sys->resources, &pp->io,
> -					sys->io_offset);
> -	}
> -
> -	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
> -	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
> -	pci_add_resource(&sys->resources, &pp->busn);
> -
> -	return 1;
> -}
> -
> -static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
> -{
> -	struct pci_bus *bus;
> -	struct pcie_port *pp = sys_to_pcie(sys);
> -
> -	pp->root_bus_nr = sys->busnr;
> -	bus = pci_scan_root_bus(pp->dev, sys->busnr,
> -				  &dw_pcie_ops, sys, &sys->resources);
> -	if (!bus)
> -		return NULL;
> -
> -	if (bus && pp->ops->scan_bus)
> -		pp->ops->scan_bus(pp);
> -
> -	return bus;
> -}
> -
> -static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> -{
> -	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
> -	int irq;
> -
> -	irq = of_irq_parse_and_map_pci(dev, slot, pin);
> -	if (!irq)
> -		irq = pp->irq;
> -
> -	return irq;
> -}
> -
> -static struct hw_pci dw_pci = {
> -	.setup		= dw_pcie_setup,
> -	.scan		= dw_pcie_scan_bus,
> -	.map_irq	= dw_pcie_map_irq,
> -};
> -
>  void dw_pcie_setup_rc(struct pcie_port *pp)
>  {
>  	u32 val;
> diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
> index d0bbd27..264c969 100644
> --- a/drivers/pci/host/pcie-designware.h
> +++ b/drivers/pci/host/pcie-designware.h
> @@ -27,25 +27,21 @@ struct pcie_port {
>  	u8			root_bus_nr;
>  	void __iomem		*dbi_base;
>  	u64			cfg0_base;
> -	u64			cfg0_mod_base;
>  	void __iomem		*va_cfg0_base;
>  	u32			cfg0_size;
>  	u64			cfg1_base;
> -	u64			cfg1_mod_base;
>  	void __iomem		*va_cfg1_base;
>  	u32			cfg1_size;
> -	u64			io_base;
> -	u64			io_mod_base;
> +	resource_size_t		io_base;
>  	phys_addr_t		io_bus_addr;
>  	u32			io_size;
>  	u64			mem_base;
> -	u64			mem_mod_base;
>  	phys_addr_t		mem_bus_addr;
>  	u32			mem_size;
> -	struct resource		cfg;
> -	struct resource		io;
> -	struct resource		mem;
> -	struct resource		busn;
> +	struct resource		*cfg;
> +	struct resource		*io;
> +	struct resource		*mem;
> +	struct resource		*busn;
>  	int			irq;
>  	u32			lanes;
>  	struct pcie_host_ops	*ops;
> diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
> index c49fbdc..03eb204 100644
> --- a/drivers/pci/host/pcie-spear13xx.c
> +++ b/drivers/pci/host/pcie-spear13xx.c
> @@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
>  		return ret;
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &spear13xx_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> 



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

* [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-19 12:20     ` Zhou Wang
  0 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-19 12:20 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Pratyush and Jingoo,

what is your opinion about this patch? It will be very appreciated if you
could take a look at it.

Thanks,
Zhou

On 2015/8/17 19:55, Zhou Wang wrote:
> This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete
> function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci,
> move related operations to dw_pcie_host_init.
> 
> In past, we use:
> pci_common_init_dev
> 	-> pcibios_init_hw
> 		-> hw->scan (dw_pcie_scan_bus)
> to pass 0 to root_bus_nr in struct pcie_port. This patch set pp->root_bus_nr = 0
> in each PCIe host driver which is based on pcie-designware.
> 
> This patch also try to use of_pci_get_host_bridge_resources for ARM32 and ARM64
> according to the suggestion for Gabriele[1]
> 
> Finally this patch reverts commit f4c55c5a3f7f "PCI: designware: Program ATU
> with untranslated address" based on 1/6 in this series. we delete *_mod_base in
> pcie-designware. This was discussed in [2]
> 
> I have compiled the driver with multi_v7_defconfig. However, I don't have
> ARM32 PCIe related board to do test. It will be appreciated if someone could
> help to test it.
> 
> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Tested-By: James Morse <james.morse@arm.com>
> 
> [1] http://www.spinics.net/lists/linux-pci/msg42194.html
> [2] http://www.spinics.net/lists/arm-kernel/msg436779.html
> ---
>  drivers/pci/host/pci-dra7xx.c      |  15 +--
>  drivers/pci/host/pci-exynos.c      |   2 +-
>  drivers/pci/host/pci-imx6.c        |   2 +-
>  drivers/pci/host/pci-keystone-dw.c |   2 +-
>  drivers/pci/host/pci-keystone.c    |   2 +-
>  drivers/pci/host/pci-layerscape.c  |   2 +-
>  drivers/pci/host/pcie-designware.c | 229 ++++++++++++-------------------------
>  drivers/pci/host/pcie-designware.h |  14 +--
>  drivers/pci/host/pcie-spear13xx.c  |   2 +-
>  9 files changed, 95 insertions(+), 175 deletions(-)
> 
> diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
> index 18ae7ff..1268c69 100644
> --- a/drivers/pci/host/pci-dra7xx.c
> +++ b/drivers/pci/host/pci-dra7xx.c
> @@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp)
>  {
>  	dw_pcie_setup_rc(pp);
>  
> -	if (pp->io_mod_base)
> -		pp->io_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->io_base)
> +		pp->io_base &= CPU_TO_BUS_ADDR;
>  
> -	if (pp->mem_mod_base)
> -		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->mem_base)
> +		pp->mem_base &= CPU_TO_BUS_ADDR;
>  
> -	if (pp->cfg0_mod_base) {
> -		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
> -		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->cfg0_base) {
> +		pp->cfg0_base &= CPU_TO_BUS_ADDR;
> +		pp->cfg1_base &= CPU_TO_BUS_ADDR;
>  	}
>  
>  	dra7xx_pcie_establish_link(pp);
> @@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
>  
>  	pp = &dra7xx->pp;
>  	pp->dev = dev;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &dra7xx_pcie_host_ops;
>  
>  	pp->irq = platform_get_irq(pdev, 1);
> diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
> index f9f468d..9771bb0 100644
> --- a/drivers/pci/host/pci-exynos.c
> +++ b/drivers/pci/host/pci-exynos.c
> @@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
>  		}
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &exynos_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
> index 233a196..bec256c 100644
> --- a/drivers/pci/host/pci-imx6.c
> +++ b/drivers/pci/host/pci-imx6.c
> @@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
>  		}
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &imx6_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c
> index f34892e..b1e4135 100644
> --- a/drivers/pci/host/pci-keystone-dw.c
> +++ b/drivers/pci/host/pci-keystone-dw.c
> @@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void __iomem *reg_virt)
>  void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
>  {
>  	struct pcie_port *pp = &ks_pcie->pp;
> -	u32 start = pp->mem.start, end = pp->mem.end;
> +	u32 start = pp->mem->start, end = pp->mem->end;
>  	int i, tr_size;
>  
>  	/* Disable BARs for inbound access */
> diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
> index 734da58..8113832 100644
> --- a/drivers/pci/host/pci-keystone.c
> +++ b/drivers/pci/host/pci-keystone.c
> @@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
>  			return ret;
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &keystone_pcie_host_ops;
>  	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
>  	if (ret) {
> diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
> index b2328ea1..79ff08c 100644
> --- a/drivers/pci/host/pci-layerscape.c
> +++ b/drivers/pci/host/pci-layerscape.c
> @@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
>  	pp = &pcie->pp;
>  	pp->dev = pcie->dev;
>  	pp->dbi_base = pcie->dbi;
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &ls_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
> index c5d407c..e71a88e 100644
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c
> @@ -11,6 +11,7 @@
>   * published by the Free Software Foundation.
>   */
>  
> +#include <linux/hardirq.h>
>  #include <linux/irq.h>
>  #include <linux/irqdomain.h>
>  #include <linux/kernel.h>
> @@ -69,16 +70,7 @@
>  #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
>  #define PCIE_ATU_UPPER_TARGET		0x91C
>  
> -static struct hw_pci dw_pci;
> -
> -static unsigned long global_io_offset;
> -
> -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
> -{
> -	BUG_ON(!sys->private_data);
> -
> -	return sys->private_data;
> -}
> +static struct pci_ops dw_pcie_ops;
>  
>  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
>  {
> @@ -255,7 +247,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
>  static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
>  {
>  	int irq, pos0, i;
> -	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
> +	struct pcie_port *pp = desc->dev->bus->sysdata;
>  
>  	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
>  				       order_base_2(no_irqs));
> @@ -298,7 +290,7 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
>  {
>  	int irq, pos;
>  	struct msi_msg msg;
> -	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
> +	struct pcie_port *pp = pdev->bus->sysdata;
>  
>  	if (desc->msi_attrib.is_msix)
>  		return -EINVAL;
> @@ -327,7 +319,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
>  {
>  	struct irq_data *data = irq_get_irq_data(irq);
>  	struct msi_desc *msi = irq_data_get_msi(data);
> -	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
> +	struct pcie_port *pp = msi->dev->bus->sysdata;
>  
>  	clear_irq_range(pp, irq, 1, data->hwirq);
>  }
> @@ -363,14 +355,12 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  {
>  	struct device_node *np = pp->dev->of_node;
>  	struct platform_device *pdev = to_platform_device(pp->dev);
> -	struct of_pci_range range;
> -	struct of_pci_range_parser parser;
> +	struct pci_bus *bus;
>  	struct resource *cfg_res;
> -	u32 val, ns;
> -	const __be32 *addrp;
> -	int i, index, ret;
> -
> -	ns = of_n_size_cells(np);
> +	LIST_HEAD(res);
> +	u32 val;
> +	int i, ret;
> +	struct resource_entry *win;
>  
>  	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
>  	if (cfg_res) {
> @@ -378,85 +368,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  		pp->cfg1_size = resource_size(cfg_res)/2;
>  		pp->cfg0_base = cfg_res->start;
>  		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
> -
> -		/* Find the untranslated configuration space address */
> -		index = of_property_match_string(np, "reg-names", "config");
> -		addrp = of_get_address(np, index, NULL, NULL);
> -		pp->cfg0_mod_base = of_read_number(addrp, ns);
> -		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
>  	} else {
>  		dev_err(pp->dev, "missing *config* reg space\n");
>  	}
>  
> -	if (of_pci_range_parser_init(&parser, np)) {
> -		dev_err(pp->dev, "missing ranges property\n");
> -		return -EINVAL;
> -	}
> +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
> +	if (ret)
> +		return ret;
>  
>  	/* Get the I/O and memory ranges from DT */
> -	for_each_of_pci_range(&parser, &range) {
> -		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
> -
> -		if (restype == IORESOURCE_IO) {
> -			of_pci_range_to_resource(&range, np, &pp->io);
> -			pp->io.name = "I/O";
> -			pp->io.start = max_t(resource_size_t,
> -					     PCIBIOS_MIN_IO,
> -					     range.pci_addr + global_io_offset);
> -			pp->io.end = min_t(resource_size_t,
> -					   IO_SPACE_LIMIT,
> -					   range.pci_addr + range.size
> -					   + global_io_offset - 1);
> -			pp->io_size = resource_size(&pp->io);
> -			pp->io_bus_addr = range.pci_addr;
> -			pp->io_base = range.cpu_addr;
> -
> -			/* Find the untranslated IO space address */
> -			pp->io_mod_base = range.cpu_addr;
> -		}
> -		if (restype == IORESOURCE_MEM) {
> -			of_pci_range_to_resource(&range, np, &pp->mem);
> -			pp->mem.name = "MEM";
> -			pp->mem_size = resource_size(&pp->mem);
> -			pp->mem_bus_addr = range.pci_addr;
> -
> -			/* Find the untranslated MEM space address */
> -			pp->mem_mod_base = range.cpu_addr;
> -		}
> -		if (restype == 0) {
> -			of_pci_range_to_resource(&range, np, &pp->cfg);
> -			pp->cfg0_size = resource_size(&pp->cfg)/2;
> -			pp->cfg1_size = resource_size(&pp->cfg)/2;
> -			pp->cfg0_base = pp->cfg.start;
> -			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
> -
> -			/* Find the untranslated configuration space address */
> -			pp->cfg0_mod_base = range.cpu_addr;
> -			pp->cfg1_mod_base = pp->cfg0_mod_base +
> -					    pp->cfg0_size;
> +	resource_list_for_each_entry(win, &res) {
> +		switch (resource_type(win->res)) {
> +		case IORESOURCE_IO:
> +			pp->io = win->res;
> +			pp->io->name = "I/O";
> +			pp->io_size = resource_size(pp->io);
> +			pp->io_bus_addr = pp->io->start - win->offset;
> +			ret = pci_remap_iospace(pp->io, pp->io_base);
> +			if (ret) {
> +				dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
> +					 ret, pp->io);
> +				continue;
> +			}
> +			break;
> +		case IORESOURCE_MEM:
> +			pp->mem = win->res;
> +			pp->mem->name = "MEM";
> +			pp->mem_size = resource_size(pp->mem);
> +			pp->mem_bus_addr = pp->mem->start - win->offset;
> +			break;
> +		case 0:
> +			pp->cfg = win->res;
> +			pp->cfg0_size = resource_size(pp->cfg)/2;
> +			pp->cfg1_size = resource_size(pp->cfg)/2;
> +			pp->cfg0_base = pp->cfg->start;
> +			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
> +			break;
> +		case IORESOURCE_BUS:
> +			pp->busn = win->res;
> +			break;
> +		default:
> +			continue;
>  		}
>  	}
>  
> -	ret = of_pci_parse_bus_range(np, &pp->busn);
> -	if (ret < 0) {
> -		pp->busn.name = np->name;
> -		pp->busn.start = 0;
> -		pp->busn.end = 0xff;
> -		pp->busn.flags = IORESOURCE_BUS;
> -		dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n",
> -			ret, &pp->busn);
> -	}
> -
>  	if (!pp->dbi_base) {
> -		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
> -					resource_size(&pp->cfg));
> +		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
> +					resource_size(pp->cfg));
>  		if (!pp->dbi_base) {
>  			dev_err(pp->dev, "error with ioremap\n");
>  			return -ENOMEM;
>  		}
>  	}
>  
> -	pp->mem_base = pp->mem.start;
> +	pp->mem_base = pp->mem->start;
>  
>  	if (!pp->va_cfg0_base) {
>  		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
> @@ -505,7 +470,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  
>  	if (!pp->ops->rd_other_conf)
>  		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
> -					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
> +					  PCIE_ATU_TYPE_MEM, pp->mem_base,
>  					  pp->mem_bus_addr, pp->mem_size);
>  
>  	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
> @@ -517,15 +482,29 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  	val |= PORT_LOGIC_SPEED_CHANGE;
>  	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
>  
> -#ifdef CONFIG_PCI_MSI
> +	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
> +				  pp, &res);
> +	if (!bus)
> +		return -ENOMEM;
> +
> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> +	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
> +#else
>  	dw_pcie_msi_chip.dev = pp->dev;
> -	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> +	bus->msi = &dw_pcie_msi_chip;
>  #endif
>  
> -	dw_pci.nr_controllers = 1;
> -	dw_pci.private_data = (void **)&pp;
> +	pci_scan_child_bus(bus);
> +	if (pp->ops->scan_bus)
> +		pp->ops->scan_bus(pp);
> +
> +#ifdef CONFIG_ARM
> +	/* support old dtbs that incorrectly describe IRQs */
> +	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
> +#endif
>  
> -	pci_common_init_dev(pp->dev, &dw_pci);
> +	pci_assign_unassigned_bus_resources(bus);
> +	pci_bus_add_devices(bus);
>  
>  	return 0;
>  }
> @@ -544,12 +523,12 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  
>  	if (bus->parent->number == pp->root_bus_nr) {
>  		type = PCIE_ATU_TYPE_CFG0;
> -		cpu_addr = pp->cfg0_mod_base;
> +		cpu_addr = pp->cfg0_base;
>  		cfg_size = pp->cfg0_size;
>  		va_cfg_base = pp->va_cfg0_base;
>  	} else {
>  		type = PCIE_ATU_TYPE_CFG1;
> -		cpu_addr = pp->cfg1_mod_base;
> +		cpu_addr = pp->cfg1_base;
>  		cfg_size = pp->cfg1_size;
>  		va_cfg_base = pp->va_cfg1_base;
>  	}
> @@ -559,7 +538,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  				  busdev, cfg_size);
>  	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
>  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> +				  PCIE_ATU_TYPE_IO, pp->io_base,
>  				  pp->io_bus_addr, pp->io_size);
>  
>  	return ret;
> @@ -579,12 +558,12 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  
>  	if (bus->parent->number == pp->root_bus_nr) {
>  		type = PCIE_ATU_TYPE_CFG0;
> -		cpu_addr = pp->cfg0_mod_base;
> +		cpu_addr = pp->cfg0_base;
>  		cfg_size = pp->cfg0_size;
>  		va_cfg_base = pp->va_cfg0_base;
>  	} else {
>  		type = PCIE_ATU_TYPE_CFG1;
> -		cpu_addr = pp->cfg1_mod_base;
> +		cpu_addr = pp->cfg1_base;
>  		cfg_size = pp->cfg1_size;
>  		va_cfg_base = pp->va_cfg1_base;
>  	}
> @@ -594,7 +573,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  				  busdev, cfg_size);
>  	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
>  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> +				  PCIE_ATU_TYPE_IO, pp->io_base,
>  				  pp->io_bus_addr, pp->io_size);
>  
>  	return ret;
> @@ -626,7 +605,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
>  static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
>  			int size, u32 *val)
>  {
> -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> +	struct pcie_port *pp = bus->sysdata;
>  	int ret;
>  
>  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
> @@ -650,7 +629,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
>  static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
>  			int where, int size, u32 val)
>  {
> -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> +	struct pcie_port *pp = bus->sysdata;
>  	int ret;
>  
>  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
> @@ -674,62 +653,6 @@ static struct pci_ops dw_pcie_ops = {
>  	.write = dw_pcie_wr_conf,
>  };
>  
> -static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
> -{
> -	struct pcie_port *pp;
> -
> -	pp = sys_to_pcie(sys);
> -
> -	if (global_io_offset < SZ_1M && pp->io_size > 0) {
> -		sys->io_offset = global_io_offset - pp->io_bus_addr;
> -		pci_ioremap_io(global_io_offset, pp->io_base);
> -		global_io_offset += SZ_64K;
> -		pci_add_resource_offset(&sys->resources, &pp->io,
> -					sys->io_offset);
> -	}
> -
> -	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
> -	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
> -	pci_add_resource(&sys->resources, &pp->busn);
> -
> -	return 1;
> -}
> -
> -static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
> -{
> -	struct pci_bus *bus;
> -	struct pcie_port *pp = sys_to_pcie(sys);
> -
> -	pp->root_bus_nr = sys->busnr;
> -	bus = pci_scan_root_bus(pp->dev, sys->busnr,
> -				  &dw_pcie_ops, sys, &sys->resources);
> -	if (!bus)
> -		return NULL;
> -
> -	if (bus && pp->ops->scan_bus)
> -		pp->ops->scan_bus(pp);
> -
> -	return bus;
> -}
> -
> -static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> -{
> -	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
> -	int irq;
> -
> -	irq = of_irq_parse_and_map_pci(dev, slot, pin);
> -	if (!irq)
> -		irq = pp->irq;
> -
> -	return irq;
> -}
> -
> -static struct hw_pci dw_pci = {
> -	.setup		= dw_pcie_setup,
> -	.scan		= dw_pcie_scan_bus,
> -	.map_irq	= dw_pcie_map_irq,
> -};
> -
>  void dw_pcie_setup_rc(struct pcie_port *pp)
>  {
>  	u32 val;
> diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
> index d0bbd27..264c969 100644
> --- a/drivers/pci/host/pcie-designware.h
> +++ b/drivers/pci/host/pcie-designware.h
> @@ -27,25 +27,21 @@ struct pcie_port {
>  	u8			root_bus_nr;
>  	void __iomem		*dbi_base;
>  	u64			cfg0_base;
> -	u64			cfg0_mod_base;
>  	void __iomem		*va_cfg0_base;
>  	u32			cfg0_size;
>  	u64			cfg1_base;
> -	u64			cfg1_mod_base;
>  	void __iomem		*va_cfg1_base;
>  	u32			cfg1_size;
> -	u64			io_base;
> -	u64			io_mod_base;
> +	resource_size_t		io_base;
>  	phys_addr_t		io_bus_addr;
>  	u32			io_size;
>  	u64			mem_base;
> -	u64			mem_mod_base;
>  	phys_addr_t		mem_bus_addr;
>  	u32			mem_size;
> -	struct resource		cfg;
> -	struct resource		io;
> -	struct resource		mem;
> -	struct resource		busn;
> +	struct resource		*cfg;
> +	struct resource		*io;
> +	struct resource		*mem;
> +	struct resource		*busn;
>  	int			irq;
>  	u32			lanes;
>  	struct pcie_host_ops	*ops;
> diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
> index c49fbdc..03eb204 100644
> --- a/drivers/pci/host/pcie-spear13xx.c
> +++ b/drivers/pci/host/pcie-spear13xx.c
> @@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
>  		return ret;
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &spear13xx_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> 

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

* Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
  2015-08-17 11:55   ` Zhou Wang
@ 2015-08-19 12:54     ` Lucas Stach
  -1 siblings, 0 replies; 53+ messages in thread
From: Lucas Stach @ 2015-08-19 12:54 UTC (permalink / raw)
  To: Zhou Wang
  Cc: Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, gabriele.paoloni, lorenzo.pieralisi,
	james.morse, Liviu.Dudau, jason, robh, linux-pci,
	linux-arm-kernel, devicetree, yuanzhichang, zhudacai, zhangjukuo,
	qiuzhenfa, liudongdong3, qiujiang, xuwei5, liguozhu

Am Montag, den 17.08.2015, 19:55 +0800 schrieb Zhou Wang:
> This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete
> function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci,
> move related operations to dw_pcie_host_init.
> 
> In past, we use:
> pci_common_init_dev
> 	-> pcibios_init_hw
> 		-> hw->scan (dw_pcie_scan_bus)
> to pass 0 to root_bus_nr in struct pcie_port. This patch set pp->root_bus_nr = 0
> in each PCIe host driver which is based on pcie-designware.
> 
This is incorrect at least if there are 2 instances of DW PCIe host in
the same SoC without using PCI domains. In that the case the bus range
determines the range of valid bus numbers per instance and the first
number is the root bus. Please look at the "bus-range" DT property in
the DW PCIe bindings.

Also we should finally remove this root-bus setup from the glue drivers
altogether. It's something that entirely belongs into the DW core code.

Regards,
Lucas

> This patch also try to use of_pci_get_host_bridge_resources for ARM32 and ARM64
> according to the suggestion for Gabriele[1]
> 
> Finally this patch reverts commit f4c55c5a3f7f "PCI: designware: Program ATU
> with untranslated address" based on 1/6 in this series. we delete *_mod_base in
> pcie-designware. This was discussed in [2]
> 
> I have compiled the driver with multi_v7_defconfig. However, I don't have
> ARM32 PCIe related board to do test. It will be appreciated if someone could
> help to test it.
> 
> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Tested-By: James Morse <james.morse@arm.com>
> 
> [1] http://www.spinics.net/lists/linux-pci/msg42194.html
> [2] http://www.spinics.net/lists/arm-kernel/msg436779.html
> ---
>  drivers/pci/host/pci-dra7xx.c      |  15 +--
>  drivers/pci/host/pci-exynos.c      |   2 +-
>  drivers/pci/host/pci-imx6.c        |   2 +-
>  drivers/pci/host/pci-keystone-dw.c |   2 +-
>  drivers/pci/host/pci-keystone.c    |   2 +-
>  drivers/pci/host/pci-layerscape.c  |   2 +-
>  drivers/pci/host/pcie-designware.c | 229 ++++++++++++-------------------------
>  drivers/pci/host/pcie-designware.h |  14 +--
>  drivers/pci/host/pcie-spear13xx.c  |   2 +-
>  9 files changed, 95 insertions(+), 175 deletions(-)
> 
> diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
> index 18ae7ff..1268c69 100644
> --- a/drivers/pci/host/pci-dra7xx.c
> +++ b/drivers/pci/host/pci-dra7xx.c
> @@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp)
>  {
>  	dw_pcie_setup_rc(pp);
>  
> -	if (pp->io_mod_base)
> -		pp->io_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->io_base)
> +		pp->io_base &= CPU_TO_BUS_ADDR;
>  
> -	if (pp->mem_mod_base)
> -		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->mem_base)
> +		pp->mem_base &= CPU_TO_BUS_ADDR;
>  
> -	if (pp->cfg0_mod_base) {
> -		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
> -		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->cfg0_base) {
> +		pp->cfg0_base &= CPU_TO_BUS_ADDR;
> +		pp->cfg1_base &= CPU_TO_BUS_ADDR;
>  	}
>  
>  	dra7xx_pcie_establish_link(pp);
> @@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
>  
>  	pp = &dra7xx->pp;
>  	pp->dev = dev;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &dra7xx_pcie_host_ops;
>  
>  	pp->irq = platform_get_irq(pdev, 1);
> diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
> index f9f468d..9771bb0 100644
> --- a/drivers/pci/host/pci-exynos.c
> +++ b/drivers/pci/host/pci-exynos.c
> @@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
>  		}
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &exynos_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
> index 233a196..bec256c 100644
> --- a/drivers/pci/host/pci-imx6.c
> +++ b/drivers/pci/host/pci-imx6.c
> @@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
>  		}
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &imx6_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c
> index f34892e..b1e4135 100644
> --- a/drivers/pci/host/pci-keystone-dw.c
> +++ b/drivers/pci/host/pci-keystone-dw.c
> @@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void __iomem *reg_virt)
>  void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
>  {
>  	struct pcie_port *pp = &ks_pcie->pp;
> -	u32 start = pp->mem.start, end = pp->mem.end;
> +	u32 start = pp->mem->start, end = pp->mem->end;
>  	int i, tr_size;
>  
>  	/* Disable BARs for inbound access */
> diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
> index 734da58..8113832 100644
> --- a/drivers/pci/host/pci-keystone.c
> +++ b/drivers/pci/host/pci-keystone.c
> @@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
>  			return ret;
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &keystone_pcie_host_ops;
>  	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
>  	if (ret) {
> diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
> index b2328ea1..79ff08c 100644
> --- a/drivers/pci/host/pci-layerscape.c
> +++ b/drivers/pci/host/pci-layerscape.c
> @@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
>  	pp = &pcie->pp;
>  	pp->dev = pcie->dev;
>  	pp->dbi_base = pcie->dbi;
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &ls_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
> index c5d407c..e71a88e 100644
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c
> @@ -11,6 +11,7 @@
>   * published by the Free Software Foundation.
>   */
>  
> +#include <linux/hardirq.h>
>  #include <linux/irq.h>
>  #include <linux/irqdomain.h>
>  #include <linux/kernel.h>
> @@ -69,16 +70,7 @@
>  #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
>  #define PCIE_ATU_UPPER_TARGET		0x91C
>  
> -static struct hw_pci dw_pci;
> -
> -static unsigned long global_io_offset;
> -
> -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
> -{
> -	BUG_ON(!sys->private_data);
> -
> -	return sys->private_data;
> -}
> +static struct pci_ops dw_pcie_ops;
>  
>  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
>  {
> @@ -255,7 +247,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
>  static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
>  {
>  	int irq, pos0, i;
> -	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
> +	struct pcie_port *pp = desc->dev->bus->sysdata;
>  
>  	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
>  				       order_base_2(no_irqs));
> @@ -298,7 +290,7 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
>  {
>  	int irq, pos;
>  	struct msi_msg msg;
> -	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
> +	struct pcie_port *pp = pdev->bus->sysdata;
>  
>  	if (desc->msi_attrib.is_msix)
>  		return -EINVAL;
> @@ -327,7 +319,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
>  {
>  	struct irq_data *data = irq_get_irq_data(irq);
>  	struct msi_desc *msi = irq_data_get_msi(data);
> -	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
> +	struct pcie_port *pp = msi->dev->bus->sysdata;
>  
>  	clear_irq_range(pp, irq, 1, data->hwirq);
>  }
> @@ -363,14 +355,12 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  {
>  	struct device_node *np = pp->dev->of_node;
>  	struct platform_device *pdev = to_platform_device(pp->dev);
> -	struct of_pci_range range;
> -	struct of_pci_range_parser parser;
> +	struct pci_bus *bus;
>  	struct resource *cfg_res;
> -	u32 val, ns;
> -	const __be32 *addrp;
> -	int i, index, ret;
> -
> -	ns = of_n_size_cells(np);
> +	LIST_HEAD(res);
> +	u32 val;
> +	int i, ret;
> +	struct resource_entry *win;
>  
>  	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
>  	if (cfg_res) {
> @@ -378,85 +368,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  		pp->cfg1_size = resource_size(cfg_res)/2;
>  		pp->cfg0_base = cfg_res->start;
>  		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
> -
> -		/* Find the untranslated configuration space address */
> -		index = of_property_match_string(np, "reg-names", "config");
> -		addrp = of_get_address(np, index, NULL, NULL);
> -		pp->cfg0_mod_base = of_read_number(addrp, ns);
> -		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
>  	} else {
>  		dev_err(pp->dev, "missing *config* reg space\n");
>  	}
>  
> -	if (of_pci_range_parser_init(&parser, np)) {
> -		dev_err(pp->dev, "missing ranges property\n");
> -		return -EINVAL;
> -	}
> +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
> +	if (ret)
> +		return ret;
>  
>  	/* Get the I/O and memory ranges from DT */
> -	for_each_of_pci_range(&parser, &range) {
> -		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
> -
> -		if (restype == IORESOURCE_IO) {
> -			of_pci_range_to_resource(&range, np, &pp->io);
> -			pp->io.name = "I/O";
> -			pp->io.start = max_t(resource_size_t,
> -					     PCIBIOS_MIN_IO,
> -					     range.pci_addr + global_io_offset);
> -			pp->io.end = min_t(resource_size_t,
> -					   IO_SPACE_LIMIT,
> -					   range.pci_addr + range.size
> -					   + global_io_offset - 1);
> -			pp->io_size = resource_size(&pp->io);
> -			pp->io_bus_addr = range.pci_addr;
> -			pp->io_base = range.cpu_addr;
> -
> -			/* Find the untranslated IO space address */
> -			pp->io_mod_base = range.cpu_addr;
> -		}
> -		if (restype == IORESOURCE_MEM) {
> -			of_pci_range_to_resource(&range, np, &pp->mem);
> -			pp->mem.name = "MEM";
> -			pp->mem_size = resource_size(&pp->mem);
> -			pp->mem_bus_addr = range.pci_addr;
> -
> -			/* Find the untranslated MEM space address */
> -			pp->mem_mod_base = range.cpu_addr;
> -		}
> -		if (restype == 0) {
> -			of_pci_range_to_resource(&range, np, &pp->cfg);
> -			pp->cfg0_size = resource_size(&pp->cfg)/2;
> -			pp->cfg1_size = resource_size(&pp->cfg)/2;
> -			pp->cfg0_base = pp->cfg.start;
> -			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
> -
> -			/* Find the untranslated configuration space address */
> -			pp->cfg0_mod_base = range.cpu_addr;
> -			pp->cfg1_mod_base = pp->cfg0_mod_base +
> -					    pp->cfg0_size;
> +	resource_list_for_each_entry(win, &res) {
> +		switch (resource_type(win->res)) {
> +		case IORESOURCE_IO:
> +			pp->io = win->res;
> +			pp->io->name = "I/O";
> +			pp->io_size = resource_size(pp->io);
> +			pp->io_bus_addr = pp->io->start - win->offset;
> +			ret = pci_remap_iospace(pp->io, pp->io_base);
> +			if (ret) {
> +				dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
> +					 ret, pp->io);
> +				continue;
> +			}
> +			break;
> +		case IORESOURCE_MEM:
> +			pp->mem = win->res;
> +			pp->mem->name = "MEM";
> +			pp->mem_size = resource_size(pp->mem);
> +			pp->mem_bus_addr = pp->mem->start - win->offset;
> +			break;
> +		case 0:
> +			pp->cfg = win->res;
> +			pp->cfg0_size = resource_size(pp->cfg)/2;
> +			pp->cfg1_size = resource_size(pp->cfg)/2;
> +			pp->cfg0_base = pp->cfg->start;
> +			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
> +			break;
> +		case IORESOURCE_BUS:
> +			pp->busn = win->res;
> +			break;
> +		default:
> +			continue;
>  		}
>  	}
>  
> -	ret = of_pci_parse_bus_range(np, &pp->busn);
> -	if (ret < 0) {
> -		pp->busn.name = np->name;
> -		pp->busn.start = 0;
> -		pp->busn.end = 0xff;
> -		pp->busn.flags = IORESOURCE_BUS;
> -		dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n",
> -			ret, &pp->busn);
> -	}
> -
>  	if (!pp->dbi_base) {
> -		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
> -					resource_size(&pp->cfg));
> +		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
> +					resource_size(pp->cfg));
>  		if (!pp->dbi_base) {
>  			dev_err(pp->dev, "error with ioremap\n");
>  			return -ENOMEM;
>  		}
>  	}
>  
> -	pp->mem_base = pp->mem.start;
> +	pp->mem_base = pp->mem->start;
>  
>  	if (!pp->va_cfg0_base) {
>  		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
> @@ -505,7 +470,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  
>  	if (!pp->ops->rd_other_conf)
>  		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
> -					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
> +					  PCIE_ATU_TYPE_MEM, pp->mem_base,
>  					  pp->mem_bus_addr, pp->mem_size);
>  
>  	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
> @@ -517,15 +482,29 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  	val |= PORT_LOGIC_SPEED_CHANGE;
>  	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
>  
> -#ifdef CONFIG_PCI_MSI
> +	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
> +				  pp, &res);
> +	if (!bus)
> +		return -ENOMEM;
> +
> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> +	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
> +#else
>  	dw_pcie_msi_chip.dev = pp->dev;
> -	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> +	bus->msi = &dw_pcie_msi_chip;
>  #endif
>  
> -	dw_pci.nr_controllers = 1;
> -	dw_pci.private_data = (void **)&pp;
> +	pci_scan_child_bus(bus);
> +	if (pp->ops->scan_bus)
> +		pp->ops->scan_bus(pp);
> +
> +#ifdef CONFIG_ARM
> +	/* support old dtbs that incorrectly describe IRQs */
> +	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
> +#endif
>  
> -	pci_common_init_dev(pp->dev, &dw_pci);
> +	pci_assign_unassigned_bus_resources(bus);
> +	pci_bus_add_devices(bus);
>  
>  	return 0;
>  }
> @@ -544,12 +523,12 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  
>  	if (bus->parent->number == pp->root_bus_nr) {
>  		type = PCIE_ATU_TYPE_CFG0;
> -		cpu_addr = pp->cfg0_mod_base;
> +		cpu_addr = pp->cfg0_base;
>  		cfg_size = pp->cfg0_size;
>  		va_cfg_base = pp->va_cfg0_base;
>  	} else {
>  		type = PCIE_ATU_TYPE_CFG1;
> -		cpu_addr = pp->cfg1_mod_base;
> +		cpu_addr = pp->cfg1_base;
>  		cfg_size = pp->cfg1_size;
>  		va_cfg_base = pp->va_cfg1_base;
>  	}
> @@ -559,7 +538,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  				  busdev, cfg_size);
>  	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
>  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> +				  PCIE_ATU_TYPE_IO, pp->io_base,
>  				  pp->io_bus_addr, pp->io_size);
>  
>  	return ret;
> @@ -579,12 +558,12 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  
>  	if (bus->parent->number == pp->root_bus_nr) {
>  		type = PCIE_ATU_TYPE_CFG0;
> -		cpu_addr = pp->cfg0_mod_base;
> +		cpu_addr = pp->cfg0_base;
>  		cfg_size = pp->cfg0_size;
>  		va_cfg_base = pp->va_cfg0_base;
>  	} else {
>  		type = PCIE_ATU_TYPE_CFG1;
> -		cpu_addr = pp->cfg1_mod_base;
> +		cpu_addr = pp->cfg1_base;
>  		cfg_size = pp->cfg1_size;
>  		va_cfg_base = pp->va_cfg1_base;
>  	}
> @@ -594,7 +573,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  				  busdev, cfg_size);
>  	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
>  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> +				  PCIE_ATU_TYPE_IO, pp->io_base,
>  				  pp->io_bus_addr, pp->io_size);
>  
>  	return ret;
> @@ -626,7 +605,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
>  static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
>  			int size, u32 *val)
>  {
> -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> +	struct pcie_port *pp = bus->sysdata;
>  	int ret;
>  
>  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
> @@ -650,7 +629,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
>  static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
>  			int where, int size, u32 val)
>  {
> -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> +	struct pcie_port *pp = bus->sysdata;
>  	int ret;
>  
>  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
> @@ -674,62 +653,6 @@ static struct pci_ops dw_pcie_ops = {
>  	.write = dw_pcie_wr_conf,
>  };
>  
> -static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
> -{
> -	struct pcie_port *pp;
> -
> -	pp = sys_to_pcie(sys);
> -
> -	if (global_io_offset < SZ_1M && pp->io_size > 0) {
> -		sys->io_offset = global_io_offset - pp->io_bus_addr;
> -		pci_ioremap_io(global_io_offset, pp->io_base);
> -		global_io_offset += SZ_64K;
> -		pci_add_resource_offset(&sys->resources, &pp->io,
> -					sys->io_offset);
> -	}
> -
> -	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
> -	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
> -	pci_add_resource(&sys->resources, &pp->busn);
> -
> -	return 1;
> -}
> -
> -static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
> -{
> -	struct pci_bus *bus;
> -	struct pcie_port *pp = sys_to_pcie(sys);
> -
> -	pp->root_bus_nr = sys->busnr;
> -	bus = pci_scan_root_bus(pp->dev, sys->busnr,
> -				  &dw_pcie_ops, sys, &sys->resources);
> -	if (!bus)
> -		return NULL;
> -
> -	if (bus && pp->ops->scan_bus)
> -		pp->ops->scan_bus(pp);
> -
> -	return bus;
> -}
> -
> -static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> -{
> -	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
> -	int irq;
> -
> -	irq = of_irq_parse_and_map_pci(dev, slot, pin);
> -	if (!irq)
> -		irq = pp->irq;
> -
> -	return irq;
> -}
> -
> -static struct hw_pci dw_pci = {
> -	.setup		= dw_pcie_setup,
> -	.scan		= dw_pcie_scan_bus,
> -	.map_irq	= dw_pcie_map_irq,
> -};
> -
>  void dw_pcie_setup_rc(struct pcie_port *pp)
>  {
>  	u32 val;
> diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
> index d0bbd27..264c969 100644
> --- a/drivers/pci/host/pcie-designware.h
> +++ b/drivers/pci/host/pcie-designware.h
> @@ -27,25 +27,21 @@ struct pcie_port {
>  	u8			root_bus_nr;
>  	void __iomem		*dbi_base;
>  	u64			cfg0_base;
> -	u64			cfg0_mod_base;
>  	void __iomem		*va_cfg0_base;
>  	u32			cfg0_size;
>  	u64			cfg1_base;
> -	u64			cfg1_mod_base;
>  	void __iomem		*va_cfg1_base;
>  	u32			cfg1_size;
> -	u64			io_base;
> -	u64			io_mod_base;
> +	resource_size_t		io_base;
>  	phys_addr_t		io_bus_addr;
>  	u32			io_size;
>  	u64			mem_base;
> -	u64			mem_mod_base;
>  	phys_addr_t		mem_bus_addr;
>  	u32			mem_size;
> -	struct resource		cfg;
> -	struct resource		io;
> -	struct resource		mem;
> -	struct resource		busn;
> +	struct resource		*cfg;
> +	struct resource		*io;
> +	struct resource		*mem;
> +	struct resource		*busn;
>  	int			irq;
>  	u32			lanes;
>  	struct pcie_host_ops	*ops;
> diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
> index c49fbdc..03eb204 100644
> --- a/drivers/pci/host/pcie-spear13xx.c
> +++ b/drivers/pci/host/pcie-spear13xx.c
> @@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
>  		return ret;
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &spear13xx_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);

-- 
Pengutronix e.K.             | Lucas Stach                 |
Industrial Linux Solutions   | http://www.pengutronix.de/  |

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

* [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-19 12:54     ` Lucas Stach
  0 siblings, 0 replies; 53+ messages in thread
From: Lucas Stach @ 2015-08-19 12:54 UTC (permalink / raw)
  To: linux-arm-kernel

Am Montag, den 17.08.2015, 19:55 +0800 schrieb Zhou Wang:
> This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete
> function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci,
> move related operations to dw_pcie_host_init.
> 
> In past, we use:
> pci_common_init_dev
> 	-> pcibios_init_hw
> 		-> hw->scan (dw_pcie_scan_bus)
> to pass 0 to root_bus_nr in struct pcie_port. This patch set pp->root_bus_nr = 0
> in each PCIe host driver which is based on pcie-designware.
> 
This is incorrect at least if there are 2 instances of DW PCIe host in
the same SoC without using PCI domains. In that the case the bus range
determines the range of valid bus numbers per instance and the first
number is the root bus. Please look at the "bus-range" DT property in
the DW PCIe bindings.

Also we should finally remove this root-bus setup from the glue drivers
altogether. It's something that entirely belongs into the DW core code.

Regards,
Lucas

> This patch also try to use of_pci_get_host_bridge_resources for ARM32 and ARM64
> according to the suggestion for Gabriele[1]
> 
> Finally this patch reverts commit f4c55c5a3f7f "PCI: designware: Program ATU
> with untranslated address" based on 1/6 in this series. we delete *_mod_base in
> pcie-designware. This was discussed in [2]
> 
> I have compiled the driver with multi_v7_defconfig. However, I don't have
> ARM32 PCIe related board to do test. It will be appreciated if someone could
> help to test it.
> 
> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Tested-By: James Morse <james.morse@arm.com>
> 
> [1] http://www.spinics.net/lists/linux-pci/msg42194.html
> [2] http://www.spinics.net/lists/arm-kernel/msg436779.html
> ---
>  drivers/pci/host/pci-dra7xx.c      |  15 +--
>  drivers/pci/host/pci-exynos.c      |   2 +-
>  drivers/pci/host/pci-imx6.c        |   2 +-
>  drivers/pci/host/pci-keystone-dw.c |   2 +-
>  drivers/pci/host/pci-keystone.c    |   2 +-
>  drivers/pci/host/pci-layerscape.c  |   2 +-
>  drivers/pci/host/pcie-designware.c | 229 ++++++++++++-------------------------
>  drivers/pci/host/pcie-designware.h |  14 +--
>  drivers/pci/host/pcie-spear13xx.c  |   2 +-
>  9 files changed, 95 insertions(+), 175 deletions(-)
> 
> diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
> index 18ae7ff..1268c69 100644
> --- a/drivers/pci/host/pci-dra7xx.c
> +++ b/drivers/pci/host/pci-dra7xx.c
> @@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp)
>  {
>  	dw_pcie_setup_rc(pp);
>  
> -	if (pp->io_mod_base)
> -		pp->io_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->io_base)
> +		pp->io_base &= CPU_TO_BUS_ADDR;
>  
> -	if (pp->mem_mod_base)
> -		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->mem_base)
> +		pp->mem_base &= CPU_TO_BUS_ADDR;
>  
> -	if (pp->cfg0_mod_base) {
> -		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
> -		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->cfg0_base) {
> +		pp->cfg0_base &= CPU_TO_BUS_ADDR;
> +		pp->cfg1_base &= CPU_TO_BUS_ADDR;
>  	}
>  
>  	dra7xx_pcie_establish_link(pp);
> @@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
>  
>  	pp = &dra7xx->pp;
>  	pp->dev = dev;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &dra7xx_pcie_host_ops;
>  
>  	pp->irq = platform_get_irq(pdev, 1);
> diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
> index f9f468d..9771bb0 100644
> --- a/drivers/pci/host/pci-exynos.c
> +++ b/drivers/pci/host/pci-exynos.c
> @@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
>  		}
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &exynos_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
> index 233a196..bec256c 100644
> --- a/drivers/pci/host/pci-imx6.c
> +++ b/drivers/pci/host/pci-imx6.c
> @@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
>  		}
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &imx6_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c
> index f34892e..b1e4135 100644
> --- a/drivers/pci/host/pci-keystone-dw.c
> +++ b/drivers/pci/host/pci-keystone-dw.c
> @@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void __iomem *reg_virt)
>  void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
>  {
>  	struct pcie_port *pp = &ks_pcie->pp;
> -	u32 start = pp->mem.start, end = pp->mem.end;
> +	u32 start = pp->mem->start, end = pp->mem->end;
>  	int i, tr_size;
>  
>  	/* Disable BARs for inbound access */
> diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
> index 734da58..8113832 100644
> --- a/drivers/pci/host/pci-keystone.c
> +++ b/drivers/pci/host/pci-keystone.c
> @@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
>  			return ret;
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &keystone_pcie_host_ops;
>  	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
>  	if (ret) {
> diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
> index b2328ea1..79ff08c 100644
> --- a/drivers/pci/host/pci-layerscape.c
> +++ b/drivers/pci/host/pci-layerscape.c
> @@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
>  	pp = &pcie->pp;
>  	pp->dev = pcie->dev;
>  	pp->dbi_base = pcie->dbi;
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &ls_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
> index c5d407c..e71a88e 100644
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c
> @@ -11,6 +11,7 @@
>   * published by the Free Software Foundation.
>   */
>  
> +#include <linux/hardirq.h>
>  #include <linux/irq.h>
>  #include <linux/irqdomain.h>
>  #include <linux/kernel.h>
> @@ -69,16 +70,7 @@
>  #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
>  #define PCIE_ATU_UPPER_TARGET		0x91C
>  
> -static struct hw_pci dw_pci;
> -
> -static unsigned long global_io_offset;
> -
> -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
> -{
> -	BUG_ON(!sys->private_data);
> -
> -	return sys->private_data;
> -}
> +static struct pci_ops dw_pcie_ops;
>  
>  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
>  {
> @@ -255,7 +247,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
>  static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
>  {
>  	int irq, pos0, i;
> -	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
> +	struct pcie_port *pp = desc->dev->bus->sysdata;
>  
>  	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
>  				       order_base_2(no_irqs));
> @@ -298,7 +290,7 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
>  {
>  	int irq, pos;
>  	struct msi_msg msg;
> -	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
> +	struct pcie_port *pp = pdev->bus->sysdata;
>  
>  	if (desc->msi_attrib.is_msix)
>  		return -EINVAL;
> @@ -327,7 +319,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
>  {
>  	struct irq_data *data = irq_get_irq_data(irq);
>  	struct msi_desc *msi = irq_data_get_msi(data);
> -	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
> +	struct pcie_port *pp = msi->dev->bus->sysdata;
>  
>  	clear_irq_range(pp, irq, 1, data->hwirq);
>  }
> @@ -363,14 +355,12 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  {
>  	struct device_node *np = pp->dev->of_node;
>  	struct platform_device *pdev = to_platform_device(pp->dev);
> -	struct of_pci_range range;
> -	struct of_pci_range_parser parser;
> +	struct pci_bus *bus;
>  	struct resource *cfg_res;
> -	u32 val, ns;
> -	const __be32 *addrp;
> -	int i, index, ret;
> -
> -	ns = of_n_size_cells(np);
> +	LIST_HEAD(res);
> +	u32 val;
> +	int i, ret;
> +	struct resource_entry *win;
>  
>  	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
>  	if (cfg_res) {
> @@ -378,85 +368,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  		pp->cfg1_size = resource_size(cfg_res)/2;
>  		pp->cfg0_base = cfg_res->start;
>  		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
> -
> -		/* Find the untranslated configuration space address */
> -		index = of_property_match_string(np, "reg-names", "config");
> -		addrp = of_get_address(np, index, NULL, NULL);
> -		pp->cfg0_mod_base = of_read_number(addrp, ns);
> -		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
>  	} else {
>  		dev_err(pp->dev, "missing *config* reg space\n");
>  	}
>  
> -	if (of_pci_range_parser_init(&parser, np)) {
> -		dev_err(pp->dev, "missing ranges property\n");
> -		return -EINVAL;
> -	}
> +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
> +	if (ret)
> +		return ret;
>  
>  	/* Get the I/O and memory ranges from DT */
> -	for_each_of_pci_range(&parser, &range) {
> -		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
> -
> -		if (restype == IORESOURCE_IO) {
> -			of_pci_range_to_resource(&range, np, &pp->io);
> -			pp->io.name = "I/O";
> -			pp->io.start = max_t(resource_size_t,
> -					     PCIBIOS_MIN_IO,
> -					     range.pci_addr + global_io_offset);
> -			pp->io.end = min_t(resource_size_t,
> -					   IO_SPACE_LIMIT,
> -					   range.pci_addr + range.size
> -					   + global_io_offset - 1);
> -			pp->io_size = resource_size(&pp->io);
> -			pp->io_bus_addr = range.pci_addr;
> -			pp->io_base = range.cpu_addr;
> -
> -			/* Find the untranslated IO space address */
> -			pp->io_mod_base = range.cpu_addr;
> -		}
> -		if (restype == IORESOURCE_MEM) {
> -			of_pci_range_to_resource(&range, np, &pp->mem);
> -			pp->mem.name = "MEM";
> -			pp->mem_size = resource_size(&pp->mem);
> -			pp->mem_bus_addr = range.pci_addr;
> -
> -			/* Find the untranslated MEM space address */
> -			pp->mem_mod_base = range.cpu_addr;
> -		}
> -		if (restype == 0) {
> -			of_pci_range_to_resource(&range, np, &pp->cfg);
> -			pp->cfg0_size = resource_size(&pp->cfg)/2;
> -			pp->cfg1_size = resource_size(&pp->cfg)/2;
> -			pp->cfg0_base = pp->cfg.start;
> -			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
> -
> -			/* Find the untranslated configuration space address */
> -			pp->cfg0_mod_base = range.cpu_addr;
> -			pp->cfg1_mod_base = pp->cfg0_mod_base +
> -					    pp->cfg0_size;
> +	resource_list_for_each_entry(win, &res) {
> +		switch (resource_type(win->res)) {
> +		case IORESOURCE_IO:
> +			pp->io = win->res;
> +			pp->io->name = "I/O";
> +			pp->io_size = resource_size(pp->io);
> +			pp->io_bus_addr = pp->io->start - win->offset;
> +			ret = pci_remap_iospace(pp->io, pp->io_base);
> +			if (ret) {
> +				dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
> +					 ret, pp->io);
> +				continue;
> +			}
> +			break;
> +		case IORESOURCE_MEM:
> +			pp->mem = win->res;
> +			pp->mem->name = "MEM";
> +			pp->mem_size = resource_size(pp->mem);
> +			pp->mem_bus_addr = pp->mem->start - win->offset;
> +			break;
> +		case 0:
> +			pp->cfg = win->res;
> +			pp->cfg0_size = resource_size(pp->cfg)/2;
> +			pp->cfg1_size = resource_size(pp->cfg)/2;
> +			pp->cfg0_base = pp->cfg->start;
> +			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
> +			break;
> +		case IORESOURCE_BUS:
> +			pp->busn = win->res;
> +			break;
> +		default:
> +			continue;
>  		}
>  	}
>  
> -	ret = of_pci_parse_bus_range(np, &pp->busn);
> -	if (ret < 0) {
> -		pp->busn.name = np->name;
> -		pp->busn.start = 0;
> -		pp->busn.end = 0xff;
> -		pp->busn.flags = IORESOURCE_BUS;
> -		dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n",
> -			ret, &pp->busn);
> -	}
> -
>  	if (!pp->dbi_base) {
> -		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
> -					resource_size(&pp->cfg));
> +		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
> +					resource_size(pp->cfg));
>  		if (!pp->dbi_base) {
>  			dev_err(pp->dev, "error with ioremap\n");
>  			return -ENOMEM;
>  		}
>  	}
>  
> -	pp->mem_base = pp->mem.start;
> +	pp->mem_base = pp->mem->start;
>  
>  	if (!pp->va_cfg0_base) {
>  		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
> @@ -505,7 +470,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  
>  	if (!pp->ops->rd_other_conf)
>  		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
> -					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
> +					  PCIE_ATU_TYPE_MEM, pp->mem_base,
>  					  pp->mem_bus_addr, pp->mem_size);
>  
>  	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
> @@ -517,15 +482,29 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  	val |= PORT_LOGIC_SPEED_CHANGE;
>  	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
>  
> -#ifdef CONFIG_PCI_MSI
> +	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
> +				  pp, &res);
> +	if (!bus)
> +		return -ENOMEM;
> +
> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> +	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
> +#else
>  	dw_pcie_msi_chip.dev = pp->dev;
> -	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> +	bus->msi = &dw_pcie_msi_chip;
>  #endif
>  
> -	dw_pci.nr_controllers = 1;
> -	dw_pci.private_data = (void **)&pp;
> +	pci_scan_child_bus(bus);
> +	if (pp->ops->scan_bus)
> +		pp->ops->scan_bus(pp);
> +
> +#ifdef CONFIG_ARM
> +	/* support old dtbs that incorrectly describe IRQs */
> +	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
> +#endif
>  
> -	pci_common_init_dev(pp->dev, &dw_pci);
> +	pci_assign_unassigned_bus_resources(bus);
> +	pci_bus_add_devices(bus);
>  
>  	return 0;
>  }
> @@ -544,12 +523,12 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  
>  	if (bus->parent->number == pp->root_bus_nr) {
>  		type = PCIE_ATU_TYPE_CFG0;
> -		cpu_addr = pp->cfg0_mod_base;
> +		cpu_addr = pp->cfg0_base;
>  		cfg_size = pp->cfg0_size;
>  		va_cfg_base = pp->va_cfg0_base;
>  	} else {
>  		type = PCIE_ATU_TYPE_CFG1;
> -		cpu_addr = pp->cfg1_mod_base;
> +		cpu_addr = pp->cfg1_base;
>  		cfg_size = pp->cfg1_size;
>  		va_cfg_base = pp->va_cfg1_base;
>  	}
> @@ -559,7 +538,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  				  busdev, cfg_size);
>  	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
>  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> +				  PCIE_ATU_TYPE_IO, pp->io_base,
>  				  pp->io_bus_addr, pp->io_size);
>  
>  	return ret;
> @@ -579,12 +558,12 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  
>  	if (bus->parent->number == pp->root_bus_nr) {
>  		type = PCIE_ATU_TYPE_CFG0;
> -		cpu_addr = pp->cfg0_mod_base;
> +		cpu_addr = pp->cfg0_base;
>  		cfg_size = pp->cfg0_size;
>  		va_cfg_base = pp->va_cfg0_base;
>  	} else {
>  		type = PCIE_ATU_TYPE_CFG1;
> -		cpu_addr = pp->cfg1_mod_base;
> +		cpu_addr = pp->cfg1_base;
>  		cfg_size = pp->cfg1_size;
>  		va_cfg_base = pp->va_cfg1_base;
>  	}
> @@ -594,7 +573,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  				  busdev, cfg_size);
>  	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
>  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> +				  PCIE_ATU_TYPE_IO, pp->io_base,
>  				  pp->io_bus_addr, pp->io_size);
>  
>  	return ret;
> @@ -626,7 +605,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
>  static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
>  			int size, u32 *val)
>  {
> -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> +	struct pcie_port *pp = bus->sysdata;
>  	int ret;
>  
>  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
> @@ -650,7 +629,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
>  static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
>  			int where, int size, u32 val)
>  {
> -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> +	struct pcie_port *pp = bus->sysdata;
>  	int ret;
>  
>  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
> @@ -674,62 +653,6 @@ static struct pci_ops dw_pcie_ops = {
>  	.write = dw_pcie_wr_conf,
>  };
>  
> -static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
> -{
> -	struct pcie_port *pp;
> -
> -	pp = sys_to_pcie(sys);
> -
> -	if (global_io_offset < SZ_1M && pp->io_size > 0) {
> -		sys->io_offset = global_io_offset - pp->io_bus_addr;
> -		pci_ioremap_io(global_io_offset, pp->io_base);
> -		global_io_offset += SZ_64K;
> -		pci_add_resource_offset(&sys->resources, &pp->io,
> -					sys->io_offset);
> -	}
> -
> -	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
> -	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
> -	pci_add_resource(&sys->resources, &pp->busn);
> -
> -	return 1;
> -}
> -
> -static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
> -{
> -	struct pci_bus *bus;
> -	struct pcie_port *pp = sys_to_pcie(sys);
> -
> -	pp->root_bus_nr = sys->busnr;
> -	bus = pci_scan_root_bus(pp->dev, sys->busnr,
> -				  &dw_pcie_ops, sys, &sys->resources);
> -	if (!bus)
> -		return NULL;
> -
> -	if (bus && pp->ops->scan_bus)
> -		pp->ops->scan_bus(pp);
> -
> -	return bus;
> -}
> -
> -static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> -{
> -	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
> -	int irq;
> -
> -	irq = of_irq_parse_and_map_pci(dev, slot, pin);
> -	if (!irq)
> -		irq = pp->irq;
> -
> -	return irq;
> -}
> -
> -static struct hw_pci dw_pci = {
> -	.setup		= dw_pcie_setup,
> -	.scan		= dw_pcie_scan_bus,
> -	.map_irq	= dw_pcie_map_irq,
> -};
> -
>  void dw_pcie_setup_rc(struct pcie_port *pp)
>  {
>  	u32 val;
> diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
> index d0bbd27..264c969 100644
> --- a/drivers/pci/host/pcie-designware.h
> +++ b/drivers/pci/host/pcie-designware.h
> @@ -27,25 +27,21 @@ struct pcie_port {
>  	u8			root_bus_nr;
>  	void __iomem		*dbi_base;
>  	u64			cfg0_base;
> -	u64			cfg0_mod_base;
>  	void __iomem		*va_cfg0_base;
>  	u32			cfg0_size;
>  	u64			cfg1_base;
> -	u64			cfg1_mod_base;
>  	void __iomem		*va_cfg1_base;
>  	u32			cfg1_size;
> -	u64			io_base;
> -	u64			io_mod_base;
> +	resource_size_t		io_base;
>  	phys_addr_t		io_bus_addr;
>  	u32			io_size;
>  	u64			mem_base;
> -	u64			mem_mod_base;
>  	phys_addr_t		mem_bus_addr;
>  	u32			mem_size;
> -	struct resource		cfg;
> -	struct resource		io;
> -	struct resource		mem;
> -	struct resource		busn;
> +	struct resource		*cfg;
> +	struct resource		*io;
> +	struct resource		*mem;
> +	struct resource		*busn;
>  	int			irq;
>  	u32			lanes;
>  	struct pcie_host_ops	*ops;
> diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
> index c49fbdc..03eb204 100644
> --- a/drivers/pci/host/pcie-spear13xx.c
> +++ b/drivers/pci/host/pcie-spear13xx.c
> @@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
>  		return ret;
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = 0;
>  	pp->ops = &spear13xx_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);

-- 
Pengutronix e.K.             | Lucas Stach                 |
Industrial Linux Solutions   | http://www.pengutronix.de/  |

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

* RE: [PATCH v7 3/6] PCI: designware: Add ARM64 support
  2015-08-19 12:54     ` Lucas Stach
  (?)
@ 2015-08-19 15:16       ` Gabriele Paoloni
  -1 siblings, 0 replies; 53+ messages in thread
From: Gabriele Paoloni @ 2015-08-19 15:16 UTC (permalink / raw)
  To: Lucas Stach, Wangzhou (B)
  Cc: Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, lorenzo.pieralisi, james.morse, Liviu.Dudau,
	jason, robh, linux-pci, linux-arm-kernel, devicetree,
	Yuanzhichang, Zhudacai, zhangjukuo, qiuzhenfa, liudongd

Hi Lucas

I have rewritten the patch to take into account multiple controllers.

As you can see now there is a static var in dw_pcie_host_init() that tracks
the bus numbers used.
Drivers that do not specify the bus range in the DTB set pp->root_bus_nr = DW_ROOT_NR_UNDEFINED.
Designware will check if the flag is set and will use the automatic bus range
assignment.
Instead if the driver assigns pp->root_bus_nr according to the dtb, designwware
will use the value passed in by the driver.
Below the relevant section:


+	static int root_bus_nr = 0;
...
+	mutex_lock(&root_bus_nr_mux);
+
+	if (pp->root_bus_nr != DW_ROOT_NR_UNDEFINED)
+		root_bus_nr = pp->root_bus_nr;
+
+	bus = pci_create_root_bus(pp->dev, root_bus_nr, &dw_pcie_ops,
+			      pp, &res);
+	if (!bus) {
+		mutex_unlock(&root_bus_nr_mux);
+		return -ENOMEM;
+	}
+
+	root_bus_nr += bus->busn_res.end + 1;
+	mutex_unlock(&root_bus_nr_mux);

Please let me know what you think...

Many Thanks

Gab
----------

From: gabriele paoloni <gabriele.paoloni@huawei.com>

This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete
function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci,
move related operations to dw_pcie_host_init.
Also set pp->root_bus_nr = DW_ROOT_NR_UNDEFINED in all the drivers that
are based on designware to flag that the drivers do not read the bus
ranges from DT.
This patch also adds handling of multiple PCI domains in designware.
if the PCI host bridge driver does not specify a root bus number, in case
of multiple domains, designware will automatillay set the next domain root
bus number to the last bus number used in the last domain + 1.

This patch also try to use of_pci_get_host_bridge_resources for ARM32 and
ARM64 according to the suggestion for Gabriele[1]

This patch is based on Gabriele's patch about of_pci_range fix[2]

Finally this patch reverts commit f4c55c5a3f7f "PCI: designware:
Program ATU with untranslated address". This was discussed in [3]

I have compiled the driver with multi_v7_defconfig. However, I don't have
ARM32 PCIe related board to do test. It will be appreciated if someone could
help to test it.

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>

[1] http://www.spinics.net/lists/linux-pci/msg42194.html
[2] https://patchwork.ozlabs.org/patch/495018/
[3] http://www.spinics.net/lists/arm-kernel/msg436779.html
---
 drivers/pci/host/pci-dra7xx.c      |  15 +--
 drivers/pci/host/pci-exynos.c      |   2 +-
 drivers/pci/host/pci-imx6.c        |   2 +-
 drivers/pci/host/pci-keystone-dw.c |   2 +-
 drivers/pci/host/pci-keystone.c    |   2 +-
 drivers/pci/host/pci-layerscape.c  |   2 +-
 drivers/pci/host/pcie-designware.c | 247 ++++++++++++++-----------------------
 drivers/pci/host/pcie-designware.h |  15 +--
 drivers/pci/host/pcie-spear13xx.c  |   2 +-
 9 files changed, 110 insertions(+), 179 deletions(-)

diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
index 5678b57..8d598fb 100644
--- a/drivers/pci/host/pci-dra7xx.c
+++ b/drivers/pci/host/pci-dra7xx.c
@@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp)
 {
 	dw_pcie_setup_rc(pp);
 
-	if (pp->io_mod_base)
-		pp->io_mod_base &= CPU_TO_BUS_ADDR;
+	if (pp->io_base)
+		pp->io_base &= CPU_TO_BUS_ADDR;
 
-	if (pp->mem_mod_base)
-		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
+	if (pp->mem_base)
+		pp->mem_base &= CPU_TO_BUS_ADDR;
 
-	if (pp->cfg0_mod_base) {
-		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
-		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
+	if (pp->cfg0_base) {
+		pp->cfg0_base &= CPU_TO_BUS_ADDR;
+		pp->cfg1_base &= CPU_TO_BUS_ADDR;
 	}
 
 	dra7xx_pcie_establish_link(pp);
@@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
 
 	pp = &dra7xx->pp;
 	pp->dev = dev;
+	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
 	pp->ops = &dra7xx_pcie_host_ops;
 
 	pp->irq = platform_get_irq(pdev, 1);
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
index f9f468d..ed03a8f 100644
--- a/drivers/pci/host/pci-exynos.c
+++ b/drivers/pci/host/pci-exynos.c
@@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
 	pp->ops = &exynos_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index 233a196..0efac85 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
 	pp->ops = &imx6_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c
index f34892e..b1e4135 100644
--- a/drivers/pci/host/pci-keystone-dw.c
+++ b/drivers/pci/host/pci-keystone-dw.c
@@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void __iomem *reg_virt)
 void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
 {
 	struct pcie_port *pp = &ks_pcie->pp;
-	u32 start = pp->mem.start, end = pp->mem.end;
+	u32 start = pp->mem->start, end = pp->mem->end;
 	int i, tr_size;
 
 	/* Disable BARs for inbound access */
diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
index 734da58..b522956 100644
--- a/drivers/pci/host/pci-keystone.c
+++ b/drivers/pci/host/pci-keystone.c
@@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
 			return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
 	pp->ops = &keystone_pcie_host_ops;
 	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
 	if (ret) {
diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
index b2328ea1..dd92ffa 100644
--- a/drivers/pci/host/pci-layerscape.c
+++ b/drivers/pci/host/pci-layerscape.c
@@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
 	pp = &pcie->pp;
 	pp->dev = pcie->dev;
 	pp->dbi_base = pcie->dbi;
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
 	pp->ops = &ls_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 5307b35..bd2606b 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/hardirq.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
@@ -69,16 +70,9 @@
 #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
 #define PCIE_ATU_UPPER_TARGET		0x91C
 
-static struct hw_pci dw_pci;
+static struct pci_ops dw_pcie_ops;
 
-static unsigned long global_io_offset;
-
-static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
-{
-	BUG_ON(!sys->private_data);
-
-	return sys->private_data;
-}
+DEFINE_MUTEX(root_bus_nr_mux);
 
 int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
 {
@@ -255,7 +249,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
 static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
 {
 	int irq, pos0, i;
-	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
+	struct pcie_port *pp = desc->dev->bus->sysdata;
 
 	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
 				       order_base_2(no_irqs));
@@ -298,7 +292,7 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
 {
 	int irq, pos;
 	struct msi_msg msg;
-	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
+	struct pcie_port *pp = pdev->bus->sysdata;
 
 	if (desc->msi_attrib.is_msix)
 		return -EINVAL;
@@ -327,7 +321,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
 {
 	struct irq_data *data = irq_get_irq_data(irq);
 	struct msi_desc *msi = irq_data_get_msi(data);
-	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
+	struct pcie_port *pp = msi->dev->bus->sysdata;
 
 	clear_irq_range(pp, irq, 1, data->hwirq);
 }
@@ -359,22 +353,17 @@ static const struct irq_domain_ops msi_domain_ops = {
 	.map = dw_pcie_msi_map,
 };
 
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);
-	struct of_pci_range range;
-	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
 	struct resource *cfg_res;
-	u32 val, na, ns;
-	const __be32 *addrp;
-	int i, index, ret;
-
-	/* Find the address cell size and the number of cells in order to get
-	 * the untranslated address.
-	 */
-	of_property_read_u32(np, "#address-cells", &na);
-	ns = of_n_size_cells(np);
+	LIST_HEAD(res);
+	u32 val;
+	int i, ret;
+	struct resource_entry *win;
+	static int root_bus_nr = 0;
 
 	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
 	if (cfg_res) {
@@ -382,85 +371,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
 		pp->cfg1_size = resource_size(cfg_res)/2;
 		pp->cfg0_base = cfg_res->start;
 		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
-
-		/* Find the untranslated configuration space address */
-		index = of_property_match_string(np, "reg-names", "config");
-		addrp = of_get_address(np, index, NULL, NULL);
-		pp->cfg0_mod_base = of_read_number(addrp, ns);
-		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
 	} else {
 		dev_err(pp->dev, "missing *config* reg space\n");
 	}
 
-	if (of_pci_range_parser_init(&parser, np)) {
-		dev_err(pp->dev, "missing ranges property\n");
-		return -EINVAL;
-	}
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
+	if (ret)
+		return ret;
 
 	/* Get the I/O and memory ranges from DT */
-	for_each_of_pci_range(&parser, &range) {
-		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
-
-		if (restype == IORESOURCE_IO) {
-			of_pci_range_to_resource(&range, np, &pp->io);
-			pp->io.name = "I/O";
-			pp->io.start = max_t(resource_size_t,
-					     PCIBIOS_MIN_IO,
-					     range.pci_addr + global_io_offset);
-			pp->io.end = min_t(resource_size_t,
-					   IO_SPACE_LIMIT,
-					   range.pci_addr + range.size
-					   + global_io_offset - 1);
-			pp->io_size = resource_size(&pp->io);
-			pp->io_bus_addr = range.pci_addr;
-			pp->io_base = range.cpu_addr;
-
-			/* Find the untranslated IO space address */
-			pp->io_mod_base = range.cpu_addr;
-		}
-		if (restype == IORESOURCE_MEM) {
-			of_pci_range_to_resource(&range, np, &pp->mem);
-			pp->mem.name = "MEM";
-			pp->mem_size = resource_size(&pp->mem);
-			pp->mem_bus_addr = range.pci_addr;
-
-			/* Find the untranslated MEM space address */
-			pp->mem_mod_base = range.cpu_addr;
-		}
-		if (restype == 0) {
-			of_pci_range_to_resource(&range, np, &pp->cfg);
-			pp->cfg0_size = resource_size(&pp->cfg)/2;
-			pp->cfg1_size = resource_size(&pp->cfg)/2;
-			pp->cfg0_base = pp->cfg.start;
-			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
-
-			/* Find the untranslated configuration space address */
-			pp->cfg0_mod_base = range.cpu_addr;
-			pp->cfg1_mod_base = pp->cfg0_mod_base +
-					    pp->cfg0_size;
+	resource_list_for_each_entry(win, &res) {
+		switch (resource_type(win->res)) {
+		case IORESOURCE_IO:
+			pp->io = win->res;
+			pp->io->name = "I/O";
+			pp->io_size = resource_size(pp->io);
+			pp->io_bus_addr = pp->io->start - win->offset;
+			ret = pci_remap_iospace(pp->io, pp->io_base);
+			if (ret) {
+				dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
+					 ret, pp->io);
+				continue;
+			}
+			break;
+		case IORESOURCE_MEM:
+			pp->mem = win->res;
+			pp->mem->name = "MEM";
+			pp->mem_size = resource_size(pp->mem);
+			pp->mem_bus_addr = pp->mem->start - win->offset;
+			break;
+		case 0:
+			pp->cfg = win->res;
+			pp->cfg0_size = resource_size(pp->cfg)/2;
+			pp->cfg1_size = resource_size(pp->cfg)/2;
+			pp->cfg0_base = pp->cfg->start;
+			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
+			break;
+		case IORESOURCE_BUS:
+			pp->busn = win->res;
+			break;
+		default:
+			continue;
 		}
 	}
 
-	ret = of_pci_parse_bus_range(np, &pp->busn);
-	if (ret < 0) {
-		pp->busn.name = np->name;
-		pp->busn.start = 0;
-		pp->busn.end = 0xff;
-		pp->busn.flags = IORESOURCE_BUS;
-		dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n",
-			ret, &pp->busn);
-	}
-
 	if (!pp->dbi_base) {
-		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
-					resource_size(&pp->cfg));
+		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
+					resource_size(pp->cfg));
 		if (!pp->dbi_base) {
 			dev_err(pp->dev, "error with ioremap\n");
 			return -ENOMEM;
 		}
 	}
 
-	pp->mem_base = pp->mem.start;
+	pp->mem_base = pp->mem->start;
 
 	if (!pp->va_cfg0_base) {
 		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
@@ -509,7 +473,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
 
 	if (!pp->ops->rd_other_conf)
 		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
-					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
+					  PCIE_ATU_TYPE_MEM, pp->mem_base,
 					  pp->mem_bus_addr, pp->mem_size);
 
 	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
@@ -521,15 +485,40 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	val |= PORT_LOGIC_SPEED_CHANGE;
 	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
 	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+
+	mutex_lock(&root_bus_nr_mux);
+
+	if (pp->root_bus_nr != DW_ROOT_NR_UNDEFINED)
+		root_bus_nr = pp->root_bus_nr;
+
+	bus = pci_create_root_bus(pp->dev, root_bus_nr, &dw_pcie_ops,
+			      pp, &res);
+	if (!bus) {
+		mutex_unlock(&root_bus_nr_mux);
+		return -ENOMEM;
+	}
+
+	root_bus_nr += bus->busn_res.end + 1;
+	mutex_unlock(&root_bus_nr_mux);
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
+#else
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
+
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
 
-	pci_common_init_dev(pp->dev, &dw_pci);
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -548,12 +537,12 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 
 	if (bus->parent->number == pp->root_bus_nr) {
 		type = PCIE_ATU_TYPE_CFG0;
-		cpu_addr = pp->cfg0_mod_base;
+		cpu_addr = pp->cfg0_base;
 		cfg_size = pp->cfg0_size;
 		va_cfg_base = pp->va_cfg0_base;
 	} else {
 		type = PCIE_ATU_TYPE_CFG1;
-		cpu_addr = pp->cfg1_mod_base;
+		cpu_addr = pp->cfg1_base;
 		cfg_size = pp->cfg1_size;
 		va_cfg_base = pp->va_cfg1_base;
 	}
@@ -563,7 +552,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 				  busdev, cfg_size);
 	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
 	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
-				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
+				  PCIE_ATU_TYPE_IO, pp->io_base,
 				  pp->io_bus_addr, pp->io_size);
 
 	return ret;
@@ -583,12 +572,12 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 
 	if (bus->parent->number == pp->root_bus_nr) {
 		type = PCIE_ATU_TYPE_CFG0;
-		cpu_addr = pp->cfg0_mod_base;
+		cpu_addr = pp->cfg0_base;
 		cfg_size = pp->cfg0_size;
 		va_cfg_base = pp->va_cfg0_base;
 	} else {
 		type = PCIE_ATU_TYPE_CFG1;
-		cpu_addr = pp->cfg1_mod_base;
+		cpu_addr = pp->cfg1_base;
 		cfg_size = pp->cfg1_size;
 		va_cfg_base = pp->va_cfg1_base;
 	}
@@ -598,7 +587,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 				  busdev, cfg_size);
 	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
 	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
-				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
+				  PCIE_ATU_TYPE_IO, pp->io_base,
 				  pp->io_bus_addr, pp->io_size);
 
 	return ret;
@@ -630,7 +619,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
 static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
@@ -654,7 +643,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 			int where, int size, u32 val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
@@ -678,62 +667,6 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
-{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
-{
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_scan_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;
-}
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
-	.map_irq	= dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
 	u32 val;
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
index d0bbd27..0c2a7eb 100644
--- a/drivers/pci/host/pcie-designware.h
+++ b/drivers/pci/host/pcie-designware.h
@@ -21,31 +21,28 @@
  */
 #define MAX_MSI_IRQS			32
 #define MAX_MSI_CTRLS			(MAX_MSI_IRQS / 32)
+#define DW_ROOT_NR_UNDEFINED	-1
 
 struct pcie_port {
 	struct device		*dev;
 	u8			root_bus_nr;
 	void __iomem		*dbi_base;
 	u64			cfg0_base;
-	u64			cfg0_mod_base;
 	void __iomem		*va_cfg0_base;
 	u32			cfg0_size;
 	u64			cfg1_base;
-	u64			cfg1_mod_base;
 	void __iomem		*va_cfg1_base;
 	u32			cfg1_size;
-	u64			io_base;
-	u64			io_mod_base;
+	resource_size_t		io_base;
 	phys_addr_t		io_bus_addr;
 	u32			io_size;
 	u64			mem_base;
-	u64			mem_mod_base;
 	phys_addr_t		mem_bus_addr;
 	u32			mem_size;
-	struct resource		cfg;
-	struct resource		io;
-	struct resource		mem;
-	struct resource		busn;
+	struct resource		*cfg;
+	struct resource		*io;
+	struct resource		*mem;
+	struct resource		*busn;
 	int			irq;
 	u32			lanes;
 	struct pcie_host_ops	*ops;
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
index c49fbdc..b2c59b9 100644
--- a/drivers/pci/host/pcie-spear13xx.c
+++ b/drivers/pci/host/pcie-spear13xx.c
@@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
 		return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
 	pp->ops = &spear13xx_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
-- 
1.9.1


> -----Original Message-----
> From: Lucas Stach [mailto:l.stach@pengutronix.de]
> Sent: Wednesday, August 19, 2015 1:54 PM
> To: Wangzhou (B)
> Cc: Bjorn Helgaas; jingoohan1@gmail.com; Pratyush Anand; Arnd Bergmann;
> linux@arm.linux.org.uk; thomas.petazzoni@free-electrons.com; Gabriele
> Paoloni; lorenzo.pieralisi@arm.com; james.morse@arm.com;
> Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org; linux-
> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> 
> Am Montag, den 17.08.2015, 19:55 +0800 schrieb Zhou Wang:
> > This patch tries to unify ARM32 and ARM64 PCIe in designware driver.
> Delete
> > function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct
> hw_pci,
> > move related operations to dw_pcie_host_init.
> >
> > In past, we use:
> > pci_common_init_dev
> > 	-> pcibios_init_hw
> > 		-> hw->scan (dw_pcie_scan_bus)
> > to pass 0 to root_bus_nr in struct pcie_port. This patch set pp-
> >root_bus_nr = 0
> > in each PCIe host driver which is based on pcie-designware.
> >
> This is incorrect at least if there are 2 instances of DW PCIe host in
> the same SoC without using PCI domains. In that the case the bus range
> determines the range of valid bus numbers per instance and the first
> number is the root bus. Please look at the "bus-range" DT property in
> the DW PCIe bindings.
> 
> Also we should finally remove this root-bus setup from the glue drivers
> altogether. It's something that entirely belongs into the DW core code.
> 
> Regards,
> Lucas
> 
> > This patch also try to use of_pci_get_host_bridge_resources for ARM32
> and ARM64
> > according to the suggestion for Gabriele[1]
> >
> > Finally this patch reverts commit f4c55c5a3f7f "PCI: designware:
> Program ATU
> > with untranslated address" based on 1/6 in this series. we delete
> *_mod_base in
> > pcie-designware. This was discussed in [2]
> >
> > I have compiled the driver with multi_v7_defconfig. However, I don't
> have
> > ARM32 PCIe related board to do test. It will be appreciated if
> someone could
> > help to test it.
> >
> > Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> > Tested-By: James Morse <james.morse@arm.com>
> >
> > [1] http://www.spinics.net/lists/linux-pci/msg42194.html
> > [2] http://www.spinics.net/lists/arm-kernel/msg436779.html
> > ---
> >  drivers/pci/host/pci-dra7xx.c      |  15 +--
> >  drivers/pci/host/pci-exynos.c      |   2 +-
> >  drivers/pci/host/pci-imx6.c        |   2 +-
> >  drivers/pci/host/pci-keystone-dw.c |   2 +-
> >  drivers/pci/host/pci-keystone.c    |   2 +-
> >  drivers/pci/host/pci-layerscape.c  |   2 +-
> >  drivers/pci/host/pcie-designware.c | 229 ++++++++++++---------------
> ----------
> >  drivers/pci/host/pcie-designware.h |  14 +--
> >  drivers/pci/host/pcie-spear13xx.c  |   2 +-
> >  9 files changed, 95 insertions(+), 175 deletions(-)
> >
> > diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-
> dra7xx.c
> > index 18ae7ff..1268c69 100644
> > --- a/drivers/pci/host/pci-dra7xx.c
> > +++ b/drivers/pci/host/pci-dra7xx.c
> > @@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct
> pcie_port *pp)
> >  {
> >  	dw_pcie_setup_rc(pp);
> >
> > -	if (pp->io_mod_base)
> > -		pp->io_mod_base &= CPU_TO_BUS_ADDR;
> > +	if (pp->io_base)
> > +		pp->io_base &= CPU_TO_BUS_ADDR;
> >
> > -	if (pp->mem_mod_base)
> > -		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
> > +	if (pp->mem_base)
> > +		pp->mem_base &= CPU_TO_BUS_ADDR;
> >
> > -	if (pp->cfg0_mod_base) {
> > -		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
> > -		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
> > +	if (pp->cfg0_base) {
> > +		pp->cfg0_base &= CPU_TO_BUS_ADDR;
> > +		pp->cfg1_base &= CPU_TO_BUS_ADDR;
> >  	}
> >
> >  	dra7xx_pcie_establish_link(pp);
> > @@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct
> dra7xx_pcie *dra7xx,
> >
> >  	pp = &dra7xx->pp;
> >  	pp->dev = dev;
> > +	pp->root_bus_nr = 0;
> >  	pp->ops = &dra7xx_pcie_host_ops;
> >
> >  	pp->irq = platform_get_irq(pdev, 1);
> > diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-
> exynos.c
> > index f9f468d..9771bb0 100644
> > --- a/drivers/pci/host/pci-exynos.c
> > +++ b/drivers/pci/host/pci-exynos.c
> > @@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct
> pcie_port *pp,
> >  		}
> >  	}
> >
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = 0;
> >  	pp->ops = &exynos_pcie_host_ops;
> >
> >  	ret = dw_pcie_host_init(pp);
> > diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-
> imx6.c
> > index 233a196..bec256c 100644
> > --- a/drivers/pci/host/pci-imx6.c
> > +++ b/drivers/pci/host/pci-imx6.c
> > @@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct
> pcie_port *pp,
> >  		}
> >  	}
> >
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = 0;
> >  	pp->ops = &imx6_pcie_host_ops;
> >
> >  	ret = dw_pcie_host_init(pp);
> > diff --git a/drivers/pci/host/pci-keystone-dw.c
> b/drivers/pci/host/pci-keystone-dw.c
> > index f34892e..b1e4135 100644
> > --- a/drivers/pci/host/pci-keystone-dw.c
> > +++ b/drivers/pci/host/pci-keystone-dw.c
> > @@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void
> __iomem *reg_virt)
> >  void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
> >  {
> >  	struct pcie_port *pp = &ks_pcie->pp;
> > -	u32 start = pp->mem.start, end = pp->mem.end;
> > +	u32 start = pp->mem->start, end = pp->mem->end;
> >  	int i, tr_size;
> >
> >  	/* Disable BARs for inbound access */
> > diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-
> keystone.c
> > index 734da58..8113832 100644
> > --- a/drivers/pci/host/pci-keystone.c
> > +++ b/drivers/pci/host/pci-keystone.c
> > @@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct
> keystone_pcie *ks_pcie,
> >  			return ret;
> >  	}
> >
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = 0;
> >  	pp->ops = &keystone_pcie_host_ops;
> >  	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
> >  	if (ret) {
> > diff --git a/drivers/pci/host/pci-layerscape.c
> b/drivers/pci/host/pci-layerscape.c
> > index b2328ea1..79ff08c 100644
> > --- a/drivers/pci/host/pci-layerscape.c
> > +++ b/drivers/pci/host/pci-layerscape.c
> > @@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
> >  	pp = &pcie->pp;
> >  	pp->dev = pcie->dev;
> >  	pp->dbi_base = pcie->dbi;
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = 0;
> >  	pp->ops = &ls_pcie_host_ops;
> >
> >  	ret = dw_pcie_host_init(pp);
> > diff --git a/drivers/pci/host/pcie-designware.c
> b/drivers/pci/host/pcie-designware.c
> > index c5d407c..e71a88e 100644
> > --- a/drivers/pci/host/pcie-designware.c
> > +++ b/drivers/pci/host/pcie-designware.c
> > @@ -11,6 +11,7 @@
> >   * published by the Free Software Foundation.
> >   */
> >
> > +#include <linux/hardirq.h>
> >  #include <linux/irq.h>
> >  #include <linux/irqdomain.h>
> >  #include <linux/kernel.h>
> > @@ -69,16 +70,7 @@
> >  #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
> >  #define PCIE_ATU_UPPER_TARGET		0x91C
> >
> > -static struct hw_pci dw_pci;
> > -
> > -static unsigned long global_io_offset;
> > -
> > -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
> > -{
> > -	BUG_ON(!sys->private_data);
> > -
> > -	return sys->private_data;
> > -}
> > +static struct pci_ops dw_pcie_ops;
> >
> >  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32
> *val)
> >  {
> > @@ -255,7 +247,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port
> *pp, int irq)
> >  static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
> >  {
> >  	int irq, pos0, i;
> > -	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
> > +	struct pcie_port *pp = desc->dev->bus->sysdata;
> >
> >  	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
> >  				       order_base_2(no_irqs));
> > @@ -298,7 +290,7 @@ static int dw_msi_setup_irq(struct msi_controller
> *chip, struct pci_dev *pdev,
> >  {
> >  	int irq, pos;
> >  	struct msi_msg msg;
> > -	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
> > +	struct pcie_port *pp = pdev->bus->sysdata;
> >
> >  	if (desc->msi_attrib.is_msix)
> >  		return -EINVAL;
> > @@ -327,7 +319,7 @@ static void dw_msi_teardown_irq(struct
> msi_controller *chip, unsigned int irq)
> >  {
> >  	struct irq_data *data = irq_get_irq_data(irq);
> >  	struct msi_desc *msi = irq_data_get_msi(data);
> > -	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
> > +	struct pcie_port *pp = msi->dev->bus->sysdata;
> >
> >  	clear_irq_range(pp, irq, 1, data->hwirq);
> >  }
> > @@ -363,14 +355,12 @@ int dw_pcie_host_init(struct pcie_port *pp)
> >  {
> >  	struct device_node *np = pp->dev->of_node;
> >  	struct platform_device *pdev = to_platform_device(pp->dev);
> > -	struct of_pci_range range;
> > -	struct of_pci_range_parser parser;
> > +	struct pci_bus *bus;
> >  	struct resource *cfg_res;
> > -	u32 val, ns;
> > -	const __be32 *addrp;
> > -	int i, index, ret;
> > -
> > -	ns = of_n_size_cells(np);
> > +	LIST_HEAD(res);
> > +	u32 val;
> > +	int i, ret;
> > +	struct resource_entry *win;
> >
> >  	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> "config");
> >  	if (cfg_res) {
> > @@ -378,85 +368,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
> >  		pp->cfg1_size = resource_size(cfg_res)/2;
> >  		pp->cfg0_base = cfg_res->start;
> >  		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
> > -
> > -		/* Find the untranslated configuration space address */
> > -		index = of_property_match_string(np, "reg-names", "config");
> > -		addrp = of_get_address(np, index, NULL, NULL);
> > -		pp->cfg0_mod_base = of_read_number(addrp, ns);
> > -		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
> >  	} else {
> >  		dev_err(pp->dev, "missing *config* reg space\n");
> >  	}
> >
> > -	if (of_pci_range_parser_init(&parser, np)) {
> > -		dev_err(pp->dev, "missing ranges property\n");
> > -		return -EINVAL;
> > -	}
> > +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp-
> >io_base);
> > +	if (ret)
> > +		return ret;
> >
> >  	/* Get the I/O and memory ranges from DT */
> > -	for_each_of_pci_range(&parser, &range) {
> > -		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
> > -
> > -		if (restype == IORESOURCE_IO) {
> > -			of_pci_range_to_resource(&range, np, &pp->io);
> > -			pp->io.name = "I/O";
> > -			pp->io.start = max_t(resource_size_t,
> > -					     PCIBIOS_MIN_IO,
> > -					     range.pci_addr + global_io_offset);
> > -			pp->io.end = min_t(resource_size_t,
> > -					   IO_SPACE_LIMIT,
> > -					   range.pci_addr + range.size
> > -					   + global_io_offset - 1);
> > -			pp->io_size = resource_size(&pp->io);
> > -			pp->io_bus_addr = range.pci_addr;
> > -			pp->io_base = range.cpu_addr;
> > -
> > -			/* Find the untranslated IO space address */
> > -			pp->io_mod_base = range.cpu_addr;
> > -		}
> > -		if (restype == IORESOURCE_MEM) {
> > -			of_pci_range_to_resource(&range, np, &pp->mem);
> > -			pp->mem.name = "MEM";
> > -			pp->mem_size = resource_size(&pp->mem);
> > -			pp->mem_bus_addr = range.pci_addr;
> > -
> > -			/* Find the untranslated MEM space address */
> > -			pp->mem_mod_base = range.cpu_addr;
> > -		}
> > -		if (restype == 0) {
> > -			of_pci_range_to_resource(&range, np, &pp->cfg);
> > -			pp->cfg0_size = resource_size(&pp->cfg)/2;
> > -			pp->cfg1_size = resource_size(&pp->cfg)/2;
> > -			pp->cfg0_base = pp->cfg.start;
> > -			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
> > -
> > -			/* Find the untranslated configuration space address
> */
> > -			pp->cfg0_mod_base = range.cpu_addr;
> > -			pp->cfg1_mod_base = pp->cfg0_mod_base +
> > -					    pp->cfg0_size;
> > +	resource_list_for_each_entry(win, &res) {
> > +		switch (resource_type(win->res)) {
> > +		case IORESOURCE_IO:
> > +			pp->io = win->res;
> > +			pp->io->name = "I/O";
> > +			pp->io_size = resource_size(pp->io);
> > +			pp->io_bus_addr = pp->io->start - win->offset;
> > +			ret = pci_remap_iospace(pp->io, pp->io_base);
> > +			if (ret) {
> > +				dev_warn(pp->dev, "error %d: failed to map
> resource %pR\n",
> > +					 ret, pp->io);
> > +				continue;
> > +			}
> > +			break;
> > +		case IORESOURCE_MEM:
> > +			pp->mem = win->res;
> > +			pp->mem->name = "MEM";
> > +			pp->mem_size = resource_size(pp->mem);
> > +			pp->mem_bus_addr = pp->mem->start - win->offset;
> > +			break;
> > +		case 0:
> > +			pp->cfg = win->res;
> > +			pp->cfg0_size = resource_size(pp->cfg)/2;
> > +			pp->cfg1_size = resource_size(pp->cfg)/2;
> > +			pp->cfg0_base = pp->cfg->start;
> > +			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
> > +			break;
> > +		case IORESOURCE_BUS:
> > +			pp->busn = win->res;
> > +			break;
> > +		default:
> > +			continue;
> >  		}
> >  	}
> >
> > -	ret = of_pci_parse_bus_range(np, &pp->busn);
> > -	if (ret < 0) {
> > -		pp->busn.name = np->name;
> > -		pp->busn.start = 0;
> > -		pp->busn.end = 0xff;
> > -		pp->busn.flags = IORESOURCE_BUS;
> > -		dev_dbg(pp->dev, "failed to parse bus-range property: %d,
> using default %pR\n",
> > -			ret, &pp->busn);
> > -	}
> > -
> >  	if (!pp->dbi_base) {
> > -		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
> > -					resource_size(&pp->cfg));
> > +		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
> > +					resource_size(pp->cfg));
> >  		if (!pp->dbi_base) {
> >  			dev_err(pp->dev, "error with ioremap\n");
> >  			return -ENOMEM;
> >  		}
> >  	}
> >
> > -	pp->mem_base = pp->mem.start;
> > +	pp->mem_base = pp->mem->start;
> >
> >  	if (!pp->va_cfg0_base) {
> >  		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
> > @@ -505,7 +470,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
> >
> >  	if (!pp->ops->rd_other_conf)
> >  		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
> > -					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
> > +					  PCIE_ATU_TYPE_MEM, pp->mem_base,
> >  					  pp->mem_bus_addr, pp->mem_size);
> >
> >  	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
> > @@ -517,15 +482,29 @@ int dw_pcie_host_init(struct pcie_port *pp)
> >  	val |= PORT_LOGIC_SPEED_CHANGE;
> >  	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
> >
> > -#ifdef CONFIG_PCI_MSI
> > +	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
> > +				  pp, &res);
> > +	if (!bus)
> > +		return -ENOMEM;
> > +
> > +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> > +	bus->msi = container_of(&pp->irq_domain, struct msi_controller,
> domain);
> > +#else
> >  	dw_pcie_msi_chip.dev = pp->dev;
> > -	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> > +	bus->msi = &dw_pcie_msi_chip;
> >  #endif
> >
> > -	dw_pci.nr_controllers = 1;
> > -	dw_pci.private_data = (void **)&pp;
> > +	pci_scan_child_bus(bus);
> > +	if (pp->ops->scan_bus)
> > +		pp->ops->scan_bus(pp);
> > +
> > +#ifdef CONFIG_ARM
> > +	/* support old dtbs that incorrectly describe IRQs */
> > +	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
> > +#endif
> >
> > -	pci_common_init_dev(pp->dev, &dw_pci);
> > +	pci_assign_unassigned_bus_resources(bus);
> > +	pci_bus_add_devices(bus);
> >
> >  	return 0;
> >  }
> > @@ -544,12 +523,12 @@ static int dw_pcie_rd_other_conf(struct
> pcie_port *pp, struct pci_bus *bus,
> >
> >  	if (bus->parent->number == pp->root_bus_nr) {
> >  		type = PCIE_ATU_TYPE_CFG0;
> > -		cpu_addr = pp->cfg0_mod_base;
> > +		cpu_addr = pp->cfg0_base;
> >  		cfg_size = pp->cfg0_size;
> >  		va_cfg_base = pp->va_cfg0_base;
> >  	} else {
> >  		type = PCIE_ATU_TYPE_CFG1;
> > -		cpu_addr = pp->cfg1_mod_base;
> > +		cpu_addr = pp->cfg1_base;
> >  		cfg_size = pp->cfg1_size;
> >  		va_cfg_base = pp->va_cfg1_base;
> >  	}
> > @@ -559,7 +538,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port
> *pp, struct pci_bus *bus,
> >  				  busdev, cfg_size);
> >  	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
> >  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> > -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> > +				  PCIE_ATU_TYPE_IO, pp->io_base,
> >  				  pp->io_bus_addr, pp->io_size);
> >
> >  	return ret;
> > @@ -579,12 +558,12 @@ static int dw_pcie_wr_other_conf(struct
> pcie_port *pp, struct pci_bus *bus,
> >
> >  	if (bus->parent->number == pp->root_bus_nr) {
> >  		type = PCIE_ATU_TYPE_CFG0;
> > -		cpu_addr = pp->cfg0_mod_base;
> > +		cpu_addr = pp->cfg0_base;
> >  		cfg_size = pp->cfg0_size;
> >  		va_cfg_base = pp->va_cfg0_base;
> >  	} else {
> >  		type = PCIE_ATU_TYPE_CFG1;
> > -		cpu_addr = pp->cfg1_mod_base;
> > +		cpu_addr = pp->cfg1_base;
> >  		cfg_size = pp->cfg1_size;
> >  		va_cfg_base = pp->va_cfg1_base;
> >  	}
> > @@ -594,7 +573,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port
> *pp, struct pci_bus *bus,
> >  				  busdev, cfg_size);
> >  	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
> >  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> > -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> > +				  PCIE_ATU_TYPE_IO, pp->io_base,
> >  				  pp->io_bus_addr, pp->io_size);
> >
> >  	return ret;
> > @@ -626,7 +605,7 @@ static int dw_pcie_valid_config(struct pcie_port
> *pp,
> >  static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> >  			int size, u32 *val)
> >  {
> > -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> > +	struct pcie_port *pp = bus->sysdata;
> >  	int ret;
> >
> >  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
> > @@ -650,7 +629,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus,
> u32 devfn, int where,
> >  static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
> >  			int where, int size, u32 val)
> >  {
> > -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> > +	struct pcie_port *pp = bus->sysdata;
> >  	int ret;
> >
> >  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
> > @@ -674,62 +653,6 @@ static struct pci_ops dw_pcie_ops = {
> >  	.write = dw_pcie_wr_conf,
> >  };
> >
> > -static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
> > -{
> > -	struct pcie_port *pp;
> > -
> > -	pp = sys_to_pcie(sys);
> > -
> > -	if (global_io_offset < SZ_1M && pp->io_size > 0) {
> > -		sys->io_offset = global_io_offset - pp->io_bus_addr;
> > -		pci_ioremap_io(global_io_offset, pp->io_base);
> > -		global_io_offset += SZ_64K;
> > -		pci_add_resource_offset(&sys->resources, &pp->io,
> > -					sys->io_offset);
> > -	}
> > -
> > -	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
> > -	pci_add_resource_offset(&sys->resources, &pp->mem, sys-
> >mem_offset);
> > -	pci_add_resource(&sys->resources, &pp->busn);
> > -
> > -	return 1;
> > -}
> > -
> > -static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data
> *sys)
> > -{
> > -	struct pci_bus *bus;
> > -	struct pcie_port *pp = sys_to_pcie(sys);
> > -
> > -	pp->root_bus_nr = sys->busnr;
> > -	bus = pci_scan_root_bus(pp->dev, sys->busnr,
> > -				  &dw_pcie_ops, sys, &sys->resources);
> > -	if (!bus)
> > -		return NULL;
> > -
> > -	if (bus && pp->ops->scan_bus)
> > -		pp->ops->scan_bus(pp);
> > -
> > -	return bus;
> > -}
> > -
> > -static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8
> pin)
> > -{
> > -	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
> > -	int irq;
> > -
> > -	irq = of_irq_parse_and_map_pci(dev, slot, pin);
> > -	if (!irq)
> > -		irq = pp->irq;
> > -
> > -	return irq;
> > -}
> > -
> > -static struct hw_pci dw_pci = {
> > -	.setup		= dw_pcie_setup,
> > -	.scan		= dw_pcie_scan_bus,
> > -	.map_irq	= dw_pcie_map_irq,
> > -};
> > -
> >  void dw_pcie_setup_rc(struct pcie_port *pp)
> >  {
> >  	u32 val;
> > diff --git a/drivers/pci/host/pcie-designware.h
> b/drivers/pci/host/pcie-designware.h
> > index d0bbd27..264c969 100644
> > --- a/drivers/pci/host/pcie-designware.h
> > +++ b/drivers/pci/host/pcie-designware.h
> > @@ -27,25 +27,21 @@ struct pcie_port {
> >  	u8			root_bus_nr;
> >  	void __iomem		*dbi_base;
> >  	u64			cfg0_base;
> > -	u64			cfg0_mod_base;
> >  	void __iomem		*va_cfg0_base;
> >  	u32			cfg0_size;
> >  	u64			cfg1_base;
> > -	u64			cfg1_mod_base;
> >  	void __iomem		*va_cfg1_base;
> >  	u32			cfg1_size;
> > -	u64			io_base;
> > -	u64			io_mod_base;
> > +	resource_size_t		io_base;
> >  	phys_addr_t		io_bus_addr;
> >  	u32			io_size;
> >  	u64			mem_base;
> > -	u64			mem_mod_base;
> >  	phys_addr_t		mem_bus_addr;
> >  	u32			mem_size;
> > -	struct resource		cfg;
> > -	struct resource		io;
> > -	struct resource		mem;
> > -	struct resource		busn;
> > +	struct resource		*cfg;
> > +	struct resource		*io;
> > +	struct resource		*mem;
> > +	struct resource		*busn;
> >  	int			irq;
> >  	u32			lanes;
> >  	struct pcie_host_ops	*ops;
> > diff --git a/drivers/pci/host/pcie-spear13xx.c
> b/drivers/pci/host/pcie-spear13xx.c
> > index c49fbdc..03eb204 100644
> > --- a/drivers/pci/host/pcie-spear13xx.c
> > +++ b/drivers/pci/host/pcie-spear13xx.c
> > @@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct
> pcie_port *pp,
> >  		return ret;
> >  	}
> >
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = 0;
> >  	pp->ops = &spear13xx_pcie_host_ops;
> >
> >  	ret = dw_pcie_host_init(pp);
> 
> --
> Pengutronix e.K.             | Lucas Stach                 |
> Industrial Linux Solutions   | http://www.pengutronix.de/  |


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

* RE: [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-19 15:16       ` Gabriele Paoloni
  0 siblings, 0 replies; 53+ messages in thread
From: Gabriele Paoloni @ 2015-08-19 15:16 UTC (permalink / raw)
  To: Lucas Stach, Wangzhou (B)
  Cc: Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, lorenzo.pieralisi, james.morse, Liviu.Dudau,
	jason, robh, linux-pci, linux-arm-kernel, devicetree,
	Yuanzhichang, Zhudacai, zhangjukuo, qiuzhenfa, liudongdong (C),
	qiujiang, xuwei (O), Liguozhu (Kenneth)

SGkgTHVjYXMNCg0KSSBoYXZlIHJld3JpdHRlbiB0aGUgcGF0Y2ggdG8gdGFrZSBpbnRvIGFjY291
bnQgbXVsdGlwbGUgY29udHJvbGxlcnMuDQoNCkFzIHlvdSBjYW4gc2VlIG5vdyB0aGVyZSBpcyBh
IHN0YXRpYyB2YXIgaW4gZHdfcGNpZV9ob3N0X2luaXQoKSB0aGF0IHRyYWNrcw0KdGhlIGJ1cyBu
dW1iZXJzIHVzZWQuDQpEcml2ZXJzIHRoYXQgZG8gbm90IHNwZWNpZnkgdGhlIGJ1cyByYW5nZSBp
biB0aGUgRFRCIHNldCBwcC0+cm9vdF9idXNfbnIgPSBEV19ST09UX05SX1VOREVGSU5FRC4NCkRl
c2lnbndhcmUgd2lsbCBjaGVjayBpZiB0aGUgZmxhZyBpcyBzZXQgYW5kIHdpbGwgdXNlIHRoZSBh
dXRvbWF0aWMgYnVzIHJhbmdlDQphc3NpZ25tZW50Lg0KSW5zdGVhZCBpZiB0aGUgZHJpdmVyIGFz
c2lnbnMgcHAtPnJvb3RfYnVzX25yIGFjY29yZGluZyB0byB0aGUgZHRiLCBkZXNpZ253d2FyZQ0K
d2lsbCB1c2UgdGhlIHZhbHVlIHBhc3NlZCBpbiBieSB0aGUgZHJpdmVyLg0KQmVsb3cgdGhlIHJl
bGV2YW50IHNlY3Rpb246DQoNCg0KKwlzdGF0aWMgaW50IHJvb3RfYnVzX25yID0gMDsNCi4uLg0K
KwltdXRleF9sb2NrKCZyb290X2J1c19ucl9tdXgpOw0KKw0KKwlpZiAocHAtPnJvb3RfYnVzX25y
ICE9IERXX1JPT1RfTlJfVU5ERUZJTkVEKQ0KKwkJcm9vdF9idXNfbnIgPSBwcC0+cm9vdF9idXNf
bnI7DQorDQorCWJ1cyA9IHBjaV9jcmVhdGVfcm9vdF9idXMocHAtPmRldiwgcm9vdF9idXNfbnIs
ICZkd19wY2llX29wcywNCisJCQkgICAgICBwcCwgJnJlcyk7DQorCWlmICghYnVzKSB7DQorCQlt
dXRleF91bmxvY2soJnJvb3RfYnVzX25yX211eCk7DQorCQlyZXR1cm4gLUVOT01FTTsNCisJfQ0K
Kw0KKwlyb290X2J1c19uciArPSBidXMtPmJ1c25fcmVzLmVuZCArIDE7DQorCW11dGV4X3VubG9j
aygmcm9vdF9idXNfbnJfbXV4KTsNCg0KUGxlYXNlIGxldCBtZSBrbm93IHdoYXQgeW91IHRoaW5r
Li4uDQoNCk1hbnkgVGhhbmtzDQoNCkdhYg0KLS0tLS0tLS0tLQ0KDQpGcm9tOiBnYWJyaWVsZSBw
YW9sb25pIDxnYWJyaWVsZS5wYW9sb25pQGh1YXdlaS5jb20+DQoNClRoaXMgcGF0Y2ggdHJpZXMg
dG8gdW5pZnkgQVJNMzIgYW5kIEFSTTY0IFBDSWUgaW4gZGVzaWdud2FyZSBkcml2ZXIuIERlbGV0
ZQ0KZnVuY3Rpb24gZHdfcGNpZV9zZXR1cCwgZHdfcGNpZV9zY2FuX2J1cywgZHdfcGNpZV9tYXBf
aXJxIGFuZCBzdHJ1Y3QgaHdfcGNpLA0KbW92ZSByZWxhdGVkIG9wZXJhdGlvbnMgdG8gZHdfcGNp
ZV9ob3N0X2luaXQuDQpBbHNvIHNldCBwcC0+cm9vdF9idXNfbnIgPSBEV19ST09UX05SX1VOREVG
SU5FRCBpbiBhbGwgdGhlIGRyaXZlcnMgdGhhdA0KYXJlIGJhc2VkIG9uIGRlc2lnbndhcmUgdG8g
ZmxhZyB0aGF0IHRoZSBkcml2ZXJzIGRvIG5vdCByZWFkIHRoZSBidXMNCnJhbmdlcyBmcm9tIERU
Lg0KVGhpcyBwYXRjaCBhbHNvIGFkZHMgaGFuZGxpbmcgb2YgbXVsdGlwbGUgUENJIGRvbWFpbnMg
aW4gZGVzaWdud2FyZS4NCmlmIHRoZSBQQ0kgaG9zdCBicmlkZ2UgZHJpdmVyIGRvZXMgbm90IHNw
ZWNpZnkgYSByb290IGJ1cyBudW1iZXIsIGluIGNhc2UNCm9mIG11bHRpcGxlIGRvbWFpbnMsIGRl
c2lnbndhcmUgd2lsbCBhdXRvbWF0aWxsYXkgc2V0IHRoZSBuZXh0IGRvbWFpbiByb290DQpidXMg
bnVtYmVyIHRvIHRoZSBsYXN0IGJ1cyBudW1iZXIgdXNlZCBpbiB0aGUgbGFzdCBkb21haW4gKyAx
Lg0KDQpUaGlzIHBhdGNoIGFsc28gdHJ5IHRvIHVzZSBvZl9wY2lfZ2V0X2hvc3RfYnJpZGdlX3Jl
c291cmNlcyBmb3IgQVJNMzIgYW5kDQpBUk02NCBhY2NvcmRpbmcgdG8gdGhlIHN1Z2dlc3Rpb24g
Zm9yIEdhYnJpZWxlWzFdDQoNClRoaXMgcGF0Y2ggaXMgYmFzZWQgb24gR2FicmllbGUncyBwYXRj
aCBhYm91dCBvZl9wY2lfcmFuZ2UgZml4WzJdDQoNCkZpbmFsbHkgdGhpcyBwYXRjaCByZXZlcnRz
IGNvbW1pdCBmNGM1NWM1YTNmN2YgIlBDSTogZGVzaWdud2FyZToNClByb2dyYW0gQVRVIHdpdGgg
dW50cmFuc2xhdGVkIGFkZHJlc3MiLiBUaGlzIHdhcyBkaXNjdXNzZWQgaW4gWzNdDQoNCkkgaGF2
ZSBjb21waWxlZCB0aGUgZHJpdmVyIHdpdGggbXVsdGlfdjdfZGVmY29uZmlnLiBIb3dldmVyLCBJ
IGRvbid0IGhhdmUNCkFSTTMyIFBDSWUgcmVsYXRlZCBib2FyZCB0byBkbyB0ZXN0LiBJdCB3aWxs
IGJlIGFwcHJlY2lhdGVkIGlmIHNvbWVvbmUgY291bGQNCmhlbHAgdG8gdGVzdCBpdC4NCg0KU2ln
bmVkLW9mZi1ieTogWmhvdSBXYW5nIDx3YW5nemhvdTFAaGlzaWxpY29uLmNvbT4NClNpZ25lZC1v
ZmYtYnk6IEFybmQgQmVyZ21hbm4gPGFybmRAYXJuZGIuZGU+DQpTaWduZWQtb2ZmLWJ5OiBHYWJy
aWVsZSBQYW9sb25pIDxnYWJyaWVsZS5wYW9sb25pQGh1YXdlaS5jb20+DQoNClsxXSBodHRwOi8v
d3d3LnNwaW5pY3MubmV0L2xpc3RzL2xpbnV4LXBjaS9tc2c0MjE5NC5odG1sDQpbMl0gaHR0cHM6
Ly9wYXRjaHdvcmsub3psYWJzLm9yZy9wYXRjaC80OTUwMTgvDQpbM10gaHR0cDovL3d3dy5zcGlu
aWNzLm5ldC9saXN0cy9hcm0ta2VybmVsL21zZzQzNjc3OS5odG1sDQotLS0NCiBkcml2ZXJzL3Bj
aS9ob3N0L3BjaS1kcmE3eHguYyAgICAgIHwgIDE1ICstLQ0KIGRyaXZlcnMvcGNpL2hvc3QvcGNp
LWV4eW5vcy5jICAgICAgfCAgIDIgKy0NCiBkcml2ZXJzL3BjaS9ob3N0L3BjaS1pbXg2LmMgICAg
ICAgIHwgICAyICstDQogZHJpdmVycy9wY2kvaG9zdC9wY2kta2V5c3RvbmUtZHcuYyB8ICAgMiAr
LQ0KIGRyaXZlcnMvcGNpL2hvc3QvcGNpLWtleXN0b25lLmMgICAgfCAgIDIgKy0NCiBkcml2ZXJz
L3BjaS9ob3N0L3BjaS1sYXllcnNjYXBlLmMgIHwgICAyICstDQogZHJpdmVycy9wY2kvaG9zdC9w
Y2llLWRlc2lnbndhcmUuYyB8IDI0NyArKysrKysrKysrKysrKy0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tDQogZHJpdmVycy9wY2kvaG9zdC9wY2llLWRlc2lnbndhcmUuaCB8ICAxNSArLS0NCiBkcml2
ZXJzL3BjaS9ob3N0L3BjaWUtc3BlYXIxM3h4LmMgIHwgICAyICstDQogOSBmaWxlcyBjaGFuZ2Vk
LCAxMTAgaW5zZXJ0aW9ucygrKSwgMTc5IGRlbGV0aW9ucygtKQ0KDQpkaWZmIC0tZ2l0IGEvZHJp
dmVycy9wY2kvaG9zdC9wY2ktZHJhN3h4LmMgYi9kcml2ZXJzL3BjaS9ob3N0L3BjaS1kcmE3eHgu
Yw0KaW5kZXggNTY3OGI1Ny4uOGQ1OThmYiAxMDA2NDQNCi0tLSBhL2RyaXZlcnMvcGNpL2hvc3Qv
cGNpLWRyYTd4eC5jDQorKysgYi9kcml2ZXJzL3BjaS9ob3N0L3BjaS1kcmE3eHguYw0KQEAgLTE0
MSwxNSArMTQxLDE1IEBAIHN0YXRpYyB2b2lkIGRyYTd4eF9wY2llX2hvc3RfaW5pdChzdHJ1Y3Qg
cGNpZV9wb3J0ICpwcCkNCiB7DQogCWR3X3BjaWVfc2V0dXBfcmMocHApOw0KIA0KLQlpZiAocHAt
PmlvX21vZF9iYXNlKQ0KLQkJcHAtPmlvX21vZF9iYXNlICY9IENQVV9UT19CVVNfQUREUjsNCisJ
aWYgKHBwLT5pb19iYXNlKQ0KKwkJcHAtPmlvX2Jhc2UgJj0gQ1BVX1RPX0JVU19BRERSOw0KIA0K
LQlpZiAocHAtPm1lbV9tb2RfYmFzZSkNCi0JCXBwLT5tZW1fbW9kX2Jhc2UgJj0gQ1BVX1RPX0JV
U19BRERSOw0KKwlpZiAocHAtPm1lbV9iYXNlKQ0KKwkJcHAtPm1lbV9iYXNlICY9IENQVV9UT19C
VVNfQUREUjsNCiANCi0JaWYgKHBwLT5jZmcwX21vZF9iYXNlKSB7DQotCQlwcC0+Y2ZnMF9tb2Rf
YmFzZSAmPSBDUFVfVE9fQlVTX0FERFI7DQotCQlwcC0+Y2ZnMV9tb2RfYmFzZSAmPSBDUFVfVE9f
QlVTX0FERFI7DQorCWlmIChwcC0+Y2ZnMF9iYXNlKSB7DQorCQlwcC0+Y2ZnMF9iYXNlICY9IENQ
VV9UT19CVVNfQUREUjsNCisJCXBwLT5jZmcxX2Jhc2UgJj0gQ1BVX1RPX0JVU19BRERSOw0KIAl9
DQogDQogCWRyYTd4eF9wY2llX2VzdGFibGlzaF9saW5rKHBwKTsNCkBAIC0yODgsNiArMjg4LDcg
QEAgc3RhdGljIGludCBfX2luaXQgZHJhN3h4X2FkZF9wY2llX3BvcnQoc3RydWN0IGRyYTd4eF9w
Y2llICpkcmE3eHgsDQogDQogCXBwID0gJmRyYTd4eC0+cHA7DQogCXBwLT5kZXYgPSBkZXY7DQor
CXBwLT5yb290X2J1c19uciA9IERXX1JPT1RfTlJfVU5ERUZJTkVEOw0KIAlwcC0+b3BzID0gJmRy
YTd4eF9wY2llX2hvc3Rfb3BzOw0KIA0KIAlwcC0+aXJxID0gcGxhdGZvcm1fZ2V0X2lycShwZGV2
LCAxKTsNCmRpZmYgLS1naXQgYS9kcml2ZXJzL3BjaS9ob3N0L3BjaS1leHlub3MuYyBiL2RyaXZl
cnMvcGNpL2hvc3QvcGNpLWV4eW5vcy5jDQppbmRleCBmOWY0NjhkLi5lZDAzYThmIDEwMDY0NA0K
LS0tIGEvZHJpdmVycy9wY2kvaG9zdC9wY2ktZXh5bm9zLmMNCisrKyBiL2RyaXZlcnMvcGNpL2hv
c3QvcGNpLWV4eW5vcy5jDQpAQCAtNTMwLDcgKzUzMCw3IEBAIHN0YXRpYyBpbnQgX19pbml0IGV4
eW5vc19hZGRfcGNpZV9wb3J0KHN0cnVjdCBwY2llX3BvcnQgKnBwLA0KIAkJfQ0KIAl9DQogDQot
CXBwLT5yb290X2J1c19uciA9IC0xOw0KKwlwcC0+cm9vdF9idXNfbnIgPSBEV19ST09UX05SX1VO
REVGSU5FRDsNCiAJcHAtPm9wcyA9ICZleHlub3NfcGNpZV9ob3N0X29wczsNCiANCiAJcmV0ID0g
ZHdfcGNpZV9ob3N0X2luaXQocHApOw0KZGlmZiAtLWdpdCBhL2RyaXZlcnMvcGNpL2hvc3QvcGNp
LWlteDYuYyBiL2RyaXZlcnMvcGNpL2hvc3QvcGNpLWlteDYuYw0KaW5kZXggMjMzYTE5Ni4uMGVm
YWM4NSAxMDA2NDQNCi0tLSBhL2RyaXZlcnMvcGNpL2hvc3QvcGNpLWlteDYuYw0KKysrIGIvZHJp
dmVycy9wY2kvaG9zdC9wY2ktaW14Ni5jDQpAQCAtNTUxLDcgKzU1MSw3IEBAIHN0YXRpYyBpbnQg
X19pbml0IGlteDZfYWRkX3BjaWVfcG9ydChzdHJ1Y3QgcGNpZV9wb3J0ICpwcCwNCiAJCX0NCiAJ
fQ0KIA0KLQlwcC0+cm9vdF9idXNfbnIgPSAtMTsNCisJcHAtPnJvb3RfYnVzX25yID0gRFdfUk9P
VF9OUl9VTkRFRklORUQ7DQogCXBwLT5vcHMgPSAmaW14Nl9wY2llX2hvc3Rfb3BzOw0KIA0KIAly
ZXQgPSBkd19wY2llX2hvc3RfaW5pdChwcCk7DQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9wY2kvaG9z
dC9wY2kta2V5c3RvbmUtZHcuYyBiL2RyaXZlcnMvcGNpL2hvc3QvcGNpLWtleXN0b25lLWR3LmMN
CmluZGV4IGYzNDg5MmUuLmIxZTQxMzUgMTAwNjQ0DQotLS0gYS9kcml2ZXJzL3BjaS9ob3N0L3Bj
aS1rZXlzdG9uZS1kdy5jDQorKysgYi9kcml2ZXJzL3BjaS9ob3N0L3BjaS1rZXlzdG9uZS1kdy5j
DQpAQCAtMzI3LDcgKzMyNyw3IEBAIHN0YXRpYyB2b2lkIGtzX2R3X3BjaWVfY2xlYXJfZGJpX21v
ZGUodm9pZCBfX2lvbWVtICpyZWdfdmlydCkNCiB2b2lkIGtzX2R3X3BjaWVfc2V0dXBfcmNfYXBw
X3JlZ3Moc3RydWN0IGtleXN0b25lX3BjaWUgKmtzX3BjaWUpDQogew0KIAlzdHJ1Y3QgcGNpZV9w
b3J0ICpwcCA9ICZrc19wY2llLT5wcDsNCi0JdTMyIHN0YXJ0ID0gcHAtPm1lbS5zdGFydCwgZW5k
ID0gcHAtPm1lbS5lbmQ7DQorCXUzMiBzdGFydCA9IHBwLT5tZW0tPnN0YXJ0LCBlbmQgPSBwcC0+
bWVtLT5lbmQ7DQogCWludCBpLCB0cl9zaXplOw0KIA0KIAkvKiBEaXNhYmxlIEJBUnMgZm9yIGlu
Ym91bmQgYWNjZXNzICovDQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9wY2kvaG9zdC9wY2kta2V5c3Rv
bmUuYyBiL2RyaXZlcnMvcGNpL2hvc3QvcGNpLWtleXN0b25lLmMNCmluZGV4IDczNGRhNTguLmI1
MjI5NTYgMTAwNjQ0DQotLS0gYS9kcml2ZXJzL3BjaS9ob3N0L3BjaS1rZXlzdG9uZS5jDQorKysg
Yi9kcml2ZXJzL3BjaS9ob3N0L3BjaS1rZXlzdG9uZS5jDQpAQCAtMzA5LDcgKzMwOSw3IEBAIHN0
YXRpYyBpbnQgX19pbml0IGtzX2FkZF9wY2llX3BvcnQoc3RydWN0IGtleXN0b25lX3BjaWUgKmtz
X3BjaWUsDQogCQkJcmV0dXJuIHJldDsNCiAJfQ0KIA0KLQlwcC0+cm9vdF9idXNfbnIgPSAtMTsN
CisJcHAtPnJvb3RfYnVzX25yID0gRFdfUk9PVF9OUl9VTkRFRklORUQ7DQogCXBwLT5vcHMgPSAm
a2V5c3RvbmVfcGNpZV9ob3N0X29wczsNCiAJcmV0ID0ga3NfZHdfcGNpZV9ob3N0X2luaXQoa3Nf
cGNpZSwga3NfcGNpZS0+bXNpX2ludGNfbnApOw0KIAlpZiAocmV0KSB7DQpkaWZmIC0tZ2l0IGEv
ZHJpdmVycy9wY2kvaG9zdC9wY2ktbGF5ZXJzY2FwZS5jIGIvZHJpdmVycy9wY2kvaG9zdC9wY2kt
bGF5ZXJzY2FwZS5jDQppbmRleCBiMjMyOGVhMS4uZGQ5MmZmYSAxMDA2NDQNCi0tLSBhL2RyaXZl
cnMvcGNpL2hvc3QvcGNpLWxheWVyc2NhcGUuYw0KKysrIGIvZHJpdmVycy9wY2kvaG9zdC9wY2kt
bGF5ZXJzY2FwZS5jDQpAQCAtMTA2LDcgKzEwNiw3IEBAIHN0YXRpYyBpbnQgbHNfYWRkX3BjaWVf
cG9ydChzdHJ1Y3QgbHNfcGNpZSAqcGNpZSkNCiAJcHAgPSAmcGNpZS0+cHA7DQogCXBwLT5kZXYg
PSBwY2llLT5kZXY7DQogCXBwLT5kYmlfYmFzZSA9IHBjaWUtPmRiaTsNCi0JcHAtPnJvb3RfYnVz
X25yID0gLTE7DQorCXBwLT5yb290X2J1c19uciA9IERXX1JPT1RfTlJfVU5ERUZJTkVEOw0KIAlw
cC0+b3BzID0gJmxzX3BjaWVfaG9zdF9vcHM7DQogDQogCXJldCA9IGR3X3BjaWVfaG9zdF9pbml0
KHBwKTsNCmRpZmYgLS1naXQgYS9kcml2ZXJzL3BjaS9ob3N0L3BjaWUtZGVzaWdud2FyZS5jIGIv
ZHJpdmVycy9wY2kvaG9zdC9wY2llLWRlc2lnbndhcmUuYw0KaW5kZXggNTMwN2IzNS4uYmQyNjA2
YiAxMDA2NDQNCi0tLSBhL2RyaXZlcnMvcGNpL2hvc3QvcGNpZS1kZXNpZ253YXJlLmMNCisrKyBi
L2RyaXZlcnMvcGNpL2hvc3QvcGNpZS1kZXNpZ253YXJlLmMNCkBAIC0xMSw2ICsxMSw3IEBADQog
ICogcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24uDQogICovDQogDQor
I2luY2x1ZGUgPGxpbnV4L2hhcmRpcnEuaD4NCiAjaW5jbHVkZSA8bGludXgvaXJxLmg+DQogI2lu
Y2x1ZGUgPGxpbnV4L2lycWRvbWFpbi5oPg0KICNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4NCkBA
IC02OSwxNiArNzAsOSBAQA0KICNkZWZpbmUgUENJRV9BVFVfRlVOQyh4KQkJKCgoeCkgJiAweDcp
IDw8IDE2KQ0KICNkZWZpbmUgUENJRV9BVFVfVVBQRVJfVEFSR0VUCQkweDkxQw0KIA0KLXN0YXRp
YyBzdHJ1Y3QgaHdfcGNpIGR3X3BjaTsNCitzdGF0aWMgc3RydWN0IHBjaV9vcHMgZHdfcGNpZV9v
cHM7DQogDQotc3RhdGljIHVuc2lnbmVkIGxvbmcgZ2xvYmFsX2lvX29mZnNldDsNCi0NCi1zdGF0
aWMgaW5saW5lIHN0cnVjdCBwY2llX3BvcnQgKnN5c190b19wY2llKHN0cnVjdCBwY2lfc3lzX2Rh
dGEgKnN5cykNCi17DQotCUJVR19PTighc3lzLT5wcml2YXRlX2RhdGEpOw0KLQ0KLQlyZXR1cm4g
c3lzLT5wcml2YXRlX2RhdGE7DQotfQ0KK0RFRklORV9NVVRFWChyb290X2J1c19ucl9tdXgpOw0K
IA0KIGludCBkd19wY2llX2NmZ19yZWFkKHZvaWQgX19pb21lbSAqYWRkciwgaW50IHdoZXJlLCBp
bnQgc2l6ZSwgdTMyICp2YWwpDQogew0KQEAgLTI1NSw3ICsyNDksNyBAQCBzdGF0aWMgdm9pZCBk
d19wY2llX21zaV9zZXRfaXJxKHN0cnVjdCBwY2llX3BvcnQgKnBwLCBpbnQgaXJxKQ0KIHN0YXRp
YyBpbnQgYXNzaWduX2lycShpbnQgbm9faXJxcywgc3RydWN0IG1zaV9kZXNjICpkZXNjLCBpbnQg
KnBvcykNCiB7DQogCWludCBpcnEsIHBvczAsIGk7DQotCXN0cnVjdCBwY2llX3BvcnQgKnBwID0g
c3lzX3RvX3BjaWUoZGVzYy0+ZGV2LT5idXMtPnN5c2RhdGEpOw0KKwlzdHJ1Y3QgcGNpZV9wb3J0
ICpwcCA9IGRlc2MtPmRldi0+YnVzLT5zeXNkYXRhOw0KIA0KIAlwb3MwID0gYml0bWFwX2ZpbmRf
ZnJlZV9yZWdpb24ocHAtPm1zaV9pcnFfaW5fdXNlLCBNQVhfTVNJX0lSUVMsDQogCQkJCSAgICAg
ICBvcmRlcl9iYXNlXzIobm9faXJxcykpOw0KQEAgLTI5OCw3ICsyOTIsNyBAQCBzdGF0aWMgaW50
IGR3X21zaV9zZXR1cF9pcnEoc3RydWN0IG1zaV9jb250cm9sbGVyICpjaGlwLCBzdHJ1Y3QgcGNp
X2RldiAqcGRldiwNCiB7DQogCWludCBpcnEsIHBvczsNCiAJc3RydWN0IG1zaV9tc2cgbXNnOw0K
LQlzdHJ1Y3QgcGNpZV9wb3J0ICpwcCA9IHN5c190b19wY2llKHBkZXYtPmJ1cy0+c3lzZGF0YSk7
DQorCXN0cnVjdCBwY2llX3BvcnQgKnBwID0gcGRldi0+YnVzLT5zeXNkYXRhOw0KIA0KIAlpZiAo
ZGVzYy0+bXNpX2F0dHJpYi5pc19tc2l4KQ0KIAkJcmV0dXJuIC1FSU5WQUw7DQpAQCAtMzI3LDcg
KzMyMSw3IEBAIHN0YXRpYyB2b2lkIGR3X21zaV90ZWFyZG93bl9pcnEoc3RydWN0IG1zaV9jb250
cm9sbGVyICpjaGlwLCB1bnNpZ25lZCBpbnQgaXJxKQ0KIHsNCiAJc3RydWN0IGlycV9kYXRhICpk
YXRhID0gaXJxX2dldF9pcnFfZGF0YShpcnEpOw0KIAlzdHJ1Y3QgbXNpX2Rlc2MgKm1zaSA9IGly
cV9kYXRhX2dldF9tc2koZGF0YSk7DQotCXN0cnVjdCBwY2llX3BvcnQgKnBwID0gc3lzX3RvX3Bj
aWUobXNpLT5kZXYtPmJ1cy0+c3lzZGF0YSk7DQorCXN0cnVjdCBwY2llX3BvcnQgKnBwID0gbXNp
LT5kZXYtPmJ1cy0+c3lzZGF0YTsNCiANCiAJY2xlYXJfaXJxX3JhbmdlKHBwLCBpcnEsIDEsIGRh
dGEtPmh3aXJxKTsNCiB9DQpAQCAtMzU5LDIyICszNTMsMTcgQEAgc3RhdGljIGNvbnN0IHN0cnVj
dCBpcnFfZG9tYWluX29wcyBtc2lfZG9tYWluX29wcyA9IHsNCiAJLm1hcCA9IGR3X3BjaWVfbXNp
X21hcCwNCiB9Ow0KIA0KLWludCBkd19wY2llX2hvc3RfaW5pdChzdHJ1Y3QgcGNpZV9wb3J0ICpw
cCkNCitpbnQgX19pbml0IGR3X3BjaWVfaG9zdF9pbml0KHN0cnVjdCBwY2llX3BvcnQgKnBwKQ0K
IHsNCiAJc3RydWN0IGRldmljZV9ub2RlICpucCA9IHBwLT5kZXYtPm9mX25vZGU7DQogCXN0cnVj
dCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYgPSB0b19wbGF0Zm9ybV9kZXZpY2UocHAtPmRldik7DQot
CXN0cnVjdCBvZl9wY2lfcmFuZ2UgcmFuZ2U7DQotCXN0cnVjdCBvZl9wY2lfcmFuZ2VfcGFyc2Vy
IHBhcnNlcjsNCisJc3RydWN0IHBjaV9idXMgKmJ1czsNCiAJc3RydWN0IHJlc291cmNlICpjZmdf
cmVzOw0KLQl1MzIgdmFsLCBuYSwgbnM7DQotCWNvbnN0IF9fYmUzMiAqYWRkcnA7DQotCWludCBp
LCBpbmRleCwgcmV0Ow0KLQ0KLQkvKiBGaW5kIHRoZSBhZGRyZXNzIGNlbGwgc2l6ZSBhbmQgdGhl
IG51bWJlciBvZiBjZWxscyBpbiBvcmRlciB0byBnZXQNCi0JICogdGhlIHVudHJhbnNsYXRlZCBh
ZGRyZXNzLg0KLQkgKi8NCi0Jb2ZfcHJvcGVydHlfcmVhZF91MzIobnAsICIjYWRkcmVzcy1jZWxs
cyIsICZuYSk7DQotCW5zID0gb2Zfbl9zaXplX2NlbGxzKG5wKTsNCisJTElTVF9IRUFEKHJlcyk7
DQorCXUzMiB2YWw7DQorCWludCBpLCByZXQ7DQorCXN0cnVjdCByZXNvdXJjZV9lbnRyeSAqd2lu
Ow0KKwlzdGF0aWMgaW50IHJvb3RfYnVzX25yID0gMDsNCiANCiAJY2ZnX3JlcyA9IHBsYXRmb3Jt
X2dldF9yZXNvdXJjZV9ieW5hbWUocGRldiwgSU9SRVNPVVJDRV9NRU0sICJjb25maWciKTsNCiAJ
aWYgKGNmZ19yZXMpIHsNCkBAIC0zODIsODUgKzM3MSw2MCBAQCBpbnQgZHdfcGNpZV9ob3N0X2lu
aXQoc3RydWN0IHBjaWVfcG9ydCAqcHApDQogCQlwcC0+Y2ZnMV9zaXplID0gcmVzb3VyY2Vfc2l6
ZShjZmdfcmVzKS8yOw0KIAkJcHAtPmNmZzBfYmFzZSA9IGNmZ19yZXMtPnN0YXJ0Ow0KIAkJcHAt
PmNmZzFfYmFzZSA9IGNmZ19yZXMtPnN0YXJ0ICsgcHAtPmNmZzBfc2l6ZTsNCi0NCi0JCS8qIEZp
bmQgdGhlIHVudHJhbnNsYXRlZCBjb25maWd1cmF0aW9uIHNwYWNlIGFkZHJlc3MgKi8NCi0JCWlu
ZGV4ID0gb2ZfcHJvcGVydHlfbWF0Y2hfc3RyaW5nKG5wLCAicmVnLW5hbWVzIiwgImNvbmZpZyIp
Ow0KLQkJYWRkcnAgPSBvZl9nZXRfYWRkcmVzcyhucCwgaW5kZXgsIE5VTEwsIE5VTEwpOw0KLQkJ
cHAtPmNmZzBfbW9kX2Jhc2UgPSBvZl9yZWFkX251bWJlcihhZGRycCwgbnMpOw0KLQkJcHAtPmNm
ZzFfbW9kX2Jhc2UgPSBwcC0+Y2ZnMF9tb2RfYmFzZSArIHBwLT5jZmcwX3NpemU7DQogCX0gZWxz
ZSB7DQogCQlkZXZfZXJyKHBwLT5kZXYsICJtaXNzaW5nICpjb25maWcqIHJlZyBzcGFjZVxuIik7
DQogCX0NCiANCi0JaWYgKG9mX3BjaV9yYW5nZV9wYXJzZXJfaW5pdCgmcGFyc2VyLCBucCkpIHsN
Ci0JCWRldl9lcnIocHAtPmRldiwgIm1pc3NpbmcgcmFuZ2VzIHByb3BlcnR5XG4iKTsNCi0JCXJl
dHVybiAtRUlOVkFMOw0KLQl9DQorCXJldCA9IG9mX3BjaV9nZXRfaG9zdF9icmlkZ2VfcmVzb3Vy
Y2VzKG5wLCAwLCAweGZmLCAmcmVzLCAmcHAtPmlvX2Jhc2UpOw0KKwlpZiAocmV0KQ0KKwkJcmV0
dXJuIHJldDsNCiANCiAJLyogR2V0IHRoZSBJL08gYW5kIG1lbW9yeSByYW5nZXMgZnJvbSBEVCAq
Lw0KLQlmb3JfZWFjaF9vZl9wY2lfcmFuZ2UoJnBhcnNlciwgJnJhbmdlKSB7DQotCQl1bnNpZ25l
ZCBsb25nIHJlc3R5cGUgPSByYW5nZS5mbGFncyAmIElPUkVTT1VSQ0VfVFlQRV9CSVRTOw0KLQ0K
LQkJaWYgKHJlc3R5cGUgPT0gSU9SRVNPVVJDRV9JTykgew0KLQkJCW9mX3BjaV9yYW5nZV90b19y
ZXNvdXJjZSgmcmFuZ2UsIG5wLCAmcHAtPmlvKTsNCi0JCQlwcC0+aW8ubmFtZSA9ICJJL08iOw0K
LQkJCXBwLT5pby5zdGFydCA9IG1heF90KHJlc291cmNlX3NpemVfdCwNCi0JCQkJCSAgICAgUENJ
QklPU19NSU5fSU8sDQotCQkJCQkgICAgIHJhbmdlLnBjaV9hZGRyICsgZ2xvYmFsX2lvX29mZnNl
dCk7DQotCQkJcHAtPmlvLmVuZCA9IG1pbl90KHJlc291cmNlX3NpemVfdCwNCi0JCQkJCSAgIElP
X1NQQUNFX0xJTUlULA0KLQkJCQkJICAgcmFuZ2UucGNpX2FkZHIgKyByYW5nZS5zaXplDQotCQkJ
CQkgICArIGdsb2JhbF9pb19vZmZzZXQgLSAxKTsNCi0JCQlwcC0+aW9fc2l6ZSA9IHJlc291cmNl
X3NpemUoJnBwLT5pbyk7DQotCQkJcHAtPmlvX2J1c19hZGRyID0gcmFuZ2UucGNpX2FkZHI7DQot
CQkJcHAtPmlvX2Jhc2UgPSByYW5nZS5jcHVfYWRkcjsNCi0NCi0JCQkvKiBGaW5kIHRoZSB1bnRy
YW5zbGF0ZWQgSU8gc3BhY2UgYWRkcmVzcyAqLw0KLQkJCXBwLT5pb19tb2RfYmFzZSA9IHJhbmdl
LmNwdV9hZGRyOw0KLQkJfQ0KLQkJaWYgKHJlc3R5cGUgPT0gSU9SRVNPVVJDRV9NRU0pIHsNCi0J
CQlvZl9wY2lfcmFuZ2VfdG9fcmVzb3VyY2UoJnJhbmdlLCBucCwgJnBwLT5tZW0pOw0KLQkJCXBw
LT5tZW0ubmFtZSA9ICJNRU0iOw0KLQkJCXBwLT5tZW1fc2l6ZSA9IHJlc291cmNlX3NpemUoJnBw
LT5tZW0pOw0KLQkJCXBwLT5tZW1fYnVzX2FkZHIgPSByYW5nZS5wY2lfYWRkcjsNCi0NCi0JCQkv
KiBGaW5kIHRoZSB1bnRyYW5zbGF0ZWQgTUVNIHNwYWNlIGFkZHJlc3MgKi8NCi0JCQlwcC0+bWVt
X21vZF9iYXNlID0gcmFuZ2UuY3B1X2FkZHI7DQotCQl9DQotCQlpZiAocmVzdHlwZSA9PSAwKSB7
DQotCQkJb2ZfcGNpX3JhbmdlX3RvX3Jlc291cmNlKCZyYW5nZSwgbnAsICZwcC0+Y2ZnKTsNCi0J
CQlwcC0+Y2ZnMF9zaXplID0gcmVzb3VyY2Vfc2l6ZSgmcHAtPmNmZykvMjsNCi0JCQlwcC0+Y2Zn
MV9zaXplID0gcmVzb3VyY2Vfc2l6ZSgmcHAtPmNmZykvMjsNCi0JCQlwcC0+Y2ZnMF9iYXNlID0g
cHAtPmNmZy5zdGFydDsNCi0JCQlwcC0+Y2ZnMV9iYXNlID0gcHAtPmNmZy5zdGFydCArIHBwLT5j
ZmcwX3NpemU7DQotDQotCQkJLyogRmluZCB0aGUgdW50cmFuc2xhdGVkIGNvbmZpZ3VyYXRpb24g
c3BhY2UgYWRkcmVzcyAqLw0KLQkJCXBwLT5jZmcwX21vZF9iYXNlID0gcmFuZ2UuY3B1X2FkZHI7
DQotCQkJcHAtPmNmZzFfbW9kX2Jhc2UgPSBwcC0+Y2ZnMF9tb2RfYmFzZSArDQotCQkJCQkgICAg
cHAtPmNmZzBfc2l6ZTsNCisJcmVzb3VyY2VfbGlzdF9mb3JfZWFjaF9lbnRyeSh3aW4sICZyZXMp
IHsNCisJCXN3aXRjaCAocmVzb3VyY2VfdHlwZSh3aW4tPnJlcykpIHsNCisJCWNhc2UgSU9SRVNP
VVJDRV9JTzoNCisJCQlwcC0+aW8gPSB3aW4tPnJlczsNCisJCQlwcC0+aW8tPm5hbWUgPSAiSS9P
IjsNCisJCQlwcC0+aW9fc2l6ZSA9IHJlc291cmNlX3NpemUocHAtPmlvKTsNCisJCQlwcC0+aW9f
YnVzX2FkZHIgPSBwcC0+aW8tPnN0YXJ0IC0gd2luLT5vZmZzZXQ7DQorCQkJcmV0ID0gcGNpX3Jl
bWFwX2lvc3BhY2UocHAtPmlvLCBwcC0+aW9fYmFzZSk7DQorCQkJaWYgKHJldCkgew0KKwkJCQlk
ZXZfd2FybihwcC0+ZGV2LCAiZXJyb3IgJWQ6IGZhaWxlZCB0byBtYXAgcmVzb3VyY2UgJXBSXG4i
LA0KKwkJCQkJIHJldCwgcHAtPmlvKTsNCisJCQkJY29udGludWU7DQorCQkJfQ0KKwkJCWJyZWFr
Ow0KKwkJY2FzZSBJT1JFU09VUkNFX01FTToNCisJCQlwcC0+bWVtID0gd2luLT5yZXM7DQorCQkJ
cHAtPm1lbS0+bmFtZSA9ICJNRU0iOw0KKwkJCXBwLT5tZW1fc2l6ZSA9IHJlc291cmNlX3NpemUo
cHAtPm1lbSk7DQorCQkJcHAtPm1lbV9idXNfYWRkciA9IHBwLT5tZW0tPnN0YXJ0IC0gd2luLT5v
ZmZzZXQ7DQorCQkJYnJlYWs7DQorCQljYXNlIDA6DQorCQkJcHAtPmNmZyA9IHdpbi0+cmVzOw0K
KwkJCXBwLT5jZmcwX3NpemUgPSByZXNvdXJjZV9zaXplKHBwLT5jZmcpLzI7DQorCQkJcHAtPmNm
ZzFfc2l6ZSA9IHJlc291cmNlX3NpemUocHAtPmNmZykvMjsNCisJCQlwcC0+Y2ZnMF9iYXNlID0g
cHAtPmNmZy0+c3RhcnQ7DQorCQkJcHAtPmNmZzFfYmFzZSA9IHBwLT5jZmctPnN0YXJ0ICsgcHAt
PmNmZzBfc2l6ZTsNCisJCQlicmVhazsNCisJCWNhc2UgSU9SRVNPVVJDRV9CVVM6DQorCQkJcHAt
PmJ1c24gPSB3aW4tPnJlczsNCisJCQlicmVhazsNCisJCWRlZmF1bHQ6DQorCQkJY29udGludWU7
DQogCQl9DQogCX0NCiANCi0JcmV0ID0gb2ZfcGNpX3BhcnNlX2J1c19yYW5nZShucCwgJnBwLT5i
dXNuKTsNCi0JaWYgKHJldCA8IDApIHsNCi0JCXBwLT5idXNuLm5hbWUgPSBucC0+bmFtZTsNCi0J
CXBwLT5idXNuLnN0YXJ0ID0gMDsNCi0JCXBwLT5idXNuLmVuZCA9IDB4ZmY7DQotCQlwcC0+YnVz
bi5mbGFncyA9IElPUkVTT1VSQ0VfQlVTOw0KLQkJZGV2X2RiZyhwcC0+ZGV2LCAiZmFpbGVkIHRv
IHBhcnNlIGJ1cy1yYW5nZSBwcm9wZXJ0eTogJWQsIHVzaW5nIGRlZmF1bHQgJXBSXG4iLA0KLQkJ
CXJldCwgJnBwLT5idXNuKTsNCi0JfQ0KLQ0KIAlpZiAoIXBwLT5kYmlfYmFzZSkgew0KLQkJcHAt
PmRiaV9iYXNlID0gZGV2bV9pb3JlbWFwKHBwLT5kZXYsIHBwLT5jZmcuc3RhcnQsDQotCQkJCQly
ZXNvdXJjZV9zaXplKCZwcC0+Y2ZnKSk7DQorCQlwcC0+ZGJpX2Jhc2UgPSBkZXZtX2lvcmVtYXAo
cHAtPmRldiwgcHAtPmNmZy0+c3RhcnQsDQorCQkJCQlyZXNvdXJjZV9zaXplKHBwLT5jZmcpKTsN
CiAJCWlmICghcHAtPmRiaV9iYXNlKSB7DQogCQkJZGV2X2VycihwcC0+ZGV2LCAiZXJyb3Igd2l0
aCBpb3JlbWFwXG4iKTsNCiAJCQlyZXR1cm4gLUVOT01FTTsNCiAJCX0NCiAJfQ0KIA0KLQlwcC0+
bWVtX2Jhc2UgPSBwcC0+bWVtLnN0YXJ0Ow0KKwlwcC0+bWVtX2Jhc2UgPSBwcC0+bWVtLT5zdGFy
dDsNCiANCiAJaWYgKCFwcC0+dmFfY2ZnMF9iYXNlKSB7DQogCQlwcC0+dmFfY2ZnMF9iYXNlID0g
ZGV2bV9pb3JlbWFwKHBwLT5kZXYsIHBwLT5jZmcwX2Jhc2UsDQpAQCAtNTA5LDcgKzQ3Myw3IEBA
IGludCBkd19wY2llX2hvc3RfaW5pdChzdHJ1Y3QgcGNpZV9wb3J0ICpwcCkNCiANCiAJaWYgKCFw
cC0+b3BzLT5yZF9vdGhlcl9jb25mKQ0KIAkJZHdfcGNpZV9wcm9nX291dGJvdW5kX2F0dShwcCwg
UENJRV9BVFVfUkVHSU9OX0lOREVYMSwNCi0JCQkJCSAgUENJRV9BVFVfVFlQRV9NRU0sIHBwLT5t
ZW1fbW9kX2Jhc2UsDQorCQkJCQkgIFBDSUVfQVRVX1RZUEVfTUVNLCBwcC0+bWVtX2Jhc2UsDQog
CQkJCQkgIHBwLT5tZW1fYnVzX2FkZHIsIHBwLT5tZW1fc2l6ZSk7DQogDQogCWR3X3BjaWVfd3Jf
b3duX2NvbmYocHAsIFBDSV9CQVNFX0FERFJFU1NfMCwgNCwgMCk7DQpAQCAtNTIxLDE1ICs0ODUs
NDAgQEAgaW50IGR3X3BjaWVfaG9zdF9pbml0KHN0cnVjdCBwY2llX3BvcnQgKnBwKQ0KIAl2YWwg
fD0gUE9SVF9MT0dJQ19TUEVFRF9DSEFOR0U7DQogCWR3X3BjaWVfd3Jfb3duX2NvbmYocHAsIFBD
SUVfTElOS19XSURUSF9TUEVFRF9DT05UUk9MLCA0LCB2YWwpOw0KIA0KLSNpZmRlZiBDT05GSUdf
UENJX01TSQ0KIAlkd19wY2llX21zaV9jaGlwLmRldiA9IHBwLT5kZXY7DQotCWR3X3BjaS5tc2lf
Y3RybCA9ICZkd19wY2llX21zaV9jaGlwOw0KKw0KKwltdXRleF9sb2NrKCZyb290X2J1c19ucl9t
dXgpOw0KKw0KKwlpZiAocHAtPnJvb3RfYnVzX25yICE9IERXX1JPT1RfTlJfVU5ERUZJTkVEKQ0K
KwkJcm9vdF9idXNfbnIgPSBwcC0+cm9vdF9idXNfbnI7DQorDQorCWJ1cyA9IHBjaV9jcmVhdGVf
cm9vdF9idXMocHAtPmRldiwgcm9vdF9idXNfbnIsICZkd19wY2llX29wcywNCisJCQkgICAgICBw
cCwgJnJlcyk7DQorCWlmICghYnVzKSB7DQorCQltdXRleF91bmxvY2soJnJvb3RfYnVzX25yX211
eCk7DQorCQlyZXR1cm4gLUVOT01FTTsNCisJfQ0KKw0KKwlyb290X2J1c19uciArPSBidXMtPmJ1
c25fcmVzLmVuZCArIDE7DQorCW11dGV4X3VubG9jaygmcm9vdF9idXNfbnJfbXV4KTsNCisNCisj
aWZkZWYgQ09ORklHX0dFTkVSSUNfTVNJX0lSUV9ET01BSU4NCisJYnVzLT5tc2kgPSBjb250YWlu
ZXJfb2YoJnBwLT5pcnFfZG9tYWluLCBzdHJ1Y3QgbXNpX2NvbnRyb2xsZXIsIGRvbWFpbik7DQor
I2Vsc2UNCisJYnVzLT5tc2kgPSAmZHdfcGNpZV9tc2lfY2hpcDsNCiAjZW5kaWYNCiANCi0JZHdf
cGNpLm5yX2NvbnRyb2xsZXJzID0gMTsNCi0JZHdfcGNpLnByaXZhdGVfZGF0YSA9ICh2b2lkICoq
KSZwcDsNCisJcGNpX3NjYW5fY2hpbGRfYnVzKGJ1cyk7DQorCWlmIChwcC0+b3BzLT5zY2FuX2J1
cykNCisJCXBwLT5vcHMtPnNjYW5fYnVzKHBwKTsNCisNCisjaWZkZWYgQ09ORklHX0FSTQ0KKwkv
KiBzdXBwb3J0IG9sZCBkdGJzIHRoYXQgaW5jb3JyZWN0bHkgZGVzY3JpYmUgSVJRcyAqLw0KKwlw
Y2lfZml4dXBfaXJxcyhwY2lfY29tbW9uX3N3aXp6bGUsIG9mX2lycV9wYXJzZV9hbmRfbWFwX3Bj
aSk7DQorI2VuZGlmDQogDQotCXBjaV9jb21tb25faW5pdF9kZXYocHAtPmRldiwgJmR3X3BjaSk7
DQorCXBjaV9hc3NpZ25fdW5hc3NpZ25lZF9idXNfcmVzb3VyY2VzKGJ1cyk7DQorCXBjaV9idXNf
YWRkX2RldmljZXMoYnVzKTsNCiANCiAJcmV0dXJuIDA7DQogfQ0KQEAgLTU0OCwxMiArNTM3LDEy
IEBAIHN0YXRpYyBpbnQgZHdfcGNpZV9yZF9vdGhlcl9jb25mKHN0cnVjdCBwY2llX3BvcnQgKnBw
LCBzdHJ1Y3QgcGNpX2J1cyAqYnVzLA0KIA0KIAlpZiAoYnVzLT5wYXJlbnQtPm51bWJlciA9PSBw
cC0+cm9vdF9idXNfbnIpIHsNCiAJCXR5cGUgPSBQQ0lFX0FUVV9UWVBFX0NGRzA7DQotCQljcHVf
YWRkciA9IHBwLT5jZmcwX21vZF9iYXNlOw0KKwkJY3B1X2FkZHIgPSBwcC0+Y2ZnMF9iYXNlOw0K
IAkJY2ZnX3NpemUgPSBwcC0+Y2ZnMF9zaXplOw0KIAkJdmFfY2ZnX2Jhc2UgPSBwcC0+dmFfY2Zn
MF9iYXNlOw0KIAl9IGVsc2Ugew0KIAkJdHlwZSA9IFBDSUVfQVRVX1RZUEVfQ0ZHMTsNCi0JCWNw
dV9hZGRyID0gcHAtPmNmZzFfbW9kX2Jhc2U7DQorCQljcHVfYWRkciA9IHBwLT5jZmcxX2Jhc2U7
DQogCQljZmdfc2l6ZSA9IHBwLT5jZmcxX3NpemU7DQogCQl2YV9jZmdfYmFzZSA9IHBwLT52YV9j
ZmcxX2Jhc2U7DQogCX0NCkBAIC01NjMsNyArNTUyLDcgQEAgc3RhdGljIGludCBkd19wY2llX3Jk
X290aGVyX2NvbmYoc3RydWN0IHBjaWVfcG9ydCAqcHAsIHN0cnVjdCBwY2lfYnVzICpidXMsDQog
CQkJCSAgYnVzZGV2LCBjZmdfc2l6ZSk7DQogCXJldCA9IGR3X3BjaWVfY2ZnX3JlYWQodmFfY2Zn
X2Jhc2UgKyBhZGRyZXNzLCB3aGVyZSwgc2l6ZSwgdmFsKTsNCiAJZHdfcGNpZV9wcm9nX291dGJv
dW5kX2F0dShwcCwgUENJRV9BVFVfUkVHSU9OX0lOREVYMCwNCi0JCQkJICBQQ0lFX0FUVV9UWVBF
X0lPLCBwcC0+aW9fbW9kX2Jhc2UsDQorCQkJCSAgUENJRV9BVFVfVFlQRV9JTywgcHAtPmlvX2Jh
c2UsDQogCQkJCSAgcHAtPmlvX2J1c19hZGRyLCBwcC0+aW9fc2l6ZSk7DQogDQogCXJldHVybiBy
ZXQ7DQpAQCAtNTgzLDEyICs1NzIsMTIgQEAgc3RhdGljIGludCBkd19wY2llX3dyX290aGVyX2Nv
bmYoc3RydWN0IHBjaWVfcG9ydCAqcHAsIHN0cnVjdCBwY2lfYnVzICpidXMsDQogDQogCWlmIChi
dXMtPnBhcmVudC0+bnVtYmVyID09IHBwLT5yb290X2J1c19ucikgew0KIAkJdHlwZSA9IFBDSUVf
QVRVX1RZUEVfQ0ZHMDsNCi0JCWNwdV9hZGRyID0gcHAtPmNmZzBfbW9kX2Jhc2U7DQorCQljcHVf
YWRkciA9IHBwLT5jZmcwX2Jhc2U7DQogCQljZmdfc2l6ZSA9IHBwLT5jZmcwX3NpemU7DQogCQl2
YV9jZmdfYmFzZSA9IHBwLT52YV9jZmcwX2Jhc2U7DQogCX0gZWxzZSB7DQogCQl0eXBlID0gUENJ
RV9BVFVfVFlQRV9DRkcxOw0KLQkJY3B1X2FkZHIgPSBwcC0+Y2ZnMV9tb2RfYmFzZTsNCisJCWNw
dV9hZGRyID0gcHAtPmNmZzFfYmFzZTsNCiAJCWNmZ19zaXplID0gcHAtPmNmZzFfc2l6ZTsNCiAJ
CXZhX2NmZ19iYXNlID0gcHAtPnZhX2NmZzFfYmFzZTsNCiAJfQ0KQEAgLTU5OCw3ICs1ODcsNyBA
QCBzdGF0aWMgaW50IGR3X3BjaWVfd3Jfb3RoZXJfY29uZihzdHJ1Y3QgcGNpZV9wb3J0ICpwcCwg
c3RydWN0IHBjaV9idXMgKmJ1cywNCiAJCQkJICBidXNkZXYsIGNmZ19zaXplKTsNCiAJcmV0ID0g
ZHdfcGNpZV9jZmdfd3JpdGUodmFfY2ZnX2Jhc2UgKyBhZGRyZXNzLCB3aGVyZSwgc2l6ZSwgdmFs
KTsNCiAJZHdfcGNpZV9wcm9nX291dGJvdW5kX2F0dShwcCwgUENJRV9BVFVfUkVHSU9OX0lOREVY
MCwNCi0JCQkJICBQQ0lFX0FUVV9UWVBFX0lPLCBwcC0+aW9fbW9kX2Jhc2UsDQorCQkJCSAgUENJ
RV9BVFVfVFlQRV9JTywgcHAtPmlvX2Jhc2UsDQogCQkJCSAgcHAtPmlvX2J1c19hZGRyLCBwcC0+
aW9fc2l6ZSk7DQogDQogCXJldHVybiByZXQ7DQpAQCAtNjMwLDcgKzYxOSw3IEBAIHN0YXRpYyBp
bnQgZHdfcGNpZV92YWxpZF9jb25maWcoc3RydWN0IHBjaWVfcG9ydCAqcHAsDQogc3RhdGljIGlu
dCBkd19wY2llX3JkX2NvbmYoc3RydWN0IHBjaV9idXMgKmJ1cywgdTMyIGRldmZuLCBpbnQgd2hl
cmUsDQogCQkJaW50IHNpemUsIHUzMiAqdmFsKQ0KIHsNCi0Jc3RydWN0IHBjaWVfcG9ydCAqcHAg
PSBzeXNfdG9fcGNpZShidXMtPnN5c2RhdGEpOw0KKwlzdHJ1Y3QgcGNpZV9wb3J0ICpwcCA9IGJ1
cy0+c3lzZGF0YTsNCiAJaW50IHJldDsNCiANCiAJaWYgKGR3X3BjaWVfdmFsaWRfY29uZmlnKHBw
LCBidXMsIFBDSV9TTE9UKGRldmZuKSkgPT0gMCkgew0KQEAgLTY1NCw3ICs2NDMsNyBAQCBzdGF0
aWMgaW50IGR3X3BjaWVfcmRfY29uZihzdHJ1Y3QgcGNpX2J1cyAqYnVzLCB1MzIgZGV2Zm4sIGlu
dCB3aGVyZSwNCiBzdGF0aWMgaW50IGR3X3BjaWVfd3JfY29uZihzdHJ1Y3QgcGNpX2J1cyAqYnVz
LCB1MzIgZGV2Zm4sDQogCQkJaW50IHdoZXJlLCBpbnQgc2l6ZSwgdTMyIHZhbCkNCiB7DQotCXN0
cnVjdCBwY2llX3BvcnQgKnBwID0gc3lzX3RvX3BjaWUoYnVzLT5zeXNkYXRhKTsNCisJc3RydWN0
IHBjaWVfcG9ydCAqcHAgPSBidXMtPnN5c2RhdGE7DQogCWludCByZXQ7DQogDQogCWlmIChkd19w
Y2llX3ZhbGlkX2NvbmZpZyhwcCwgYnVzLCBQQ0lfU0xPVChkZXZmbikpID09IDApDQpAQCAtNjc4
LDYyICs2NjcsNiBAQCBzdGF0aWMgc3RydWN0IHBjaV9vcHMgZHdfcGNpZV9vcHMgPSB7DQogCS53
cml0ZSA9IGR3X3BjaWVfd3JfY29uZiwNCiB9Ow0KIA0KLXN0YXRpYyBpbnQgZHdfcGNpZV9zZXR1
cChpbnQgbnIsIHN0cnVjdCBwY2lfc3lzX2RhdGEgKnN5cykNCi17DQotCXN0cnVjdCBwY2llX3Bv
cnQgKnBwOw0KLQ0KLQlwcCA9IHN5c190b19wY2llKHN5cyk7DQotDQotCWlmIChnbG9iYWxfaW9f
b2Zmc2V0IDwgU1pfMU0gJiYgcHAtPmlvX3NpemUgPiAwKSB7DQotCQlzeXMtPmlvX29mZnNldCA9
IGdsb2JhbF9pb19vZmZzZXQgLSBwcC0+aW9fYnVzX2FkZHI7DQotCQlwY2lfaW9yZW1hcF9pbyhn
bG9iYWxfaW9fb2Zmc2V0LCBwcC0+aW9fYmFzZSk7DQotCQlnbG9iYWxfaW9fb2Zmc2V0ICs9IFNa
XzY0SzsNCi0JCXBjaV9hZGRfcmVzb3VyY2Vfb2Zmc2V0KCZzeXMtPnJlc291cmNlcywgJnBwLT5p
bywNCi0JCQkJCXN5cy0+aW9fb2Zmc2V0KTsNCi0JfQ0KLQ0KLQlzeXMtPm1lbV9vZmZzZXQgPSBw
cC0+bWVtLnN0YXJ0IC0gcHAtPm1lbV9idXNfYWRkcjsNCi0JcGNpX2FkZF9yZXNvdXJjZV9vZmZz
ZXQoJnN5cy0+cmVzb3VyY2VzLCAmcHAtPm1lbSwgc3lzLT5tZW1fb2Zmc2V0KTsNCi0JcGNpX2Fk
ZF9yZXNvdXJjZSgmc3lzLT5yZXNvdXJjZXMsICZwcC0+YnVzbik7DQotDQotCXJldHVybiAxOw0K
LX0NCi0NCi1zdGF0aWMgc3RydWN0IHBjaV9idXMgKmR3X3BjaWVfc2Nhbl9idXMoaW50IG5yLCBz
dHJ1Y3QgcGNpX3N5c19kYXRhICpzeXMpDQotew0KLQlzdHJ1Y3QgcGNpX2J1cyAqYnVzOw0KLQlz
dHJ1Y3QgcGNpZV9wb3J0ICpwcCA9IHN5c190b19wY2llKHN5cyk7DQotDQotCXBwLT5yb290X2J1
c19uciA9IHN5cy0+YnVzbnI7DQotCWJ1cyA9IHBjaV9zY2FuX3Jvb3RfYnVzKHBwLT5kZXYsIHN5
cy0+YnVzbnIsDQotCQkJCSAgJmR3X3BjaWVfb3BzLCBzeXMsICZzeXMtPnJlc291cmNlcyk7DQot
CWlmICghYnVzKQ0KLQkJcmV0dXJuIE5VTEw7DQotDQotCWlmIChidXMgJiYgcHAtPm9wcy0+c2Nh
bl9idXMpDQotCQlwcC0+b3BzLT5zY2FuX2J1cyhwcCk7DQotDQotCXJldHVybiBidXM7DQotfQ0K
LQ0KLXN0YXRpYyBpbnQgZHdfcGNpZV9tYXBfaXJxKGNvbnN0IHN0cnVjdCBwY2lfZGV2ICpkZXYs
IHU4IHNsb3QsIHU4IHBpbikNCi17DQotCXN0cnVjdCBwY2llX3BvcnQgKnBwID0gc3lzX3RvX3Bj
aWUoZGV2LT5idXMtPnN5c2RhdGEpOw0KLQlpbnQgaXJxOw0KLQ0KLQlpcnEgPSBvZl9pcnFfcGFy
c2VfYW5kX21hcF9wY2koZGV2LCBzbG90LCBwaW4pOw0KLQlpZiAoIWlycSkNCi0JCWlycSA9IHBw
LT5pcnE7DQotDQotCXJldHVybiBpcnE7DQotfQ0KLQ0KLXN0YXRpYyBzdHJ1Y3QgaHdfcGNpIGR3
X3BjaSA9IHsNCi0JLnNldHVwCQk9IGR3X3BjaWVfc2V0dXAsDQotCS5zY2FuCQk9IGR3X3BjaWVf
c2Nhbl9idXMsDQotCS5tYXBfaXJxCT0gZHdfcGNpZV9tYXBfaXJxLA0KLX07DQotDQogdm9pZCBk
d19wY2llX3NldHVwX3JjKHN0cnVjdCBwY2llX3BvcnQgKnBwKQ0KIHsNCiAJdTMyIHZhbDsNCmRp
ZmYgLS1naXQgYS9kcml2ZXJzL3BjaS9ob3N0L3BjaWUtZGVzaWdud2FyZS5oIGIvZHJpdmVycy9w
Y2kvaG9zdC9wY2llLWRlc2lnbndhcmUuaA0KaW5kZXggZDBiYmQyNy4uMGMyYTdlYiAxMDA2NDQN
Ci0tLSBhL2RyaXZlcnMvcGNpL2hvc3QvcGNpZS1kZXNpZ253YXJlLmgNCisrKyBiL2RyaXZlcnMv
cGNpL2hvc3QvcGNpZS1kZXNpZ253YXJlLmgNCkBAIC0yMSwzMSArMjEsMjggQEANCiAgKi8NCiAj
ZGVmaW5lIE1BWF9NU0lfSVJRUwkJCTMyDQogI2RlZmluZSBNQVhfTVNJX0NUUkxTCQkJKE1BWF9N
U0lfSVJRUyAvIDMyKQ0KKyNkZWZpbmUgRFdfUk9PVF9OUl9VTkRFRklORUQJLTENCiANCiBzdHJ1
Y3QgcGNpZV9wb3J0IHsNCiAJc3RydWN0IGRldmljZQkJKmRldjsNCiAJdTgJCQlyb290X2J1c19u
cjsNCiAJdm9pZCBfX2lvbWVtCQkqZGJpX2Jhc2U7DQogCXU2NAkJCWNmZzBfYmFzZTsNCi0JdTY0
CQkJY2ZnMF9tb2RfYmFzZTsNCiAJdm9pZCBfX2lvbWVtCQkqdmFfY2ZnMF9iYXNlOw0KIAl1MzIJ
CQljZmcwX3NpemU7DQogCXU2NAkJCWNmZzFfYmFzZTsNCi0JdTY0CQkJY2ZnMV9tb2RfYmFzZTsN
CiAJdm9pZCBfX2lvbWVtCQkqdmFfY2ZnMV9iYXNlOw0KIAl1MzIJCQljZmcxX3NpemU7DQotCXU2
NAkJCWlvX2Jhc2U7DQotCXU2NAkJCWlvX21vZF9iYXNlOw0KKwlyZXNvdXJjZV9zaXplX3QJCWlv
X2Jhc2U7DQogCXBoeXNfYWRkcl90CQlpb19idXNfYWRkcjsNCiAJdTMyCQkJaW9fc2l6ZTsNCiAJ
dTY0CQkJbWVtX2Jhc2U7DQotCXU2NAkJCW1lbV9tb2RfYmFzZTsNCiAJcGh5c19hZGRyX3QJCW1l
bV9idXNfYWRkcjsNCiAJdTMyCQkJbWVtX3NpemU7DQotCXN0cnVjdCByZXNvdXJjZQkJY2ZnOw0K
LQlzdHJ1Y3QgcmVzb3VyY2UJCWlvOw0KLQlzdHJ1Y3QgcmVzb3VyY2UJCW1lbTsNCi0Jc3RydWN0
IHJlc291cmNlCQlidXNuOw0KKwlzdHJ1Y3QgcmVzb3VyY2UJCSpjZmc7DQorCXN0cnVjdCByZXNv
dXJjZQkJKmlvOw0KKwlzdHJ1Y3QgcmVzb3VyY2UJCSptZW07DQorCXN0cnVjdCByZXNvdXJjZQkJ
KmJ1c247DQogCWludAkJCWlycTsNCiAJdTMyCQkJbGFuZXM7DQogCXN0cnVjdCBwY2llX2hvc3Rf
b3BzCSpvcHM7DQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9wY2kvaG9zdC9wY2llLXNwZWFyMTN4eC5j
IGIvZHJpdmVycy9wY2kvaG9zdC9wY2llLXNwZWFyMTN4eC5jDQppbmRleCBjNDlmYmRjLi5iMmM1
OWI5IDEwMDY0NA0KLS0tIGEvZHJpdmVycy9wY2kvaG9zdC9wY2llLXNwZWFyMTN4eC5jDQorKysg
Yi9kcml2ZXJzL3BjaS9ob3N0L3BjaWUtc3BlYXIxM3h4LmMNCkBAIC0yODYsNyArMjg2LDcgQEAg
c3RhdGljIGludCBzcGVhcjEzeHhfYWRkX3BjaWVfcG9ydChzdHJ1Y3QgcGNpZV9wb3J0ICpwcCwN
CiAJCXJldHVybiByZXQ7DQogCX0NCiANCi0JcHAtPnJvb3RfYnVzX25yID0gLTE7DQorCXBwLT5y
b290X2J1c19uciA9IERXX1JPT1RfTlJfVU5ERUZJTkVEOw0KIAlwcC0+b3BzID0gJnNwZWFyMTN4
eF9wY2llX2hvc3Rfb3BzOw0KIA0KIAlyZXQgPSBkd19wY2llX2hvc3RfaW5pdChwcCk7DQotLSAN
CjEuOS4xDQoNCg0KPiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBMdWNhcyBT
dGFjaCBbbWFpbHRvOmwuc3RhY2hAcGVuZ3V0cm9uaXguZGVdDQo+IFNlbnQ6IFdlZG5lc2RheSwg
QXVndXN0IDE5LCAyMDE1IDE6NTQgUE0NCj4gVG86IFdhbmd6aG91IChCKQ0KPiBDYzogQmpvcm4g
SGVsZ2FhczsgamluZ29vaGFuMUBnbWFpbC5jb207IFByYXR5dXNoIEFuYW5kOyBBcm5kIEJlcmdt
YW5uOw0KPiBsaW51eEBhcm0ubGludXgub3JnLnVrOyB0aG9tYXMucGV0YXp6b25pQGZyZWUtZWxl
Y3Ryb25zLmNvbTsgR2FicmllbGUNCj4gUGFvbG9uaTsgbG9yZW56by5waWVyYWxpc2lAYXJtLmNv
bTsgamFtZXMubW9yc2VAYXJtLmNvbTsNCj4gTGl2aXUuRHVkYXVAYXJtLmNvbTsgamFzb25AbGFr
ZWRhZW1vbi5uZXQ7IHJvYmhAa2VybmVsLm9yZzsgbGludXgtDQo+IHBjaUB2Z2VyLmtlcm5lbC5v
cmc7IGxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZzsNCj4gZGV2aWNldHJlZUB2
Z2VyLmtlcm5lbC5vcmc7IFl1YW56aGljaGFuZzsgWmh1ZGFjYWk7IHpoYW5nanVrdW87DQo+IHFp
dXpoZW5mYTsgbGl1ZG9uZ2RvbmcgKEMpOyBxaXVqaWFuZzsgeHV3ZWkgKE8pOyBMaWd1b3podSAo
S2VubmV0aCkNCj4gU3ViamVjdDogUmU6IFtQQVRDSCB2NyAzLzZdIFBDSTogZGVzaWdud2FyZTog
QWRkIEFSTTY0IHN1cHBvcnQNCj4gDQo+IEFtIE1vbnRhZywgZGVuIDE3LjA4LjIwMTUsIDE5OjU1
ICswODAwIHNjaHJpZWIgWmhvdSBXYW5nOg0KPiA+IFRoaXMgcGF0Y2ggdHJpZXMgdG8gdW5pZnkg
QVJNMzIgYW5kIEFSTTY0IFBDSWUgaW4gZGVzaWdud2FyZSBkcml2ZXIuDQo+IERlbGV0ZQ0KPiA+
IGZ1bmN0aW9uIGR3X3BjaWVfc2V0dXAsIGR3X3BjaWVfc2Nhbl9idXMsIGR3X3BjaWVfbWFwX2ly
cSBhbmQgc3RydWN0DQo+IGh3X3BjaSwNCj4gPiBtb3ZlIHJlbGF0ZWQgb3BlcmF0aW9ucyB0byBk
d19wY2llX2hvc3RfaW5pdC4NCj4gPg0KPiA+IEluIHBhc3QsIHdlIHVzZToNCj4gPiBwY2lfY29t
bW9uX2luaXRfZGV2DQo+ID4gCS0+IHBjaWJpb3NfaW5pdF9odw0KPiA+IAkJLT4gaHctPnNjYW4g
KGR3X3BjaWVfc2Nhbl9idXMpDQo+ID4gdG8gcGFzcyAwIHRvIHJvb3RfYnVzX25yIGluIHN0cnVj
dCBwY2llX3BvcnQuIFRoaXMgcGF0Y2ggc2V0IHBwLQ0KPiA+cm9vdF9idXNfbnIgPSAwDQo+ID4g
aW4gZWFjaCBQQ0llIGhvc3QgZHJpdmVyIHdoaWNoIGlzIGJhc2VkIG9uIHBjaWUtZGVzaWdud2Fy
ZS4NCj4gPg0KPiBUaGlzIGlzIGluY29ycmVjdCBhdCBsZWFzdCBpZiB0aGVyZSBhcmUgMiBpbnN0
YW5jZXMgb2YgRFcgUENJZSBob3N0IGluDQo+IHRoZSBzYW1lIFNvQyB3aXRob3V0IHVzaW5nIFBD
SSBkb21haW5zLiBJbiB0aGF0IHRoZSBjYXNlIHRoZSBidXMgcmFuZ2UNCj4gZGV0ZXJtaW5lcyB0
aGUgcmFuZ2Ugb2YgdmFsaWQgYnVzIG51bWJlcnMgcGVyIGluc3RhbmNlIGFuZCB0aGUgZmlyc3QN
Cj4gbnVtYmVyIGlzIHRoZSByb290IGJ1cy4gUGxlYXNlIGxvb2sgYXQgdGhlICJidXMtcmFuZ2Ui
IERUIHByb3BlcnR5IGluDQo+IHRoZSBEVyBQQ0llIGJpbmRpbmdzLg0KPiANCj4gQWxzbyB3ZSBz
aG91bGQgZmluYWxseSByZW1vdmUgdGhpcyByb290LWJ1cyBzZXR1cCBmcm9tIHRoZSBnbHVlIGRy
aXZlcnMNCj4gYWx0b2dldGhlci4gSXQncyBzb21ldGhpbmcgdGhhdCBlbnRpcmVseSBiZWxvbmdz
IGludG8gdGhlIERXIGNvcmUgY29kZS4NCj4gDQo+IFJlZ2FyZHMsDQo+IEx1Y2FzDQo+IA0KPiA+
IFRoaXMgcGF0Y2ggYWxzbyB0cnkgdG8gdXNlIG9mX3BjaV9nZXRfaG9zdF9icmlkZ2VfcmVzb3Vy
Y2VzIGZvciBBUk0zMg0KPiBhbmQgQVJNNjQNCj4gPiBhY2NvcmRpbmcgdG8gdGhlIHN1Z2dlc3Rp
b24gZm9yIEdhYnJpZWxlWzFdDQo+ID4NCj4gPiBGaW5hbGx5IHRoaXMgcGF0Y2ggcmV2ZXJ0cyBj
b21taXQgZjRjNTVjNWEzZjdmICJQQ0k6IGRlc2lnbndhcmU6DQo+IFByb2dyYW0gQVRVDQo+ID4g
d2l0aCB1bnRyYW5zbGF0ZWQgYWRkcmVzcyIgYmFzZWQgb24gMS82IGluIHRoaXMgc2VyaWVzLiB3
ZSBkZWxldGUNCj4gKl9tb2RfYmFzZSBpbg0KPiA+IHBjaWUtZGVzaWdud2FyZS4gVGhpcyB3YXMg
ZGlzY3Vzc2VkIGluIFsyXQ0KPiA+DQo+ID4gSSBoYXZlIGNvbXBpbGVkIHRoZSBkcml2ZXIgd2l0
aCBtdWx0aV92N19kZWZjb25maWcuIEhvd2V2ZXIsIEkgZG9uJ3QNCj4gaGF2ZQ0KPiA+IEFSTTMy
IFBDSWUgcmVsYXRlZCBib2FyZCB0byBkbyB0ZXN0LiBJdCB3aWxsIGJlIGFwcHJlY2lhdGVkIGlm
DQo+IHNvbWVvbmUgY291bGQNCj4gPiBoZWxwIHRvIHRlc3QgaXQuDQo+ID4NCj4gPiBTaWduZWQt
b2ZmLWJ5OiBaaG91IFdhbmcgPHdhbmd6aG91MUBoaXNpbGljb24uY29tPg0KPiA+IFNpZ25lZC1v
ZmYtYnk6IEdhYnJpZWxlIFBhb2xvbmkgPGdhYnJpZWxlLnBhb2xvbmlAaHVhd2VpLmNvbT4NCj4g
PiBTaWduZWQtb2ZmLWJ5OiBBcm5kIEJlcmdtYW5uIDxhcm5kQGFybmRiLmRlPg0KPiA+IFRlc3Rl
ZC1CeTogSmFtZXMgTW9yc2UgPGphbWVzLm1vcnNlQGFybS5jb20+DQo+ID4NCj4gPiBbMV0gaHR0
cDovL3d3dy5zcGluaWNzLm5ldC9saXN0cy9saW51eC1wY2kvbXNnNDIxOTQuaHRtbA0KPiA+IFsy
XSBodHRwOi8vd3d3LnNwaW5pY3MubmV0L2xpc3RzL2FybS1rZXJuZWwvbXNnNDM2Nzc5Lmh0bWwN
Cj4gPiAtLS0NCj4gPiAgZHJpdmVycy9wY2kvaG9zdC9wY2ktZHJhN3h4LmMgICAgICB8ICAxNSAr
LS0NCj4gPiAgZHJpdmVycy9wY2kvaG9zdC9wY2ktZXh5bm9zLmMgICAgICB8ICAgMiArLQ0KPiA+
ICBkcml2ZXJzL3BjaS9ob3N0L3BjaS1pbXg2LmMgICAgICAgIHwgICAyICstDQo+ID4gIGRyaXZl
cnMvcGNpL2hvc3QvcGNpLWtleXN0b25lLWR3LmMgfCAgIDIgKy0NCj4gPiAgZHJpdmVycy9wY2kv
aG9zdC9wY2kta2V5c3RvbmUuYyAgICB8ICAgMiArLQ0KPiA+ICBkcml2ZXJzL3BjaS9ob3N0L3Bj
aS1sYXllcnNjYXBlLmMgIHwgICAyICstDQo+ID4gIGRyaXZlcnMvcGNpL2hvc3QvcGNpZS1kZXNp
Z253YXJlLmMgfCAyMjkgKysrKysrKysrKysrLS0tLS0tLS0tLS0tLS0tDQo+IC0tLS0tLS0tLS0N
Cj4gPiAgZHJpdmVycy9wY2kvaG9zdC9wY2llLWRlc2lnbndhcmUuaCB8ICAxNCArLS0NCj4gPiAg
ZHJpdmVycy9wY2kvaG9zdC9wY2llLXNwZWFyMTN4eC5jICB8ICAgMiArLQ0KPiA+ICA5IGZpbGVz
IGNoYW5nZWQsIDk1IGluc2VydGlvbnMoKyksIDE3NSBkZWxldGlvbnMoLSkNCj4gPg0KPiA+IGRp
ZmYgLS1naXQgYS9kcml2ZXJzL3BjaS9ob3N0L3BjaS1kcmE3eHguYyBiL2RyaXZlcnMvcGNpL2hv
c3QvcGNpLQ0KPiBkcmE3eHguYw0KPiA+IGluZGV4IDE4YWU3ZmYuLjEyNjhjNjkgMTAwNjQ0DQo+
ID4gLS0tIGEvZHJpdmVycy9wY2kvaG9zdC9wY2ktZHJhN3h4LmMNCj4gPiArKysgYi9kcml2ZXJz
L3BjaS9ob3N0L3BjaS1kcmE3eHguYw0KPiA+IEBAIC0xNDEsMTUgKzE0MSwxNSBAQCBzdGF0aWMg
dm9pZCBkcmE3eHhfcGNpZV9ob3N0X2luaXQoc3RydWN0DQo+IHBjaWVfcG9ydCAqcHApDQo+ID4g
IHsNCj4gPiAgCWR3X3BjaWVfc2V0dXBfcmMocHApOw0KPiA+DQo+ID4gLQlpZiAocHAtPmlvX21v
ZF9iYXNlKQ0KPiA+IC0JCXBwLT5pb19tb2RfYmFzZSAmPSBDUFVfVE9fQlVTX0FERFI7DQo+ID4g
KwlpZiAocHAtPmlvX2Jhc2UpDQo+ID4gKwkJcHAtPmlvX2Jhc2UgJj0gQ1BVX1RPX0JVU19BRERS
Ow0KPiA+DQo+ID4gLQlpZiAocHAtPm1lbV9tb2RfYmFzZSkNCj4gPiAtCQlwcC0+bWVtX21vZF9i
YXNlICY9IENQVV9UT19CVVNfQUREUjsNCj4gPiArCWlmIChwcC0+bWVtX2Jhc2UpDQo+ID4gKwkJ
cHAtPm1lbV9iYXNlICY9IENQVV9UT19CVVNfQUREUjsNCj4gPg0KPiA+IC0JaWYgKHBwLT5jZmcw
X21vZF9iYXNlKSB7DQo+ID4gLQkJcHAtPmNmZzBfbW9kX2Jhc2UgJj0gQ1BVX1RPX0JVU19BRERS
Ow0KPiA+IC0JCXBwLT5jZmcxX21vZF9iYXNlICY9IENQVV9UT19CVVNfQUREUjsNCj4gPiArCWlm
IChwcC0+Y2ZnMF9iYXNlKSB7DQo+ID4gKwkJcHAtPmNmZzBfYmFzZSAmPSBDUFVfVE9fQlVTX0FE
RFI7DQo+ID4gKwkJcHAtPmNmZzFfYmFzZSAmPSBDUFVfVE9fQlVTX0FERFI7DQo+ID4gIAl9DQo+
ID4NCj4gPiAgCWRyYTd4eF9wY2llX2VzdGFibGlzaF9saW5rKHBwKTsNCj4gPiBAQCAtMjg4LDYg
KzI4OCw3IEBAIHN0YXRpYyBpbnQgX19pbml0IGRyYTd4eF9hZGRfcGNpZV9wb3J0KHN0cnVjdA0K
PiBkcmE3eHhfcGNpZSAqZHJhN3h4LA0KPiA+DQo+ID4gIAlwcCA9ICZkcmE3eHgtPnBwOw0KPiA+
ICAJcHAtPmRldiA9IGRldjsNCj4gPiArCXBwLT5yb290X2J1c19uciA9IDA7DQo+ID4gIAlwcC0+
b3BzID0gJmRyYTd4eF9wY2llX2hvc3Rfb3BzOw0KPiA+DQo+ID4gIAlwcC0+aXJxID0gcGxhdGZv
cm1fZ2V0X2lycShwZGV2LCAxKTsNCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9wY2kvaG9zdC9w
Y2ktZXh5bm9zLmMgYi9kcml2ZXJzL3BjaS9ob3N0L3BjaS0NCj4gZXh5bm9zLmMNCj4gPiBpbmRl
eCBmOWY0NjhkLi45NzcxYmIwIDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvcGNpL2hvc3QvcGNp
LWV4eW5vcy5jDQo+ID4gKysrIGIvZHJpdmVycy9wY2kvaG9zdC9wY2ktZXh5bm9zLmMNCj4gPiBA
QCAtNTMwLDcgKzUzMCw3IEBAIHN0YXRpYyBpbnQgX19pbml0IGV4eW5vc19hZGRfcGNpZV9wb3J0
KHN0cnVjdA0KPiBwY2llX3BvcnQgKnBwLA0KPiA+ICAJCX0NCj4gPiAgCX0NCj4gPg0KPiA+IC0J
cHAtPnJvb3RfYnVzX25yID0gLTE7DQo+ID4gKwlwcC0+cm9vdF9idXNfbnIgPSAwOw0KPiA+ICAJ
cHAtPm9wcyA9ICZleHlub3NfcGNpZV9ob3N0X29wczsNCj4gPg0KPiA+ICAJcmV0ID0gZHdfcGNp
ZV9ob3N0X2luaXQocHApOw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3BjaS9ob3N0L3BjaS1p
bXg2LmMgYi9kcml2ZXJzL3BjaS9ob3N0L3BjaS0NCj4gaW14Ni5jDQo+ID4gaW5kZXggMjMzYTE5
Ni4uYmVjMjU2YyAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL3BjaS9ob3N0L3BjaS1pbXg2LmMN
Cj4gPiArKysgYi9kcml2ZXJzL3BjaS9ob3N0L3BjaS1pbXg2LmMNCj4gPiBAQCAtNTUxLDcgKzU1
MSw3IEBAIHN0YXRpYyBpbnQgX19pbml0IGlteDZfYWRkX3BjaWVfcG9ydChzdHJ1Y3QNCj4gcGNp
ZV9wb3J0ICpwcCwNCj4gPiAgCQl9DQo+ID4gIAl9DQo+ID4NCj4gPiAtCXBwLT5yb290X2J1c19u
ciA9IC0xOw0KPiA+ICsJcHAtPnJvb3RfYnVzX25yID0gMDsNCj4gPiAgCXBwLT5vcHMgPSAmaW14
Nl9wY2llX2hvc3Rfb3BzOw0KPiA+DQo+ID4gIAlyZXQgPSBkd19wY2llX2hvc3RfaW5pdChwcCk7
DQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvcGNpL2hvc3QvcGNpLWtleXN0b25lLWR3LmMNCj4g
Yi9kcml2ZXJzL3BjaS9ob3N0L3BjaS1rZXlzdG9uZS1kdy5jDQo+ID4gaW5kZXggZjM0ODkyZS4u
YjFlNDEzNSAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL3BjaS9ob3N0L3BjaS1rZXlzdG9uZS1k
dy5jDQo+ID4gKysrIGIvZHJpdmVycy9wY2kvaG9zdC9wY2kta2V5c3RvbmUtZHcuYw0KPiA+IEBA
IC0zMjcsNyArMzI3LDcgQEAgc3RhdGljIHZvaWQga3NfZHdfcGNpZV9jbGVhcl9kYmlfbW9kZSh2
b2lkDQo+IF9faW9tZW0gKnJlZ192aXJ0KQ0KPiA+ICB2b2lkIGtzX2R3X3BjaWVfc2V0dXBfcmNf
YXBwX3JlZ3Moc3RydWN0IGtleXN0b25lX3BjaWUgKmtzX3BjaWUpDQo+ID4gIHsNCj4gPiAgCXN0
cnVjdCBwY2llX3BvcnQgKnBwID0gJmtzX3BjaWUtPnBwOw0KPiA+IC0JdTMyIHN0YXJ0ID0gcHAt
Pm1lbS5zdGFydCwgZW5kID0gcHAtPm1lbS5lbmQ7DQo+ID4gKwl1MzIgc3RhcnQgPSBwcC0+bWVt
LT5zdGFydCwgZW5kID0gcHAtPm1lbS0+ZW5kOw0KPiA+ICAJaW50IGksIHRyX3NpemU7DQo+ID4N
Cj4gPiAgCS8qIERpc2FibGUgQkFScyBmb3IgaW5ib3VuZCBhY2Nlc3MgKi8NCj4gPiBkaWZmIC0t
Z2l0IGEvZHJpdmVycy9wY2kvaG9zdC9wY2kta2V5c3RvbmUuYyBiL2RyaXZlcnMvcGNpL2hvc3Qv
cGNpLQ0KPiBrZXlzdG9uZS5jDQo+ID4gaW5kZXggNzM0ZGE1OC4uODExMzgzMiAxMDA2NDQNCj4g
PiAtLS0gYS9kcml2ZXJzL3BjaS9ob3N0L3BjaS1rZXlzdG9uZS5jDQo+ID4gKysrIGIvZHJpdmVy
cy9wY2kvaG9zdC9wY2kta2V5c3RvbmUuYw0KPiA+IEBAIC0zMDksNyArMzA5LDcgQEAgc3RhdGlj
IGludCBfX2luaXQga3NfYWRkX3BjaWVfcG9ydChzdHJ1Y3QNCj4ga2V5c3RvbmVfcGNpZSAqa3Nf
cGNpZSwNCj4gPiAgCQkJcmV0dXJuIHJldDsNCj4gPiAgCX0NCj4gPg0KPiA+IC0JcHAtPnJvb3Rf
YnVzX25yID0gLTE7DQo+ID4gKwlwcC0+cm9vdF9idXNfbnIgPSAwOw0KPiA+ICAJcHAtPm9wcyA9
ICZrZXlzdG9uZV9wY2llX2hvc3Rfb3BzOw0KPiA+ICAJcmV0ID0ga3NfZHdfcGNpZV9ob3N0X2lu
aXQoa3NfcGNpZSwga3NfcGNpZS0+bXNpX2ludGNfbnApOw0KPiA+ICAJaWYgKHJldCkgew0KPiA+
IGRpZmYgLS1naXQgYS9kcml2ZXJzL3BjaS9ob3N0L3BjaS1sYXllcnNjYXBlLmMNCj4gYi9kcml2
ZXJzL3BjaS9ob3N0L3BjaS1sYXllcnNjYXBlLmMNCj4gPiBpbmRleCBiMjMyOGVhMS4uNzlmZjA4
YyAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL3BjaS9ob3N0L3BjaS1sYXllcnNjYXBlLmMNCj4g
PiArKysgYi9kcml2ZXJzL3BjaS9ob3N0L3BjaS1sYXllcnNjYXBlLmMNCj4gPiBAQCAtMTA2LDcg
KzEwNiw3IEBAIHN0YXRpYyBpbnQgbHNfYWRkX3BjaWVfcG9ydChzdHJ1Y3QgbHNfcGNpZSAqcGNp
ZSkNCj4gPiAgCXBwID0gJnBjaWUtPnBwOw0KPiA+ICAJcHAtPmRldiA9IHBjaWUtPmRldjsNCj4g
PiAgCXBwLT5kYmlfYmFzZSA9IHBjaWUtPmRiaTsNCj4gPiAtCXBwLT5yb290X2J1c19uciA9IC0x
Ow0KPiA+ICsJcHAtPnJvb3RfYnVzX25yID0gMDsNCj4gPiAgCXBwLT5vcHMgPSAmbHNfcGNpZV9o
b3N0X29wczsNCj4gPg0KPiA+ICAJcmV0ID0gZHdfcGNpZV9ob3N0X2luaXQocHApOw0KPiA+IGRp
ZmYgLS1naXQgYS9kcml2ZXJzL3BjaS9ob3N0L3BjaWUtZGVzaWdud2FyZS5jDQo+IGIvZHJpdmVy
cy9wY2kvaG9zdC9wY2llLWRlc2lnbndhcmUuYw0KPiA+IGluZGV4IGM1ZDQwN2MuLmU3MWE4OGUg
MTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9wY2kvaG9zdC9wY2llLWRlc2lnbndhcmUuYw0KPiA+
ICsrKyBiL2RyaXZlcnMvcGNpL2hvc3QvcGNpZS1kZXNpZ253YXJlLmMNCj4gPiBAQCAtMTEsNiAr
MTEsNyBAQA0KPiA+ICAgKiBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlv
bi4NCj4gPiAgICovDQo+ID4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L2hhcmRpcnEuaD4NCj4gPiAg
I2luY2x1ZGUgPGxpbnV4L2lycS5oPg0KPiA+ICAjaW5jbHVkZSA8bGludXgvaXJxZG9tYWluLmg+
DQo+ID4gICNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4NCj4gPiBAQCAtNjksMTYgKzcwLDcgQEAN
Cj4gPiAgI2RlZmluZSBQQ0lFX0FUVV9GVU5DKHgpCQkoKCh4KSAmIDB4NykgPDwgMTYpDQo+ID4g
ICNkZWZpbmUgUENJRV9BVFVfVVBQRVJfVEFSR0VUCQkweDkxQw0KPiA+DQo+ID4gLXN0YXRpYyBz
dHJ1Y3QgaHdfcGNpIGR3X3BjaTsNCj4gPiAtDQo+ID4gLXN0YXRpYyB1bnNpZ25lZCBsb25nIGds
b2JhbF9pb19vZmZzZXQ7DQo+ID4gLQ0KPiA+IC1zdGF0aWMgaW5saW5lIHN0cnVjdCBwY2llX3Bv
cnQgKnN5c190b19wY2llKHN0cnVjdCBwY2lfc3lzX2RhdGEgKnN5cykNCj4gPiAtew0KPiA+IC0J
QlVHX09OKCFzeXMtPnByaXZhdGVfZGF0YSk7DQo+ID4gLQ0KPiA+IC0JcmV0dXJuIHN5cy0+cHJp
dmF0ZV9kYXRhOw0KPiA+IC19DQo+ID4gK3N0YXRpYyBzdHJ1Y3QgcGNpX29wcyBkd19wY2llX29w
czsNCj4gPg0KPiA+ICBpbnQgZHdfcGNpZV9jZmdfcmVhZCh2b2lkIF9faW9tZW0gKmFkZHIsIGlu
dCB3aGVyZSwgaW50IHNpemUsIHUzMg0KPiAqdmFsKQ0KPiA+ICB7DQo+ID4gQEAgLTI1NSw3ICsy
NDcsNyBAQCBzdGF0aWMgdm9pZCBkd19wY2llX21zaV9zZXRfaXJxKHN0cnVjdCBwY2llX3BvcnQN
Cj4gKnBwLCBpbnQgaXJxKQ0KPiA+ICBzdGF0aWMgaW50IGFzc2lnbl9pcnEoaW50IG5vX2lycXMs
IHN0cnVjdCBtc2lfZGVzYyAqZGVzYywgaW50ICpwb3MpDQo+ID4gIHsNCj4gPiAgCWludCBpcnEs
IHBvczAsIGk7DQo+ID4gLQlzdHJ1Y3QgcGNpZV9wb3J0ICpwcCA9IHN5c190b19wY2llKGRlc2Mt
PmRldi0+YnVzLT5zeXNkYXRhKTsNCj4gPiArCXN0cnVjdCBwY2llX3BvcnQgKnBwID0gZGVzYy0+
ZGV2LT5idXMtPnN5c2RhdGE7DQo+ID4NCj4gPiAgCXBvczAgPSBiaXRtYXBfZmluZF9mcmVlX3Jl
Z2lvbihwcC0+bXNpX2lycV9pbl91c2UsIE1BWF9NU0lfSVJRUywNCj4gPiAgCQkJCSAgICAgICBv
cmRlcl9iYXNlXzIobm9faXJxcykpOw0KPiA+IEBAIC0yOTgsNyArMjkwLDcgQEAgc3RhdGljIGlu
dCBkd19tc2lfc2V0dXBfaXJxKHN0cnVjdCBtc2lfY29udHJvbGxlcg0KPiAqY2hpcCwgc3RydWN0
IHBjaV9kZXYgKnBkZXYsDQo+ID4gIHsNCj4gPiAgCWludCBpcnEsIHBvczsNCj4gPiAgCXN0cnVj
dCBtc2lfbXNnIG1zZzsNCj4gPiAtCXN0cnVjdCBwY2llX3BvcnQgKnBwID0gc3lzX3RvX3BjaWUo
cGRldi0+YnVzLT5zeXNkYXRhKTsNCj4gPiArCXN0cnVjdCBwY2llX3BvcnQgKnBwID0gcGRldi0+
YnVzLT5zeXNkYXRhOw0KPiA+DQo+ID4gIAlpZiAoZGVzYy0+bXNpX2F0dHJpYi5pc19tc2l4KQ0K
PiA+ICAJCXJldHVybiAtRUlOVkFMOw0KPiA+IEBAIC0zMjcsNyArMzE5LDcgQEAgc3RhdGljIHZv
aWQgZHdfbXNpX3RlYXJkb3duX2lycShzdHJ1Y3QNCj4gbXNpX2NvbnRyb2xsZXIgKmNoaXAsIHVu
c2lnbmVkIGludCBpcnEpDQo+ID4gIHsNCj4gPiAgCXN0cnVjdCBpcnFfZGF0YSAqZGF0YSA9IGly
cV9nZXRfaXJxX2RhdGEoaXJxKTsNCj4gPiAgCXN0cnVjdCBtc2lfZGVzYyAqbXNpID0gaXJxX2Rh
dGFfZ2V0X21zaShkYXRhKTsNCj4gPiAtCXN0cnVjdCBwY2llX3BvcnQgKnBwID0gc3lzX3RvX3Bj
aWUobXNpLT5kZXYtPmJ1cy0+c3lzZGF0YSk7DQo+ID4gKwlzdHJ1Y3QgcGNpZV9wb3J0ICpwcCA9
IG1zaS0+ZGV2LT5idXMtPnN5c2RhdGE7DQo+ID4NCj4gPiAgCWNsZWFyX2lycV9yYW5nZShwcCwg
aXJxLCAxLCBkYXRhLT5od2lycSk7DQo+ID4gIH0NCj4gPiBAQCAtMzYzLDE0ICszNTUsMTIgQEAg
aW50IGR3X3BjaWVfaG9zdF9pbml0KHN0cnVjdCBwY2llX3BvcnQgKnBwKQ0KPiA+ICB7DQo+ID4g
IAlzdHJ1Y3QgZGV2aWNlX25vZGUgKm5wID0gcHAtPmRldi0+b2Zfbm9kZTsNCj4gPiAgCXN0cnVj
dCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYgPSB0b19wbGF0Zm9ybV9kZXZpY2UocHAtPmRldik7DQo+
ID4gLQlzdHJ1Y3Qgb2ZfcGNpX3JhbmdlIHJhbmdlOw0KPiA+IC0Jc3RydWN0IG9mX3BjaV9yYW5n
ZV9wYXJzZXIgcGFyc2VyOw0KPiA+ICsJc3RydWN0IHBjaV9idXMgKmJ1czsNCj4gPiAgCXN0cnVj
dCByZXNvdXJjZSAqY2ZnX3JlczsNCj4gPiAtCXUzMiB2YWwsIG5zOw0KPiA+IC0JY29uc3QgX19i
ZTMyICphZGRycDsNCj4gPiAtCWludCBpLCBpbmRleCwgcmV0Ow0KPiA+IC0NCj4gPiAtCW5zID0g
b2Zfbl9zaXplX2NlbGxzKG5wKTsNCj4gPiArCUxJU1RfSEVBRChyZXMpOw0KPiA+ICsJdTMyIHZh
bDsNCj4gPiArCWludCBpLCByZXQ7DQo+ID4gKwlzdHJ1Y3QgcmVzb3VyY2VfZW50cnkgKndpbjsN
Cj4gPg0KPiA+ICAJY2ZnX3JlcyA9IHBsYXRmb3JtX2dldF9yZXNvdXJjZV9ieW5hbWUocGRldiwg
SU9SRVNPVVJDRV9NRU0sDQo+ICJjb25maWciKTsNCj4gPiAgCWlmIChjZmdfcmVzKSB7DQo+ID4g
QEAgLTM3OCw4NSArMzY4LDYwIEBAIGludCBkd19wY2llX2hvc3RfaW5pdChzdHJ1Y3QgcGNpZV9w
b3J0ICpwcCkNCj4gPiAgCQlwcC0+Y2ZnMV9zaXplID0gcmVzb3VyY2Vfc2l6ZShjZmdfcmVzKS8y
Ow0KPiA+ICAJCXBwLT5jZmcwX2Jhc2UgPSBjZmdfcmVzLT5zdGFydDsNCj4gPiAgCQlwcC0+Y2Zn
MV9iYXNlID0gY2ZnX3Jlcy0+c3RhcnQgKyBwcC0+Y2ZnMF9zaXplOw0KPiA+IC0NCj4gPiAtCQkv
KiBGaW5kIHRoZSB1bnRyYW5zbGF0ZWQgY29uZmlndXJhdGlvbiBzcGFjZSBhZGRyZXNzICovDQo+
ID4gLQkJaW5kZXggPSBvZl9wcm9wZXJ0eV9tYXRjaF9zdHJpbmcobnAsICJyZWctbmFtZXMiLCAi
Y29uZmlnIik7DQo+ID4gLQkJYWRkcnAgPSBvZl9nZXRfYWRkcmVzcyhucCwgaW5kZXgsIE5VTEws
IE5VTEwpOw0KPiA+IC0JCXBwLT5jZmcwX21vZF9iYXNlID0gb2ZfcmVhZF9udW1iZXIoYWRkcnAs
IG5zKTsNCj4gPiAtCQlwcC0+Y2ZnMV9tb2RfYmFzZSA9IHBwLT5jZmcwX21vZF9iYXNlICsgcHAt
PmNmZzBfc2l6ZTsNCj4gPiAgCX0gZWxzZSB7DQo+ID4gIAkJZGV2X2VycihwcC0+ZGV2LCAibWlz
c2luZyAqY29uZmlnKiByZWcgc3BhY2VcbiIpOw0KPiA+ICAJfQ0KPiA+DQo+ID4gLQlpZiAob2Zf
cGNpX3JhbmdlX3BhcnNlcl9pbml0KCZwYXJzZXIsIG5wKSkgew0KPiA+IC0JCWRldl9lcnIocHAt
PmRldiwgIm1pc3NpbmcgcmFuZ2VzIHByb3BlcnR5XG4iKTsNCj4gPiAtCQlyZXR1cm4gLUVJTlZB
TDsNCj4gPiAtCX0NCj4gPiArCXJldCA9IG9mX3BjaV9nZXRfaG9zdF9icmlkZ2VfcmVzb3VyY2Vz
KG5wLCAwLCAweGZmLCAmcmVzLCAmcHAtDQo+ID5pb19iYXNlKTsNCj4gPiArCWlmIChyZXQpDQo+
ID4gKwkJcmV0dXJuIHJldDsNCj4gPg0KPiA+ICAJLyogR2V0IHRoZSBJL08gYW5kIG1lbW9yeSBy
YW5nZXMgZnJvbSBEVCAqLw0KPiA+IC0JZm9yX2VhY2hfb2ZfcGNpX3JhbmdlKCZwYXJzZXIsICZy
YW5nZSkgew0KPiA+IC0JCXVuc2lnbmVkIGxvbmcgcmVzdHlwZSA9IHJhbmdlLmZsYWdzICYgSU9S
RVNPVVJDRV9UWVBFX0JJVFM7DQo+ID4gLQ0KPiA+IC0JCWlmIChyZXN0eXBlID09IElPUkVTT1VS
Q0VfSU8pIHsNCj4gPiAtCQkJb2ZfcGNpX3JhbmdlX3RvX3Jlc291cmNlKCZyYW5nZSwgbnAsICZw
cC0+aW8pOw0KPiA+IC0JCQlwcC0+aW8ubmFtZSA9ICJJL08iOw0KPiA+IC0JCQlwcC0+aW8uc3Rh
cnQgPSBtYXhfdChyZXNvdXJjZV9zaXplX3QsDQo+ID4gLQkJCQkJICAgICBQQ0lCSU9TX01JTl9J
TywNCj4gPiAtCQkJCQkgICAgIHJhbmdlLnBjaV9hZGRyICsgZ2xvYmFsX2lvX29mZnNldCk7DQo+
ID4gLQkJCXBwLT5pby5lbmQgPSBtaW5fdChyZXNvdXJjZV9zaXplX3QsDQo+ID4gLQkJCQkJICAg
SU9fU1BBQ0VfTElNSVQsDQo+ID4gLQkJCQkJICAgcmFuZ2UucGNpX2FkZHIgKyByYW5nZS5zaXpl
DQo+ID4gLQkJCQkJICAgKyBnbG9iYWxfaW9fb2Zmc2V0IC0gMSk7DQo+ID4gLQkJCXBwLT5pb19z
aXplID0gcmVzb3VyY2Vfc2l6ZSgmcHAtPmlvKTsNCj4gPiAtCQkJcHAtPmlvX2J1c19hZGRyID0g
cmFuZ2UucGNpX2FkZHI7DQo+ID4gLQkJCXBwLT5pb19iYXNlID0gcmFuZ2UuY3B1X2FkZHI7DQo+
ID4gLQ0KPiA+IC0JCQkvKiBGaW5kIHRoZSB1bnRyYW5zbGF0ZWQgSU8gc3BhY2UgYWRkcmVzcyAq
Lw0KPiA+IC0JCQlwcC0+aW9fbW9kX2Jhc2UgPSByYW5nZS5jcHVfYWRkcjsNCj4gPiAtCQl9DQo+
ID4gLQkJaWYgKHJlc3R5cGUgPT0gSU9SRVNPVVJDRV9NRU0pIHsNCj4gPiAtCQkJb2ZfcGNpX3Jh
bmdlX3RvX3Jlc291cmNlKCZyYW5nZSwgbnAsICZwcC0+bWVtKTsNCj4gPiAtCQkJcHAtPm1lbS5u
YW1lID0gIk1FTSI7DQo+ID4gLQkJCXBwLT5tZW1fc2l6ZSA9IHJlc291cmNlX3NpemUoJnBwLT5t
ZW0pOw0KPiA+IC0JCQlwcC0+bWVtX2J1c19hZGRyID0gcmFuZ2UucGNpX2FkZHI7DQo+ID4gLQ0K
PiA+IC0JCQkvKiBGaW5kIHRoZSB1bnRyYW5zbGF0ZWQgTUVNIHNwYWNlIGFkZHJlc3MgKi8NCj4g
PiAtCQkJcHAtPm1lbV9tb2RfYmFzZSA9IHJhbmdlLmNwdV9hZGRyOw0KPiA+IC0JCX0NCj4gPiAt
CQlpZiAocmVzdHlwZSA9PSAwKSB7DQo+ID4gLQkJCW9mX3BjaV9yYW5nZV90b19yZXNvdXJjZSgm
cmFuZ2UsIG5wLCAmcHAtPmNmZyk7DQo+ID4gLQkJCXBwLT5jZmcwX3NpemUgPSByZXNvdXJjZV9z
aXplKCZwcC0+Y2ZnKS8yOw0KPiA+IC0JCQlwcC0+Y2ZnMV9zaXplID0gcmVzb3VyY2Vfc2l6ZSgm
cHAtPmNmZykvMjsNCj4gPiAtCQkJcHAtPmNmZzBfYmFzZSA9IHBwLT5jZmcuc3RhcnQ7DQo+ID4g
LQkJCXBwLT5jZmcxX2Jhc2UgPSBwcC0+Y2ZnLnN0YXJ0ICsgcHAtPmNmZzBfc2l6ZTsNCj4gPiAt
DQo+ID4gLQkJCS8qIEZpbmQgdGhlIHVudHJhbnNsYXRlZCBjb25maWd1cmF0aW9uIHNwYWNlIGFk
ZHJlc3MNCj4gKi8NCj4gPiAtCQkJcHAtPmNmZzBfbW9kX2Jhc2UgPSByYW5nZS5jcHVfYWRkcjsN
Cj4gPiAtCQkJcHAtPmNmZzFfbW9kX2Jhc2UgPSBwcC0+Y2ZnMF9tb2RfYmFzZSArDQo+ID4gLQkJ
CQkJICAgIHBwLT5jZmcwX3NpemU7DQo+ID4gKwlyZXNvdXJjZV9saXN0X2Zvcl9lYWNoX2VudHJ5
KHdpbiwgJnJlcykgew0KPiA+ICsJCXN3aXRjaCAocmVzb3VyY2VfdHlwZSh3aW4tPnJlcykpIHsN
Cj4gPiArCQljYXNlIElPUkVTT1VSQ0VfSU86DQo+ID4gKwkJCXBwLT5pbyA9IHdpbi0+cmVzOw0K
PiA+ICsJCQlwcC0+aW8tPm5hbWUgPSAiSS9PIjsNCj4gPiArCQkJcHAtPmlvX3NpemUgPSByZXNv
dXJjZV9zaXplKHBwLT5pbyk7DQo+ID4gKwkJCXBwLT5pb19idXNfYWRkciA9IHBwLT5pby0+c3Rh
cnQgLSB3aW4tPm9mZnNldDsNCj4gPiArCQkJcmV0ID0gcGNpX3JlbWFwX2lvc3BhY2UocHAtPmlv
LCBwcC0+aW9fYmFzZSk7DQo+ID4gKwkJCWlmIChyZXQpIHsNCj4gPiArCQkJCWRldl93YXJuKHBw
LT5kZXYsICJlcnJvciAlZDogZmFpbGVkIHRvIG1hcA0KPiByZXNvdXJjZSAlcFJcbiIsDQo+ID4g
KwkJCQkJIHJldCwgcHAtPmlvKTsNCj4gPiArCQkJCWNvbnRpbnVlOw0KPiA+ICsJCQl9DQo+ID4g
KwkJCWJyZWFrOw0KPiA+ICsJCWNhc2UgSU9SRVNPVVJDRV9NRU06DQo+ID4gKwkJCXBwLT5tZW0g
PSB3aW4tPnJlczsNCj4gPiArCQkJcHAtPm1lbS0+bmFtZSA9ICJNRU0iOw0KPiA+ICsJCQlwcC0+
bWVtX3NpemUgPSByZXNvdXJjZV9zaXplKHBwLT5tZW0pOw0KPiA+ICsJCQlwcC0+bWVtX2J1c19h
ZGRyID0gcHAtPm1lbS0+c3RhcnQgLSB3aW4tPm9mZnNldDsNCj4gPiArCQkJYnJlYWs7DQo+ID4g
KwkJY2FzZSAwOg0KPiA+ICsJCQlwcC0+Y2ZnID0gd2luLT5yZXM7DQo+ID4gKwkJCXBwLT5jZmcw
X3NpemUgPSByZXNvdXJjZV9zaXplKHBwLT5jZmcpLzI7DQo+ID4gKwkJCXBwLT5jZmcxX3NpemUg
PSByZXNvdXJjZV9zaXplKHBwLT5jZmcpLzI7DQo+ID4gKwkJCXBwLT5jZmcwX2Jhc2UgPSBwcC0+
Y2ZnLT5zdGFydDsNCj4gPiArCQkJcHAtPmNmZzFfYmFzZSA9IHBwLT5jZmctPnN0YXJ0ICsgcHAt
PmNmZzBfc2l6ZTsNCj4gPiArCQkJYnJlYWs7DQo+ID4gKwkJY2FzZSBJT1JFU09VUkNFX0JVUzoN
Cj4gPiArCQkJcHAtPmJ1c24gPSB3aW4tPnJlczsNCj4gPiArCQkJYnJlYWs7DQo+ID4gKwkJZGVm
YXVsdDoNCj4gPiArCQkJY29udGludWU7DQo+ID4gIAkJfQ0KPiA+ICAJfQ0KPiA+DQo+ID4gLQly
ZXQgPSBvZl9wY2lfcGFyc2VfYnVzX3JhbmdlKG5wLCAmcHAtPmJ1c24pOw0KPiA+IC0JaWYgKHJl
dCA8IDApIHsNCj4gPiAtCQlwcC0+YnVzbi5uYW1lID0gbnAtPm5hbWU7DQo+ID4gLQkJcHAtPmJ1
c24uc3RhcnQgPSAwOw0KPiA+IC0JCXBwLT5idXNuLmVuZCA9IDB4ZmY7DQo+ID4gLQkJcHAtPmJ1
c24uZmxhZ3MgPSBJT1JFU09VUkNFX0JVUzsNCj4gPiAtCQlkZXZfZGJnKHBwLT5kZXYsICJmYWls
ZWQgdG8gcGFyc2UgYnVzLXJhbmdlIHByb3BlcnR5OiAlZCwNCj4gdXNpbmcgZGVmYXVsdCAlcFJc
biIsDQo+ID4gLQkJCXJldCwgJnBwLT5idXNuKTsNCj4gPiAtCX0NCj4gPiAtDQo+ID4gIAlpZiAo
IXBwLT5kYmlfYmFzZSkgew0KPiA+IC0JCXBwLT5kYmlfYmFzZSA9IGRldm1faW9yZW1hcChwcC0+
ZGV2LCBwcC0+Y2ZnLnN0YXJ0LA0KPiA+IC0JCQkJCXJlc291cmNlX3NpemUoJnBwLT5jZmcpKTsN
Cj4gPiArCQlwcC0+ZGJpX2Jhc2UgPSBkZXZtX2lvcmVtYXAocHAtPmRldiwgcHAtPmNmZy0+c3Rh
cnQsDQo+ID4gKwkJCQkJcmVzb3VyY2Vfc2l6ZShwcC0+Y2ZnKSk7DQo+ID4gIAkJaWYgKCFwcC0+
ZGJpX2Jhc2UpIHsNCj4gPiAgCQkJZGV2X2VycihwcC0+ZGV2LCAiZXJyb3Igd2l0aCBpb3JlbWFw
XG4iKTsNCj4gPiAgCQkJcmV0dXJuIC1FTk9NRU07DQo+ID4gIAkJfQ0KPiA+ICAJfQ0KPiA+DQo+
ID4gLQlwcC0+bWVtX2Jhc2UgPSBwcC0+bWVtLnN0YXJ0Ow0KPiA+ICsJcHAtPm1lbV9iYXNlID0g
cHAtPm1lbS0+c3RhcnQ7DQo+ID4NCj4gPiAgCWlmICghcHAtPnZhX2NmZzBfYmFzZSkgew0KPiA+
ICAJCXBwLT52YV9jZmcwX2Jhc2UgPSBkZXZtX2lvcmVtYXAocHAtPmRldiwgcHAtPmNmZzBfYmFz
ZSwNCj4gPiBAQCAtNTA1LDcgKzQ3MCw3IEBAIGludCBkd19wY2llX2hvc3RfaW5pdChzdHJ1Y3Qg
cGNpZV9wb3J0ICpwcCkNCj4gPg0KPiA+ICAJaWYgKCFwcC0+b3BzLT5yZF9vdGhlcl9jb25mKQ0K
PiA+ICAJCWR3X3BjaWVfcHJvZ19vdXRib3VuZF9hdHUocHAsIFBDSUVfQVRVX1JFR0lPTl9JTkRF
WDEsDQo+ID4gLQkJCQkJICBQQ0lFX0FUVV9UWVBFX01FTSwgcHAtPm1lbV9tb2RfYmFzZSwNCj4g
PiArCQkJCQkgIFBDSUVfQVRVX1RZUEVfTUVNLCBwcC0+bWVtX2Jhc2UsDQo+ID4gIAkJCQkJICBw
cC0+bWVtX2J1c19hZGRyLCBwcC0+bWVtX3NpemUpOw0KPiA+DQo+ID4gIAlkd19wY2llX3dyX293
bl9jb25mKHBwLCBQQ0lfQkFTRV9BRERSRVNTXzAsIDQsIDApOw0KPiA+IEBAIC01MTcsMTUgKzQ4
MiwyOSBAQCBpbnQgZHdfcGNpZV9ob3N0X2luaXQoc3RydWN0IHBjaWVfcG9ydCAqcHApDQo+ID4g
IAl2YWwgfD0gUE9SVF9MT0dJQ19TUEVFRF9DSEFOR0U7DQo+ID4gIAlkd19wY2llX3dyX293bl9j
b25mKHBwLCBQQ0lFX0xJTktfV0lEVEhfU1BFRURfQ09OVFJPTCwgNCwgdmFsKTsNCj4gPg0KPiA+
IC0jaWZkZWYgQ09ORklHX1BDSV9NU0kNCj4gPiArCWJ1cyA9IHBjaV9jcmVhdGVfcm9vdF9idXMo
cHAtPmRldiwgcHAtPnJvb3RfYnVzX25yLCAmZHdfcGNpZV9vcHMsDQo+ID4gKwkJCQkgIHBwLCAm
cmVzKTsNCj4gPiArCWlmICghYnVzKQ0KPiA+ICsJCXJldHVybiAtRU5PTUVNOw0KPiA+ICsNCj4g
PiArI2lmZGVmIENPTkZJR19HRU5FUklDX01TSV9JUlFfRE9NQUlODQo+ID4gKwlidXMtPm1zaSA9
IGNvbnRhaW5lcl9vZigmcHAtPmlycV9kb21haW4sIHN0cnVjdCBtc2lfY29udHJvbGxlciwNCj4g
ZG9tYWluKTsNCj4gPiArI2Vsc2UNCj4gPiAgCWR3X3BjaWVfbXNpX2NoaXAuZGV2ID0gcHAtPmRl
djsNCj4gPiAtCWR3X3BjaS5tc2lfY3RybCA9ICZkd19wY2llX21zaV9jaGlwOw0KPiA+ICsJYnVz
LT5tc2kgPSAmZHdfcGNpZV9tc2lfY2hpcDsNCj4gPiAgI2VuZGlmDQo+ID4NCj4gPiAtCWR3X3Bj
aS5ucl9jb250cm9sbGVycyA9IDE7DQo+ID4gLQlkd19wY2kucHJpdmF0ZV9kYXRhID0gKHZvaWQg
KiopJnBwOw0KPiA+ICsJcGNpX3NjYW5fY2hpbGRfYnVzKGJ1cyk7DQo+ID4gKwlpZiAocHAtPm9w
cy0+c2Nhbl9idXMpDQo+ID4gKwkJcHAtPm9wcy0+c2Nhbl9idXMocHApOw0KPiA+ICsNCj4gPiAr
I2lmZGVmIENPTkZJR19BUk0NCj4gPiArCS8qIHN1cHBvcnQgb2xkIGR0YnMgdGhhdCBpbmNvcnJl
Y3RseSBkZXNjcmliZSBJUlFzICovDQo+ID4gKwlwY2lfZml4dXBfaXJxcyhwY2lfY29tbW9uX3N3
aXp6bGUsIG9mX2lycV9wYXJzZV9hbmRfbWFwX3BjaSk7DQo+ID4gKyNlbmRpZg0KPiA+DQo+ID4g
LQlwY2lfY29tbW9uX2luaXRfZGV2KHBwLT5kZXYsICZkd19wY2kpOw0KPiA+ICsJcGNpX2Fzc2ln
bl91bmFzc2lnbmVkX2J1c19yZXNvdXJjZXMoYnVzKTsNCj4gPiArCXBjaV9idXNfYWRkX2Rldmlj
ZXMoYnVzKTsNCj4gPg0KPiA+ICAJcmV0dXJuIDA7DQo+ID4gIH0NCj4gPiBAQCAtNTQ0LDEyICs1
MjMsMTIgQEAgc3RhdGljIGludCBkd19wY2llX3JkX290aGVyX2NvbmYoc3RydWN0DQo+IHBjaWVf
cG9ydCAqcHAsIHN0cnVjdCBwY2lfYnVzICpidXMsDQo+ID4NCj4gPiAgCWlmIChidXMtPnBhcmVu
dC0+bnVtYmVyID09IHBwLT5yb290X2J1c19ucikgew0KPiA+ICAJCXR5cGUgPSBQQ0lFX0FUVV9U
WVBFX0NGRzA7DQo+ID4gLQkJY3B1X2FkZHIgPSBwcC0+Y2ZnMF9tb2RfYmFzZTsNCj4gPiArCQlj
cHVfYWRkciA9IHBwLT5jZmcwX2Jhc2U7DQo+ID4gIAkJY2ZnX3NpemUgPSBwcC0+Y2ZnMF9zaXpl
Ow0KPiA+ICAJCXZhX2NmZ19iYXNlID0gcHAtPnZhX2NmZzBfYmFzZTsNCj4gPiAgCX0gZWxzZSB7
DQo+ID4gIAkJdHlwZSA9IFBDSUVfQVRVX1RZUEVfQ0ZHMTsNCj4gPiAtCQljcHVfYWRkciA9IHBw
LT5jZmcxX21vZF9iYXNlOw0KPiA+ICsJCWNwdV9hZGRyID0gcHAtPmNmZzFfYmFzZTsNCj4gPiAg
CQljZmdfc2l6ZSA9IHBwLT5jZmcxX3NpemU7DQo+ID4gIAkJdmFfY2ZnX2Jhc2UgPSBwcC0+dmFf
Y2ZnMV9iYXNlOw0KPiA+ICAJfQ0KPiA+IEBAIC01NTksNyArNTM4LDcgQEAgc3RhdGljIGludCBk
d19wY2llX3JkX290aGVyX2NvbmYoc3RydWN0IHBjaWVfcG9ydA0KPiAqcHAsIHN0cnVjdCBwY2lf
YnVzICpidXMsDQo+ID4gIAkJCQkgIGJ1c2RldiwgY2ZnX3NpemUpOw0KPiA+ICAJcmV0ID0gZHdf
cGNpZV9jZmdfcmVhZCh2YV9jZmdfYmFzZSArIGFkZHJlc3MsIHdoZXJlLCBzaXplLCB2YWwpOw0K
PiA+ICAJZHdfcGNpZV9wcm9nX291dGJvdW5kX2F0dShwcCwgUENJRV9BVFVfUkVHSU9OX0lOREVY
MCwNCj4gPiAtCQkJCSAgUENJRV9BVFVfVFlQRV9JTywgcHAtPmlvX21vZF9iYXNlLA0KPiA+ICsJ
CQkJICBQQ0lFX0FUVV9UWVBFX0lPLCBwcC0+aW9fYmFzZSwNCj4gPiAgCQkJCSAgcHAtPmlvX2J1
c19hZGRyLCBwcC0+aW9fc2l6ZSk7DQo+ID4NCj4gPiAgCXJldHVybiByZXQ7DQo+ID4gQEAgLTU3
OSwxMiArNTU4LDEyIEBAIHN0YXRpYyBpbnQgZHdfcGNpZV93cl9vdGhlcl9jb25mKHN0cnVjdA0K
PiBwY2llX3BvcnQgKnBwLCBzdHJ1Y3QgcGNpX2J1cyAqYnVzLA0KPiA+DQo+ID4gIAlpZiAoYnVz
LT5wYXJlbnQtPm51bWJlciA9PSBwcC0+cm9vdF9idXNfbnIpIHsNCj4gPiAgCQl0eXBlID0gUENJ
RV9BVFVfVFlQRV9DRkcwOw0KPiA+IC0JCWNwdV9hZGRyID0gcHAtPmNmZzBfbW9kX2Jhc2U7DQo+
ID4gKwkJY3B1X2FkZHIgPSBwcC0+Y2ZnMF9iYXNlOw0KPiA+ICAJCWNmZ19zaXplID0gcHAtPmNm
ZzBfc2l6ZTsNCj4gPiAgCQl2YV9jZmdfYmFzZSA9IHBwLT52YV9jZmcwX2Jhc2U7DQo+ID4gIAl9
IGVsc2Ugew0KPiA+ICAJCXR5cGUgPSBQQ0lFX0FUVV9UWVBFX0NGRzE7DQo+ID4gLQkJY3B1X2Fk
ZHIgPSBwcC0+Y2ZnMV9tb2RfYmFzZTsNCj4gPiArCQljcHVfYWRkciA9IHBwLT5jZmcxX2Jhc2U7
DQo+ID4gIAkJY2ZnX3NpemUgPSBwcC0+Y2ZnMV9zaXplOw0KPiA+ICAJCXZhX2NmZ19iYXNlID0g
cHAtPnZhX2NmZzFfYmFzZTsNCj4gPiAgCX0NCj4gPiBAQCAtNTk0LDcgKzU3Myw3IEBAIHN0YXRp
YyBpbnQgZHdfcGNpZV93cl9vdGhlcl9jb25mKHN0cnVjdCBwY2llX3BvcnQNCj4gKnBwLCBzdHJ1
Y3QgcGNpX2J1cyAqYnVzLA0KPiA+ICAJCQkJICBidXNkZXYsIGNmZ19zaXplKTsNCj4gPiAgCXJl
dCA9IGR3X3BjaWVfY2ZnX3dyaXRlKHZhX2NmZ19iYXNlICsgYWRkcmVzcywgd2hlcmUsIHNpemUs
IHZhbCk7DQo+ID4gIAlkd19wY2llX3Byb2dfb3V0Ym91bmRfYXR1KHBwLCBQQ0lFX0FUVV9SRUdJ
T05fSU5ERVgwLA0KPiA+IC0JCQkJICBQQ0lFX0FUVV9UWVBFX0lPLCBwcC0+aW9fbW9kX2Jhc2Us
DQo+ID4gKwkJCQkgIFBDSUVfQVRVX1RZUEVfSU8sIHBwLT5pb19iYXNlLA0KPiA+ICAJCQkJICBw
cC0+aW9fYnVzX2FkZHIsIHBwLT5pb19zaXplKTsNCj4gPg0KPiA+ICAJcmV0dXJuIHJldDsNCj4g
PiBAQCAtNjI2LDcgKzYwNSw3IEBAIHN0YXRpYyBpbnQgZHdfcGNpZV92YWxpZF9jb25maWcoc3Ry
dWN0IHBjaWVfcG9ydA0KPiAqcHAsDQo+ID4gIHN0YXRpYyBpbnQgZHdfcGNpZV9yZF9jb25mKHN0
cnVjdCBwY2lfYnVzICpidXMsIHUzMiBkZXZmbiwgaW50IHdoZXJlLA0KPiA+ICAJCQlpbnQgc2l6
ZSwgdTMyICp2YWwpDQo+ID4gIHsNCj4gPiAtCXN0cnVjdCBwY2llX3BvcnQgKnBwID0gc3lzX3Rv
X3BjaWUoYnVzLT5zeXNkYXRhKTsNCj4gPiArCXN0cnVjdCBwY2llX3BvcnQgKnBwID0gYnVzLT5z
eXNkYXRhOw0KPiA+ICAJaW50IHJldDsNCj4gPg0KPiA+ICAJaWYgKGR3X3BjaWVfdmFsaWRfY29u
ZmlnKHBwLCBidXMsIFBDSV9TTE9UKGRldmZuKSkgPT0gMCkgew0KPiA+IEBAIC02NTAsNyArNjI5
LDcgQEAgc3RhdGljIGludCBkd19wY2llX3JkX2NvbmYoc3RydWN0IHBjaV9idXMgKmJ1cywNCj4g
dTMyIGRldmZuLCBpbnQgd2hlcmUsDQo+ID4gIHN0YXRpYyBpbnQgZHdfcGNpZV93cl9jb25mKHN0
cnVjdCBwY2lfYnVzICpidXMsIHUzMiBkZXZmbiwNCj4gPiAgCQkJaW50IHdoZXJlLCBpbnQgc2l6
ZSwgdTMyIHZhbCkNCj4gPiAgew0KPiA+IC0Jc3RydWN0IHBjaWVfcG9ydCAqcHAgPSBzeXNfdG9f
cGNpZShidXMtPnN5c2RhdGEpOw0KPiA+ICsJc3RydWN0IHBjaWVfcG9ydCAqcHAgPSBidXMtPnN5
c2RhdGE7DQo+ID4gIAlpbnQgcmV0Ow0KPiA+DQo+ID4gIAlpZiAoZHdfcGNpZV92YWxpZF9jb25m
aWcocHAsIGJ1cywgUENJX1NMT1QoZGV2Zm4pKSA9PSAwKQ0KPiA+IEBAIC02NzQsNjIgKzY1Myw2
IEBAIHN0YXRpYyBzdHJ1Y3QgcGNpX29wcyBkd19wY2llX29wcyA9IHsNCj4gPiAgCS53cml0ZSA9
IGR3X3BjaWVfd3JfY29uZiwNCj4gPiAgfTsNCj4gPg0KPiA+IC1zdGF0aWMgaW50IGR3X3BjaWVf
c2V0dXAoaW50IG5yLCBzdHJ1Y3QgcGNpX3N5c19kYXRhICpzeXMpDQo+ID4gLXsNCj4gPiAtCXN0
cnVjdCBwY2llX3BvcnQgKnBwOw0KPiA+IC0NCj4gPiAtCXBwID0gc3lzX3RvX3BjaWUoc3lzKTsN
Cj4gPiAtDQo+ID4gLQlpZiAoZ2xvYmFsX2lvX29mZnNldCA8IFNaXzFNICYmIHBwLT5pb19zaXpl
ID4gMCkgew0KPiA+IC0JCXN5cy0+aW9fb2Zmc2V0ID0gZ2xvYmFsX2lvX29mZnNldCAtIHBwLT5p
b19idXNfYWRkcjsNCj4gPiAtCQlwY2lfaW9yZW1hcF9pbyhnbG9iYWxfaW9fb2Zmc2V0LCBwcC0+
aW9fYmFzZSk7DQo+ID4gLQkJZ2xvYmFsX2lvX29mZnNldCArPSBTWl82NEs7DQo+ID4gLQkJcGNp
X2FkZF9yZXNvdXJjZV9vZmZzZXQoJnN5cy0+cmVzb3VyY2VzLCAmcHAtPmlvLA0KPiA+IC0JCQkJ
CXN5cy0+aW9fb2Zmc2V0KTsNCj4gPiAtCX0NCj4gPiAtDQo+ID4gLQlzeXMtPm1lbV9vZmZzZXQg
PSBwcC0+bWVtLnN0YXJ0IC0gcHAtPm1lbV9idXNfYWRkcjsNCj4gPiAtCXBjaV9hZGRfcmVzb3Vy
Y2Vfb2Zmc2V0KCZzeXMtPnJlc291cmNlcywgJnBwLT5tZW0sIHN5cy0NCj4gPm1lbV9vZmZzZXQp
Ow0KPiA+IC0JcGNpX2FkZF9yZXNvdXJjZSgmc3lzLT5yZXNvdXJjZXMsICZwcC0+YnVzbik7DQo+
ID4gLQ0KPiA+IC0JcmV0dXJuIDE7DQo+ID4gLX0NCj4gPiAtDQo+ID4gLXN0YXRpYyBzdHJ1Y3Qg
cGNpX2J1cyAqZHdfcGNpZV9zY2FuX2J1cyhpbnQgbnIsIHN0cnVjdCBwY2lfc3lzX2RhdGENCj4g
KnN5cykNCj4gPiAtew0KPiA+IC0Jc3RydWN0IHBjaV9idXMgKmJ1czsNCj4gPiAtCXN0cnVjdCBw
Y2llX3BvcnQgKnBwID0gc3lzX3RvX3BjaWUoc3lzKTsNCj4gPiAtDQo+ID4gLQlwcC0+cm9vdF9i
dXNfbnIgPSBzeXMtPmJ1c25yOw0KPiA+IC0JYnVzID0gcGNpX3NjYW5fcm9vdF9idXMocHAtPmRl
diwgc3lzLT5idXNuciwNCj4gPiAtCQkJCSAgJmR3X3BjaWVfb3BzLCBzeXMsICZzeXMtPnJlc291
cmNlcyk7DQo+ID4gLQlpZiAoIWJ1cykNCj4gPiAtCQlyZXR1cm4gTlVMTDsNCj4gPiAtDQo+ID4g
LQlpZiAoYnVzICYmIHBwLT5vcHMtPnNjYW5fYnVzKQ0KPiA+IC0JCXBwLT5vcHMtPnNjYW5fYnVz
KHBwKTsNCj4gPiAtDQo+ID4gLQlyZXR1cm4gYnVzOw0KPiA+IC19DQo+ID4gLQ0KPiA+IC1zdGF0
aWMgaW50IGR3X3BjaWVfbWFwX2lycShjb25zdCBzdHJ1Y3QgcGNpX2RldiAqZGV2LCB1OCBzbG90
LCB1OA0KPiBwaW4pDQo+ID4gLXsNCj4gPiAtCXN0cnVjdCBwY2llX3BvcnQgKnBwID0gc3lzX3Rv
X3BjaWUoZGV2LT5idXMtPnN5c2RhdGEpOw0KPiA+IC0JaW50IGlycTsNCj4gPiAtDQo+ID4gLQlp
cnEgPSBvZl9pcnFfcGFyc2VfYW5kX21hcF9wY2koZGV2LCBzbG90LCBwaW4pOw0KPiA+IC0JaWYg
KCFpcnEpDQo+ID4gLQkJaXJxID0gcHAtPmlycTsNCj4gPiAtDQo+ID4gLQlyZXR1cm4gaXJxOw0K
PiA+IC19DQo+ID4gLQ0KPiA+IC1zdGF0aWMgc3RydWN0IGh3X3BjaSBkd19wY2kgPSB7DQo+ID4g
LQkuc2V0dXAJCT0gZHdfcGNpZV9zZXR1cCwNCj4gPiAtCS5zY2FuCQk9IGR3X3BjaWVfc2Nhbl9i
dXMsDQo+ID4gLQkubWFwX2lycQk9IGR3X3BjaWVfbWFwX2lycSwNCj4gPiAtfTsNCj4gPiAtDQo+
ID4gIHZvaWQgZHdfcGNpZV9zZXR1cF9yYyhzdHJ1Y3QgcGNpZV9wb3J0ICpwcCkNCj4gPiAgew0K
PiA+ICAJdTMyIHZhbDsNCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9wY2kvaG9zdC9wY2llLWRl
c2lnbndhcmUuaA0KPiBiL2RyaXZlcnMvcGNpL2hvc3QvcGNpZS1kZXNpZ253YXJlLmgNCj4gPiBp
bmRleCBkMGJiZDI3Li4yNjRjOTY5IDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvcGNpL2hvc3Qv
cGNpZS1kZXNpZ253YXJlLmgNCj4gPiArKysgYi9kcml2ZXJzL3BjaS9ob3N0L3BjaWUtZGVzaWdu
d2FyZS5oDQo+ID4gQEAgLTI3LDI1ICsyNywyMSBAQCBzdHJ1Y3QgcGNpZV9wb3J0IHsNCj4gPiAg
CXU4CQkJcm9vdF9idXNfbnI7DQo+ID4gIAl2b2lkIF9faW9tZW0JCSpkYmlfYmFzZTsNCj4gPiAg
CXU2NAkJCWNmZzBfYmFzZTsNCj4gPiAtCXU2NAkJCWNmZzBfbW9kX2Jhc2U7DQo+ID4gIAl2b2lk
IF9faW9tZW0JCSp2YV9jZmcwX2Jhc2U7DQo+ID4gIAl1MzIJCQljZmcwX3NpemU7DQo+ID4gIAl1
NjQJCQljZmcxX2Jhc2U7DQo+ID4gLQl1NjQJCQljZmcxX21vZF9iYXNlOw0KPiA+ICAJdm9pZCBf
X2lvbWVtCQkqdmFfY2ZnMV9iYXNlOw0KPiA+ICAJdTMyCQkJY2ZnMV9zaXplOw0KPiA+IC0JdTY0
CQkJaW9fYmFzZTsNCj4gPiAtCXU2NAkJCWlvX21vZF9iYXNlOw0KPiA+ICsJcmVzb3VyY2Vfc2l6
ZV90CQlpb19iYXNlOw0KPiA+ICAJcGh5c19hZGRyX3QJCWlvX2J1c19hZGRyOw0KPiA+ICAJdTMy
CQkJaW9fc2l6ZTsNCj4gPiAgCXU2NAkJCW1lbV9iYXNlOw0KPiA+IC0JdTY0CQkJbWVtX21vZF9i
YXNlOw0KPiA+ICAJcGh5c19hZGRyX3QJCW1lbV9idXNfYWRkcjsNCj4gPiAgCXUzMgkJCW1lbV9z
aXplOw0KPiA+IC0Jc3RydWN0IHJlc291cmNlCQljZmc7DQo+ID4gLQlzdHJ1Y3QgcmVzb3VyY2UJ
CWlvOw0KPiA+IC0Jc3RydWN0IHJlc291cmNlCQltZW07DQo+ID4gLQlzdHJ1Y3QgcmVzb3VyY2UJ
CWJ1c247DQo+ID4gKwlzdHJ1Y3QgcmVzb3VyY2UJCSpjZmc7DQo+ID4gKwlzdHJ1Y3QgcmVzb3Vy
Y2UJCSppbzsNCj4gPiArCXN0cnVjdCByZXNvdXJjZQkJKm1lbTsNCj4gPiArCXN0cnVjdCByZXNv
dXJjZQkJKmJ1c247DQo+ID4gIAlpbnQJCQlpcnE7DQo+ID4gIAl1MzIJCQlsYW5lczsNCj4gPiAg
CXN0cnVjdCBwY2llX2hvc3Rfb3BzCSpvcHM7DQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvcGNp
L2hvc3QvcGNpZS1zcGVhcjEzeHguYw0KPiBiL2RyaXZlcnMvcGNpL2hvc3QvcGNpZS1zcGVhcjEz
eHguYw0KPiA+IGluZGV4IGM0OWZiZGMuLjAzZWIyMDQgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVy
cy9wY2kvaG9zdC9wY2llLXNwZWFyMTN4eC5jDQo+ID4gKysrIGIvZHJpdmVycy9wY2kvaG9zdC9w
Y2llLXNwZWFyMTN4eC5jDQo+ID4gQEAgLTI4Niw3ICsyODYsNyBAQCBzdGF0aWMgaW50IHNwZWFy
MTN4eF9hZGRfcGNpZV9wb3J0KHN0cnVjdA0KPiBwY2llX3BvcnQgKnBwLA0KPiA+ICAJCXJldHVy
biByZXQ7DQo+ID4gIAl9DQo+ID4NCj4gPiAtCXBwLT5yb290X2J1c19uciA9IC0xOw0KPiA+ICsJ
cHAtPnJvb3RfYnVzX25yID0gMDsNCj4gPiAgCXBwLT5vcHMgPSAmc3BlYXIxM3h4X3BjaWVfaG9z
dF9vcHM7DQo+ID4NCj4gPiAgCXJldCA9IGR3X3BjaWVfaG9zdF9pbml0KHBwKTsNCj4gDQo+IC0t
DQo+IFBlbmd1dHJvbml4IGUuSy4gICAgICAgICAgICAgfCBMdWNhcyBTdGFjaCAgICAgICAgICAg
ICAgICAgfA0KPiBJbmR1c3RyaWFsIExpbnV4IFNvbHV0aW9ucyAgIHwgaHR0cDovL3d3dy5wZW5n
dXRyb25peC5kZS8gIHwNCg0K

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

* [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-19 15:16       ` Gabriele Paoloni
  0 siblings, 0 replies; 53+ messages in thread
From: Gabriele Paoloni @ 2015-08-19 15:16 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Lucas

I have rewritten the patch to take into account multiple controllers.

As you can see now there is a static var in dw_pcie_host_init() that tracks
the bus numbers used.
Drivers that do not specify the bus range in the DTB set pp->root_bus_nr = DW_ROOT_NR_UNDEFINED.
Designware will check if the flag is set and will use the automatic bus range
assignment.
Instead if the driver assigns pp->root_bus_nr according to the dtb, designwware
will use the value passed in by the driver.
Below the relevant section:


+	static int root_bus_nr = 0;
...
+	mutex_lock(&root_bus_nr_mux);
+
+	if (pp->root_bus_nr != DW_ROOT_NR_UNDEFINED)
+		root_bus_nr = pp->root_bus_nr;
+
+	bus = pci_create_root_bus(pp->dev, root_bus_nr, &dw_pcie_ops,
+			      pp, &res);
+	if (!bus) {
+		mutex_unlock(&root_bus_nr_mux);
+		return -ENOMEM;
+	}
+
+	root_bus_nr += bus->busn_res.end + 1;
+	mutex_unlock(&root_bus_nr_mux);

Please let me know what you think...

Many Thanks

Gab
----------

From: gabriele paoloni <gabriele.paoloni@huawei.com>

This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete
function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci,
move related operations to dw_pcie_host_init.
Also set pp->root_bus_nr = DW_ROOT_NR_UNDEFINED in all the drivers that
are based on designware to flag that the drivers do not read the bus
ranges from DT.
This patch also adds handling of multiple PCI domains in designware.
if the PCI host bridge driver does not specify a root bus number, in case
of multiple domains, designware will automatillay set the next domain root
bus number to the last bus number used in the last domain + 1.

This patch also try to use of_pci_get_host_bridge_resources for ARM32 and
ARM64 according to the suggestion for Gabriele[1]

This patch is based on Gabriele's patch about of_pci_range fix[2]

Finally this patch reverts commit f4c55c5a3f7f "PCI: designware:
Program ATU with untranslated address". This was discussed in [3]

I have compiled the driver with multi_v7_defconfig. However, I don't have
ARM32 PCIe related board to do test. It will be appreciated if someone could
help to test it.

Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>

[1] http://www.spinics.net/lists/linux-pci/msg42194.html
[2] https://patchwork.ozlabs.org/patch/495018/
[3] http://www.spinics.net/lists/arm-kernel/msg436779.html
---
 drivers/pci/host/pci-dra7xx.c      |  15 +--
 drivers/pci/host/pci-exynos.c      |   2 +-
 drivers/pci/host/pci-imx6.c        |   2 +-
 drivers/pci/host/pci-keystone-dw.c |   2 +-
 drivers/pci/host/pci-keystone.c    |   2 +-
 drivers/pci/host/pci-layerscape.c  |   2 +-
 drivers/pci/host/pcie-designware.c | 247 ++++++++++++++-----------------------
 drivers/pci/host/pcie-designware.h |  15 +--
 drivers/pci/host/pcie-spear13xx.c  |   2 +-
 9 files changed, 110 insertions(+), 179 deletions(-)

diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
index 5678b57..8d598fb 100644
--- a/drivers/pci/host/pci-dra7xx.c
+++ b/drivers/pci/host/pci-dra7xx.c
@@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp)
 {
 	dw_pcie_setup_rc(pp);
 
-	if (pp->io_mod_base)
-		pp->io_mod_base &= CPU_TO_BUS_ADDR;
+	if (pp->io_base)
+		pp->io_base &= CPU_TO_BUS_ADDR;
 
-	if (pp->mem_mod_base)
-		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
+	if (pp->mem_base)
+		pp->mem_base &= CPU_TO_BUS_ADDR;
 
-	if (pp->cfg0_mod_base) {
-		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
-		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
+	if (pp->cfg0_base) {
+		pp->cfg0_base &= CPU_TO_BUS_ADDR;
+		pp->cfg1_base &= CPU_TO_BUS_ADDR;
 	}
 
 	dra7xx_pcie_establish_link(pp);
@@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
 
 	pp = &dra7xx->pp;
 	pp->dev = dev;
+	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
 	pp->ops = &dra7xx_pcie_host_ops;
 
 	pp->irq = platform_get_irq(pdev, 1);
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
index f9f468d..ed03a8f 100644
--- a/drivers/pci/host/pci-exynos.c
+++ b/drivers/pci/host/pci-exynos.c
@@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
 	pp->ops = &exynos_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index 233a196..0efac85 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
 		}
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
 	pp->ops = &imx6_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c
index f34892e..b1e4135 100644
--- a/drivers/pci/host/pci-keystone-dw.c
+++ b/drivers/pci/host/pci-keystone-dw.c
@@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void __iomem *reg_virt)
 void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
 {
 	struct pcie_port *pp = &ks_pcie->pp;
-	u32 start = pp->mem.start, end = pp->mem.end;
+	u32 start = pp->mem->start, end = pp->mem->end;
 	int i, tr_size;
 
 	/* Disable BARs for inbound access */
diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
index 734da58..b522956 100644
--- a/drivers/pci/host/pci-keystone.c
+++ b/drivers/pci/host/pci-keystone.c
@@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
 			return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
 	pp->ops = &keystone_pcie_host_ops;
 	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
 	if (ret) {
diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
index b2328ea1..dd92ffa 100644
--- a/drivers/pci/host/pci-layerscape.c
+++ b/drivers/pci/host/pci-layerscape.c
@@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
 	pp = &pcie->pp;
 	pp->dev = pcie->dev;
 	pp->dbi_base = pcie->dbi;
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
 	pp->ops = &ls_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 5307b35..bd2606b 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/hardirq.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
@@ -69,16 +70,9 @@
 #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
 #define PCIE_ATU_UPPER_TARGET		0x91C
 
-static struct hw_pci dw_pci;
+static struct pci_ops dw_pcie_ops;
 
-static unsigned long global_io_offset;
-
-static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
-{
-	BUG_ON(!sys->private_data);
-
-	return sys->private_data;
-}
+DEFINE_MUTEX(root_bus_nr_mux);
 
 int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
 {
@@ -255,7 +249,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
 static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
 {
 	int irq, pos0, i;
-	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
+	struct pcie_port *pp = desc->dev->bus->sysdata;
 
 	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
 				       order_base_2(no_irqs));
@@ -298,7 +292,7 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
 {
 	int irq, pos;
 	struct msi_msg msg;
-	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
+	struct pcie_port *pp = pdev->bus->sysdata;
 
 	if (desc->msi_attrib.is_msix)
 		return -EINVAL;
@@ -327,7 +321,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
 {
 	struct irq_data *data = irq_get_irq_data(irq);
 	struct msi_desc *msi = irq_data_get_msi(data);
-	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
+	struct pcie_port *pp = msi->dev->bus->sysdata;
 
 	clear_irq_range(pp, irq, 1, data->hwirq);
 }
@@ -359,22 +353,17 @@ static const struct irq_domain_ops msi_domain_ops = {
 	.map = dw_pcie_msi_map,
 };
 
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
 {
 	struct device_node *np = pp->dev->of_node;
 	struct platform_device *pdev = to_platform_device(pp->dev);
-	struct of_pci_range range;
-	struct of_pci_range_parser parser;
+	struct pci_bus *bus;
 	struct resource *cfg_res;
-	u32 val, na, ns;
-	const __be32 *addrp;
-	int i, index, ret;
-
-	/* Find the address cell size and the number of cells in order to get
-	 * the untranslated address.
-	 */
-	of_property_read_u32(np, "#address-cells", &na);
-	ns = of_n_size_cells(np);
+	LIST_HEAD(res);
+	u32 val;
+	int i, ret;
+	struct resource_entry *win;
+	static int root_bus_nr = 0;
 
 	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
 	if (cfg_res) {
@@ -382,85 +371,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
 		pp->cfg1_size = resource_size(cfg_res)/2;
 		pp->cfg0_base = cfg_res->start;
 		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
-
-		/* Find the untranslated configuration space address */
-		index = of_property_match_string(np, "reg-names", "config");
-		addrp = of_get_address(np, index, NULL, NULL);
-		pp->cfg0_mod_base = of_read_number(addrp, ns);
-		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
 	} else {
 		dev_err(pp->dev, "missing *config* reg space\n");
 	}
 
-	if (of_pci_range_parser_init(&parser, np)) {
-		dev_err(pp->dev, "missing ranges property\n");
-		return -EINVAL;
-	}
+	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
+	if (ret)
+		return ret;
 
 	/* Get the I/O and memory ranges from DT */
-	for_each_of_pci_range(&parser, &range) {
-		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
-
-		if (restype == IORESOURCE_IO) {
-			of_pci_range_to_resource(&range, np, &pp->io);
-			pp->io.name = "I/O";
-			pp->io.start = max_t(resource_size_t,
-					     PCIBIOS_MIN_IO,
-					     range.pci_addr + global_io_offset);
-			pp->io.end = min_t(resource_size_t,
-					   IO_SPACE_LIMIT,
-					   range.pci_addr + range.size
-					   + global_io_offset - 1);
-			pp->io_size = resource_size(&pp->io);
-			pp->io_bus_addr = range.pci_addr;
-			pp->io_base = range.cpu_addr;
-
-			/* Find the untranslated IO space address */
-			pp->io_mod_base = range.cpu_addr;
-		}
-		if (restype == IORESOURCE_MEM) {
-			of_pci_range_to_resource(&range, np, &pp->mem);
-			pp->mem.name = "MEM";
-			pp->mem_size = resource_size(&pp->mem);
-			pp->mem_bus_addr = range.pci_addr;
-
-			/* Find the untranslated MEM space address */
-			pp->mem_mod_base = range.cpu_addr;
-		}
-		if (restype == 0) {
-			of_pci_range_to_resource(&range, np, &pp->cfg);
-			pp->cfg0_size = resource_size(&pp->cfg)/2;
-			pp->cfg1_size = resource_size(&pp->cfg)/2;
-			pp->cfg0_base = pp->cfg.start;
-			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
-
-			/* Find the untranslated configuration space address */
-			pp->cfg0_mod_base = range.cpu_addr;
-			pp->cfg1_mod_base = pp->cfg0_mod_base +
-					    pp->cfg0_size;
+	resource_list_for_each_entry(win, &res) {
+		switch (resource_type(win->res)) {
+		case IORESOURCE_IO:
+			pp->io = win->res;
+			pp->io->name = "I/O";
+			pp->io_size = resource_size(pp->io);
+			pp->io_bus_addr = pp->io->start - win->offset;
+			ret = pci_remap_iospace(pp->io, pp->io_base);
+			if (ret) {
+				dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
+					 ret, pp->io);
+				continue;
+			}
+			break;
+		case IORESOURCE_MEM:
+			pp->mem = win->res;
+			pp->mem->name = "MEM";
+			pp->mem_size = resource_size(pp->mem);
+			pp->mem_bus_addr = pp->mem->start - win->offset;
+			break;
+		case 0:
+			pp->cfg = win->res;
+			pp->cfg0_size = resource_size(pp->cfg)/2;
+			pp->cfg1_size = resource_size(pp->cfg)/2;
+			pp->cfg0_base = pp->cfg->start;
+			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
+			break;
+		case IORESOURCE_BUS:
+			pp->busn = win->res;
+			break;
+		default:
+			continue;
 		}
 	}
 
-	ret = of_pci_parse_bus_range(np, &pp->busn);
-	if (ret < 0) {
-		pp->busn.name = np->name;
-		pp->busn.start = 0;
-		pp->busn.end = 0xff;
-		pp->busn.flags = IORESOURCE_BUS;
-		dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n",
-			ret, &pp->busn);
-	}
-
 	if (!pp->dbi_base) {
-		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
-					resource_size(&pp->cfg));
+		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
+					resource_size(pp->cfg));
 		if (!pp->dbi_base) {
 			dev_err(pp->dev, "error with ioremap\n");
 			return -ENOMEM;
 		}
 	}
 
-	pp->mem_base = pp->mem.start;
+	pp->mem_base = pp->mem->start;
 
 	if (!pp->va_cfg0_base) {
 		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
@@ -509,7 +473,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
 
 	if (!pp->ops->rd_other_conf)
 		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
-					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
+					  PCIE_ATU_TYPE_MEM, pp->mem_base,
 					  pp->mem_bus_addr, pp->mem_size);
 
 	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
@@ -521,15 +485,40 @@ int dw_pcie_host_init(struct pcie_port *pp)
 	val |= PORT_LOGIC_SPEED_CHANGE;
 	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
-#ifdef CONFIG_PCI_MSI
 	dw_pcie_msi_chip.dev = pp->dev;
-	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+
+	mutex_lock(&root_bus_nr_mux);
+
+	if (pp->root_bus_nr != DW_ROOT_NR_UNDEFINED)
+		root_bus_nr = pp->root_bus_nr;
+
+	bus = pci_create_root_bus(pp->dev, root_bus_nr, &dw_pcie_ops,
+			      pp, &res);
+	if (!bus) {
+		mutex_unlock(&root_bus_nr_mux);
+		return -ENOMEM;
+	}
+
+	root_bus_nr += bus->busn_res.end + 1;
+	mutex_unlock(&root_bus_nr_mux);
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
+#else
+	bus->msi = &dw_pcie_msi_chip;
 #endif
 
-	dw_pci.nr_controllers = 1;
-	dw_pci.private_data = (void **)&pp;
+	pci_scan_child_bus(bus);
+	if (pp->ops->scan_bus)
+		pp->ops->scan_bus(pp);
+
+#ifdef CONFIG_ARM
+	/* support old dtbs that incorrectly describe IRQs */
+	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
 
-	pci_common_init_dev(pp->dev, &dw_pci);
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
 
 	return 0;
 }
@@ -548,12 +537,12 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 
 	if (bus->parent->number == pp->root_bus_nr) {
 		type = PCIE_ATU_TYPE_CFG0;
-		cpu_addr = pp->cfg0_mod_base;
+		cpu_addr = pp->cfg0_base;
 		cfg_size = pp->cfg0_size;
 		va_cfg_base = pp->va_cfg0_base;
 	} else {
 		type = PCIE_ATU_TYPE_CFG1;
-		cpu_addr = pp->cfg1_mod_base;
+		cpu_addr = pp->cfg1_base;
 		cfg_size = pp->cfg1_size;
 		va_cfg_base = pp->va_cfg1_base;
 	}
@@ -563,7 +552,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 				  busdev, cfg_size);
 	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
 	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
-				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
+				  PCIE_ATU_TYPE_IO, pp->io_base,
 				  pp->io_bus_addr, pp->io_size);
 
 	return ret;
@@ -583,12 +572,12 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 
 	if (bus->parent->number == pp->root_bus_nr) {
 		type = PCIE_ATU_TYPE_CFG0;
-		cpu_addr = pp->cfg0_mod_base;
+		cpu_addr = pp->cfg0_base;
 		cfg_size = pp->cfg0_size;
 		va_cfg_base = pp->va_cfg0_base;
 	} else {
 		type = PCIE_ATU_TYPE_CFG1;
-		cpu_addr = pp->cfg1_mod_base;
+		cpu_addr = pp->cfg1_base;
 		cfg_size = pp->cfg1_size;
 		va_cfg_base = pp->va_cfg1_base;
 	}
@@ -598,7 +587,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 				  busdev, cfg_size);
 	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
 	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
-				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
+				  PCIE_ATU_TYPE_IO, pp->io_base,
 				  pp->io_bus_addr, pp->io_size);
 
 	return ret;
@@ -630,7 +619,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
 static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 			int size, u32 *val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
@@ -654,7 +643,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 			int where, int size, u32 val)
 {
-	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+	struct pcie_port *pp = bus->sysdata;
 	int ret;
 
 	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
@@ -678,62 +667,6 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
 
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
-{
-	struct pcie_port *pp;
-
-	pp = sys_to_pcie(sys);
-
-	if (global_io_offset < SZ_1M && pp->io_size > 0) {
-		sys->io_offset = global_io_offset - pp->io_bus_addr;
-		pci_ioremap_io(global_io_offset, pp->io_base);
-		global_io_offset += SZ_64K;
-		pci_add_resource_offset(&sys->resources, &pp->io,
-					sys->io_offset);
-	}
-
-	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
-	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
-	pci_add_resource(&sys->resources, &pp->busn);
-
-	return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
-{
-	struct pci_bus *bus;
-	struct pcie_port *pp = sys_to_pcie(sys);
-
-	pp->root_bus_nr = sys->busnr;
-	bus = pci_scan_root_bus(pp->dev, sys->busnr,
-				  &dw_pcie_ops, sys, &sys->resources);
-	if (!bus)
-		return NULL;
-
-	if (bus && pp->ops->scan_bus)
-		pp->ops->scan_bus(pp);
-
-	return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
-	int irq;
-
-	irq = of_irq_parse_and_map_pci(dev, slot, pin);
-	if (!irq)
-		irq = pp->irq;
-
-	return irq;
-}
-
-static struct hw_pci dw_pci = {
-	.setup		= dw_pcie_setup,
-	.scan		= dw_pcie_scan_bus,
-	.map_irq	= dw_pcie_map_irq,
-};
-
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
 	u32 val;
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
index d0bbd27..0c2a7eb 100644
--- a/drivers/pci/host/pcie-designware.h
+++ b/drivers/pci/host/pcie-designware.h
@@ -21,31 +21,28 @@
  */
 #define MAX_MSI_IRQS			32
 #define MAX_MSI_CTRLS			(MAX_MSI_IRQS / 32)
+#define DW_ROOT_NR_UNDEFINED	-1
 
 struct pcie_port {
 	struct device		*dev;
 	u8			root_bus_nr;
 	void __iomem		*dbi_base;
 	u64			cfg0_base;
-	u64			cfg0_mod_base;
 	void __iomem		*va_cfg0_base;
 	u32			cfg0_size;
 	u64			cfg1_base;
-	u64			cfg1_mod_base;
 	void __iomem		*va_cfg1_base;
 	u32			cfg1_size;
-	u64			io_base;
-	u64			io_mod_base;
+	resource_size_t		io_base;
 	phys_addr_t		io_bus_addr;
 	u32			io_size;
 	u64			mem_base;
-	u64			mem_mod_base;
 	phys_addr_t		mem_bus_addr;
 	u32			mem_size;
-	struct resource		cfg;
-	struct resource		io;
-	struct resource		mem;
-	struct resource		busn;
+	struct resource		*cfg;
+	struct resource		*io;
+	struct resource		*mem;
+	struct resource		*busn;
 	int			irq;
 	u32			lanes;
 	struct pcie_host_ops	*ops;
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
index c49fbdc..b2c59b9 100644
--- a/drivers/pci/host/pcie-spear13xx.c
+++ b/drivers/pci/host/pcie-spear13xx.c
@@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
 		return ret;
 	}
 
-	pp->root_bus_nr = -1;
+	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
 	pp->ops = &spear13xx_pcie_host_ops;
 
 	ret = dw_pcie_host_init(pp);
-- 
1.9.1


> -----Original Message-----
> From: Lucas Stach [mailto:l.stach at pengutronix.de]
> Sent: Wednesday, August 19, 2015 1:54 PM
> To: Wangzhou (B)
> Cc: Bjorn Helgaas; jingoohan1 at gmail.com; Pratyush Anand; Arnd Bergmann;
> linux at arm.linux.org.uk; thomas.petazzoni at free-electrons.com; Gabriele
> Paoloni; lorenzo.pieralisi at arm.com; james.morse at arm.com;
> Liviu.Dudau at arm.com; jason at lakedaemon.net; robh at kernel.org; linux-
> pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> 
> Am Montag, den 17.08.2015, 19:55 +0800 schrieb Zhou Wang:
> > This patch tries to unify ARM32 and ARM64 PCIe in designware driver.
> Delete
> > function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct
> hw_pci,
> > move related operations to dw_pcie_host_init.
> >
> > In past, we use:
> > pci_common_init_dev
> > 	-> pcibios_init_hw
> > 		-> hw->scan (dw_pcie_scan_bus)
> > to pass 0 to root_bus_nr in struct pcie_port. This patch set pp-
> >root_bus_nr = 0
> > in each PCIe host driver which is based on pcie-designware.
> >
> This is incorrect at least if there are 2 instances of DW PCIe host in
> the same SoC without using PCI domains. In that the case the bus range
> determines the range of valid bus numbers per instance and the first
> number is the root bus. Please look at the "bus-range" DT property in
> the DW PCIe bindings.
> 
> Also we should finally remove this root-bus setup from the glue drivers
> altogether. It's something that entirely belongs into the DW core code.
> 
> Regards,
> Lucas
> 
> > This patch also try to use of_pci_get_host_bridge_resources for ARM32
> and ARM64
> > according to the suggestion for Gabriele[1]
> >
> > Finally this patch reverts commit f4c55c5a3f7f "PCI: designware:
> Program ATU
> > with untranslated address" based on 1/6 in this series. we delete
> *_mod_base in
> > pcie-designware. This was discussed in [2]
> >
> > I have compiled the driver with multi_v7_defconfig. However, I don't
> have
> > ARM32 PCIe related board to do test. It will be appreciated if
> someone could
> > help to test it.
> >
> > Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> > Tested-By: James Morse <james.morse@arm.com>
> >
> > [1] http://www.spinics.net/lists/linux-pci/msg42194.html
> > [2] http://www.spinics.net/lists/arm-kernel/msg436779.html
> > ---
> >  drivers/pci/host/pci-dra7xx.c      |  15 +--
> >  drivers/pci/host/pci-exynos.c      |   2 +-
> >  drivers/pci/host/pci-imx6.c        |   2 +-
> >  drivers/pci/host/pci-keystone-dw.c |   2 +-
> >  drivers/pci/host/pci-keystone.c    |   2 +-
> >  drivers/pci/host/pci-layerscape.c  |   2 +-
> >  drivers/pci/host/pcie-designware.c | 229 ++++++++++++---------------
> ----------
> >  drivers/pci/host/pcie-designware.h |  14 +--
> >  drivers/pci/host/pcie-spear13xx.c  |   2 +-
> >  9 files changed, 95 insertions(+), 175 deletions(-)
> >
> > diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-
> dra7xx.c
> > index 18ae7ff..1268c69 100644
> > --- a/drivers/pci/host/pci-dra7xx.c
> > +++ b/drivers/pci/host/pci-dra7xx.c
> > @@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct
> pcie_port *pp)
> >  {
> >  	dw_pcie_setup_rc(pp);
> >
> > -	if (pp->io_mod_base)
> > -		pp->io_mod_base &= CPU_TO_BUS_ADDR;
> > +	if (pp->io_base)
> > +		pp->io_base &= CPU_TO_BUS_ADDR;
> >
> > -	if (pp->mem_mod_base)
> > -		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
> > +	if (pp->mem_base)
> > +		pp->mem_base &= CPU_TO_BUS_ADDR;
> >
> > -	if (pp->cfg0_mod_base) {
> > -		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
> > -		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
> > +	if (pp->cfg0_base) {
> > +		pp->cfg0_base &= CPU_TO_BUS_ADDR;
> > +		pp->cfg1_base &= CPU_TO_BUS_ADDR;
> >  	}
> >
> >  	dra7xx_pcie_establish_link(pp);
> > @@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct
> dra7xx_pcie *dra7xx,
> >
> >  	pp = &dra7xx->pp;
> >  	pp->dev = dev;
> > +	pp->root_bus_nr = 0;
> >  	pp->ops = &dra7xx_pcie_host_ops;
> >
> >  	pp->irq = platform_get_irq(pdev, 1);
> > diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-
> exynos.c
> > index f9f468d..9771bb0 100644
> > --- a/drivers/pci/host/pci-exynos.c
> > +++ b/drivers/pci/host/pci-exynos.c
> > @@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct
> pcie_port *pp,
> >  		}
> >  	}
> >
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = 0;
> >  	pp->ops = &exynos_pcie_host_ops;
> >
> >  	ret = dw_pcie_host_init(pp);
> > diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-
> imx6.c
> > index 233a196..bec256c 100644
> > --- a/drivers/pci/host/pci-imx6.c
> > +++ b/drivers/pci/host/pci-imx6.c
> > @@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct
> pcie_port *pp,
> >  		}
> >  	}
> >
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = 0;
> >  	pp->ops = &imx6_pcie_host_ops;
> >
> >  	ret = dw_pcie_host_init(pp);
> > diff --git a/drivers/pci/host/pci-keystone-dw.c
> b/drivers/pci/host/pci-keystone-dw.c
> > index f34892e..b1e4135 100644
> > --- a/drivers/pci/host/pci-keystone-dw.c
> > +++ b/drivers/pci/host/pci-keystone-dw.c
> > @@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void
> __iomem *reg_virt)
> >  void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
> >  {
> >  	struct pcie_port *pp = &ks_pcie->pp;
> > -	u32 start = pp->mem.start, end = pp->mem.end;
> > +	u32 start = pp->mem->start, end = pp->mem->end;
> >  	int i, tr_size;
> >
> >  	/* Disable BARs for inbound access */
> > diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-
> keystone.c
> > index 734da58..8113832 100644
> > --- a/drivers/pci/host/pci-keystone.c
> > +++ b/drivers/pci/host/pci-keystone.c
> > @@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct
> keystone_pcie *ks_pcie,
> >  			return ret;
> >  	}
> >
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = 0;
> >  	pp->ops = &keystone_pcie_host_ops;
> >  	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
> >  	if (ret) {
> > diff --git a/drivers/pci/host/pci-layerscape.c
> b/drivers/pci/host/pci-layerscape.c
> > index b2328ea1..79ff08c 100644
> > --- a/drivers/pci/host/pci-layerscape.c
> > +++ b/drivers/pci/host/pci-layerscape.c
> > @@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
> >  	pp = &pcie->pp;
> >  	pp->dev = pcie->dev;
> >  	pp->dbi_base = pcie->dbi;
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = 0;
> >  	pp->ops = &ls_pcie_host_ops;
> >
> >  	ret = dw_pcie_host_init(pp);
> > diff --git a/drivers/pci/host/pcie-designware.c
> b/drivers/pci/host/pcie-designware.c
> > index c5d407c..e71a88e 100644
> > --- a/drivers/pci/host/pcie-designware.c
> > +++ b/drivers/pci/host/pcie-designware.c
> > @@ -11,6 +11,7 @@
> >   * published by the Free Software Foundation.
> >   */
> >
> > +#include <linux/hardirq.h>
> >  #include <linux/irq.h>
> >  #include <linux/irqdomain.h>
> >  #include <linux/kernel.h>
> > @@ -69,16 +70,7 @@
> >  #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
> >  #define PCIE_ATU_UPPER_TARGET		0x91C
> >
> > -static struct hw_pci dw_pci;
> > -
> > -static unsigned long global_io_offset;
> > -
> > -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
> > -{
> > -	BUG_ON(!sys->private_data);
> > -
> > -	return sys->private_data;
> > -}
> > +static struct pci_ops dw_pcie_ops;
> >
> >  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32
> *val)
> >  {
> > @@ -255,7 +247,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port
> *pp, int irq)
> >  static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
> >  {
> >  	int irq, pos0, i;
> > -	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
> > +	struct pcie_port *pp = desc->dev->bus->sysdata;
> >
> >  	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
> >  				       order_base_2(no_irqs));
> > @@ -298,7 +290,7 @@ static int dw_msi_setup_irq(struct msi_controller
> *chip, struct pci_dev *pdev,
> >  {
> >  	int irq, pos;
> >  	struct msi_msg msg;
> > -	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
> > +	struct pcie_port *pp = pdev->bus->sysdata;
> >
> >  	if (desc->msi_attrib.is_msix)
> >  		return -EINVAL;
> > @@ -327,7 +319,7 @@ static void dw_msi_teardown_irq(struct
> msi_controller *chip, unsigned int irq)
> >  {
> >  	struct irq_data *data = irq_get_irq_data(irq);
> >  	struct msi_desc *msi = irq_data_get_msi(data);
> > -	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
> > +	struct pcie_port *pp = msi->dev->bus->sysdata;
> >
> >  	clear_irq_range(pp, irq, 1, data->hwirq);
> >  }
> > @@ -363,14 +355,12 @@ int dw_pcie_host_init(struct pcie_port *pp)
> >  {
> >  	struct device_node *np = pp->dev->of_node;
> >  	struct platform_device *pdev = to_platform_device(pp->dev);
> > -	struct of_pci_range range;
> > -	struct of_pci_range_parser parser;
> > +	struct pci_bus *bus;
> >  	struct resource *cfg_res;
> > -	u32 val, ns;
> > -	const __be32 *addrp;
> > -	int i, index, ret;
> > -
> > -	ns = of_n_size_cells(np);
> > +	LIST_HEAD(res);
> > +	u32 val;
> > +	int i, ret;
> > +	struct resource_entry *win;
> >
> >  	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> "config");
> >  	if (cfg_res) {
> > @@ -378,85 +368,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
> >  		pp->cfg1_size = resource_size(cfg_res)/2;
> >  		pp->cfg0_base = cfg_res->start;
> >  		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
> > -
> > -		/* Find the untranslated configuration space address */
> > -		index = of_property_match_string(np, "reg-names", "config");
> > -		addrp = of_get_address(np, index, NULL, NULL);
> > -		pp->cfg0_mod_base = of_read_number(addrp, ns);
> > -		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
> >  	} else {
> >  		dev_err(pp->dev, "missing *config* reg space\n");
> >  	}
> >
> > -	if (of_pci_range_parser_init(&parser, np)) {
> > -		dev_err(pp->dev, "missing ranges property\n");
> > -		return -EINVAL;
> > -	}
> > +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp-
> >io_base);
> > +	if (ret)
> > +		return ret;
> >
> >  	/* Get the I/O and memory ranges from DT */
> > -	for_each_of_pci_range(&parser, &range) {
> > -		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
> > -
> > -		if (restype == IORESOURCE_IO) {
> > -			of_pci_range_to_resource(&range, np, &pp->io);
> > -			pp->io.name = "I/O";
> > -			pp->io.start = max_t(resource_size_t,
> > -					     PCIBIOS_MIN_IO,
> > -					     range.pci_addr + global_io_offset);
> > -			pp->io.end = min_t(resource_size_t,
> > -					   IO_SPACE_LIMIT,
> > -					   range.pci_addr + range.size
> > -					   + global_io_offset - 1);
> > -			pp->io_size = resource_size(&pp->io);
> > -			pp->io_bus_addr = range.pci_addr;
> > -			pp->io_base = range.cpu_addr;
> > -
> > -			/* Find the untranslated IO space address */
> > -			pp->io_mod_base = range.cpu_addr;
> > -		}
> > -		if (restype == IORESOURCE_MEM) {
> > -			of_pci_range_to_resource(&range, np, &pp->mem);
> > -			pp->mem.name = "MEM";
> > -			pp->mem_size = resource_size(&pp->mem);
> > -			pp->mem_bus_addr = range.pci_addr;
> > -
> > -			/* Find the untranslated MEM space address */
> > -			pp->mem_mod_base = range.cpu_addr;
> > -		}
> > -		if (restype == 0) {
> > -			of_pci_range_to_resource(&range, np, &pp->cfg);
> > -			pp->cfg0_size = resource_size(&pp->cfg)/2;
> > -			pp->cfg1_size = resource_size(&pp->cfg)/2;
> > -			pp->cfg0_base = pp->cfg.start;
> > -			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
> > -
> > -			/* Find the untranslated configuration space address
> */
> > -			pp->cfg0_mod_base = range.cpu_addr;
> > -			pp->cfg1_mod_base = pp->cfg0_mod_base +
> > -					    pp->cfg0_size;
> > +	resource_list_for_each_entry(win, &res) {
> > +		switch (resource_type(win->res)) {
> > +		case IORESOURCE_IO:
> > +			pp->io = win->res;
> > +			pp->io->name = "I/O";
> > +			pp->io_size = resource_size(pp->io);
> > +			pp->io_bus_addr = pp->io->start - win->offset;
> > +			ret = pci_remap_iospace(pp->io, pp->io_base);
> > +			if (ret) {
> > +				dev_warn(pp->dev, "error %d: failed to map
> resource %pR\n",
> > +					 ret, pp->io);
> > +				continue;
> > +			}
> > +			break;
> > +		case IORESOURCE_MEM:
> > +			pp->mem = win->res;
> > +			pp->mem->name = "MEM";
> > +			pp->mem_size = resource_size(pp->mem);
> > +			pp->mem_bus_addr = pp->mem->start - win->offset;
> > +			break;
> > +		case 0:
> > +			pp->cfg = win->res;
> > +			pp->cfg0_size = resource_size(pp->cfg)/2;
> > +			pp->cfg1_size = resource_size(pp->cfg)/2;
> > +			pp->cfg0_base = pp->cfg->start;
> > +			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
> > +			break;
> > +		case IORESOURCE_BUS:
> > +			pp->busn = win->res;
> > +			break;
> > +		default:
> > +			continue;
> >  		}
> >  	}
> >
> > -	ret = of_pci_parse_bus_range(np, &pp->busn);
> > -	if (ret < 0) {
> > -		pp->busn.name = np->name;
> > -		pp->busn.start = 0;
> > -		pp->busn.end = 0xff;
> > -		pp->busn.flags = IORESOURCE_BUS;
> > -		dev_dbg(pp->dev, "failed to parse bus-range property: %d,
> using default %pR\n",
> > -			ret, &pp->busn);
> > -	}
> > -
> >  	if (!pp->dbi_base) {
> > -		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
> > -					resource_size(&pp->cfg));
> > +		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
> > +					resource_size(pp->cfg));
> >  		if (!pp->dbi_base) {
> >  			dev_err(pp->dev, "error with ioremap\n");
> >  			return -ENOMEM;
> >  		}
> >  	}
> >
> > -	pp->mem_base = pp->mem.start;
> > +	pp->mem_base = pp->mem->start;
> >
> >  	if (!pp->va_cfg0_base) {
> >  		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
> > @@ -505,7 +470,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
> >
> >  	if (!pp->ops->rd_other_conf)
> >  		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
> > -					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
> > +					  PCIE_ATU_TYPE_MEM, pp->mem_base,
> >  					  pp->mem_bus_addr, pp->mem_size);
> >
> >  	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
> > @@ -517,15 +482,29 @@ int dw_pcie_host_init(struct pcie_port *pp)
> >  	val |= PORT_LOGIC_SPEED_CHANGE;
> >  	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
> >
> > -#ifdef CONFIG_PCI_MSI
> > +	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
> > +				  pp, &res);
> > +	if (!bus)
> > +		return -ENOMEM;
> > +
> > +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> > +	bus->msi = container_of(&pp->irq_domain, struct msi_controller,
> domain);
> > +#else
> >  	dw_pcie_msi_chip.dev = pp->dev;
> > -	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> > +	bus->msi = &dw_pcie_msi_chip;
> >  #endif
> >
> > -	dw_pci.nr_controllers = 1;
> > -	dw_pci.private_data = (void **)&pp;
> > +	pci_scan_child_bus(bus);
> > +	if (pp->ops->scan_bus)
> > +		pp->ops->scan_bus(pp);
> > +
> > +#ifdef CONFIG_ARM
> > +	/* support old dtbs that incorrectly describe IRQs */
> > +	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
> > +#endif
> >
> > -	pci_common_init_dev(pp->dev, &dw_pci);
> > +	pci_assign_unassigned_bus_resources(bus);
> > +	pci_bus_add_devices(bus);
> >
> >  	return 0;
> >  }
> > @@ -544,12 +523,12 @@ static int dw_pcie_rd_other_conf(struct
> pcie_port *pp, struct pci_bus *bus,
> >
> >  	if (bus->parent->number == pp->root_bus_nr) {
> >  		type = PCIE_ATU_TYPE_CFG0;
> > -		cpu_addr = pp->cfg0_mod_base;
> > +		cpu_addr = pp->cfg0_base;
> >  		cfg_size = pp->cfg0_size;
> >  		va_cfg_base = pp->va_cfg0_base;
> >  	} else {
> >  		type = PCIE_ATU_TYPE_CFG1;
> > -		cpu_addr = pp->cfg1_mod_base;
> > +		cpu_addr = pp->cfg1_base;
> >  		cfg_size = pp->cfg1_size;
> >  		va_cfg_base = pp->va_cfg1_base;
> >  	}
> > @@ -559,7 +538,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port
> *pp, struct pci_bus *bus,
> >  				  busdev, cfg_size);
> >  	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
> >  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> > -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> > +				  PCIE_ATU_TYPE_IO, pp->io_base,
> >  				  pp->io_bus_addr, pp->io_size);
> >
> >  	return ret;
> > @@ -579,12 +558,12 @@ static int dw_pcie_wr_other_conf(struct
> pcie_port *pp, struct pci_bus *bus,
> >
> >  	if (bus->parent->number == pp->root_bus_nr) {
> >  		type = PCIE_ATU_TYPE_CFG0;
> > -		cpu_addr = pp->cfg0_mod_base;
> > +		cpu_addr = pp->cfg0_base;
> >  		cfg_size = pp->cfg0_size;
> >  		va_cfg_base = pp->va_cfg0_base;
> >  	} else {
> >  		type = PCIE_ATU_TYPE_CFG1;
> > -		cpu_addr = pp->cfg1_mod_base;
> > +		cpu_addr = pp->cfg1_base;
> >  		cfg_size = pp->cfg1_size;
> >  		va_cfg_base = pp->va_cfg1_base;
> >  	}
> > @@ -594,7 +573,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port
> *pp, struct pci_bus *bus,
> >  				  busdev, cfg_size);
> >  	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
> >  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> > -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> > +				  PCIE_ATU_TYPE_IO, pp->io_base,
> >  				  pp->io_bus_addr, pp->io_size);
> >
> >  	return ret;
> > @@ -626,7 +605,7 @@ static int dw_pcie_valid_config(struct pcie_port
> *pp,
> >  static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> >  			int size, u32 *val)
> >  {
> > -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> > +	struct pcie_port *pp = bus->sysdata;
> >  	int ret;
> >
> >  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
> > @@ -650,7 +629,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus,
> u32 devfn, int where,
> >  static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
> >  			int where, int size, u32 val)
> >  {
> > -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> > +	struct pcie_port *pp = bus->sysdata;
> >  	int ret;
> >
> >  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
> > @@ -674,62 +653,6 @@ static struct pci_ops dw_pcie_ops = {
> >  	.write = dw_pcie_wr_conf,
> >  };
> >
> > -static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
> > -{
> > -	struct pcie_port *pp;
> > -
> > -	pp = sys_to_pcie(sys);
> > -
> > -	if (global_io_offset < SZ_1M && pp->io_size > 0) {
> > -		sys->io_offset = global_io_offset - pp->io_bus_addr;
> > -		pci_ioremap_io(global_io_offset, pp->io_base);
> > -		global_io_offset += SZ_64K;
> > -		pci_add_resource_offset(&sys->resources, &pp->io,
> > -					sys->io_offset);
> > -	}
> > -
> > -	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
> > -	pci_add_resource_offset(&sys->resources, &pp->mem, sys-
> >mem_offset);
> > -	pci_add_resource(&sys->resources, &pp->busn);
> > -
> > -	return 1;
> > -}
> > -
> > -static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data
> *sys)
> > -{
> > -	struct pci_bus *bus;
> > -	struct pcie_port *pp = sys_to_pcie(sys);
> > -
> > -	pp->root_bus_nr = sys->busnr;
> > -	bus = pci_scan_root_bus(pp->dev, sys->busnr,
> > -				  &dw_pcie_ops, sys, &sys->resources);
> > -	if (!bus)
> > -		return NULL;
> > -
> > -	if (bus && pp->ops->scan_bus)
> > -		pp->ops->scan_bus(pp);
> > -
> > -	return bus;
> > -}
> > -
> > -static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8
> pin)
> > -{
> > -	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
> > -	int irq;
> > -
> > -	irq = of_irq_parse_and_map_pci(dev, slot, pin);
> > -	if (!irq)
> > -		irq = pp->irq;
> > -
> > -	return irq;
> > -}
> > -
> > -static struct hw_pci dw_pci = {
> > -	.setup		= dw_pcie_setup,
> > -	.scan		= dw_pcie_scan_bus,
> > -	.map_irq	= dw_pcie_map_irq,
> > -};
> > -
> >  void dw_pcie_setup_rc(struct pcie_port *pp)
> >  {
> >  	u32 val;
> > diff --git a/drivers/pci/host/pcie-designware.h
> b/drivers/pci/host/pcie-designware.h
> > index d0bbd27..264c969 100644
> > --- a/drivers/pci/host/pcie-designware.h
> > +++ b/drivers/pci/host/pcie-designware.h
> > @@ -27,25 +27,21 @@ struct pcie_port {
> >  	u8			root_bus_nr;
> >  	void __iomem		*dbi_base;
> >  	u64			cfg0_base;
> > -	u64			cfg0_mod_base;
> >  	void __iomem		*va_cfg0_base;
> >  	u32			cfg0_size;
> >  	u64			cfg1_base;
> > -	u64			cfg1_mod_base;
> >  	void __iomem		*va_cfg1_base;
> >  	u32			cfg1_size;
> > -	u64			io_base;
> > -	u64			io_mod_base;
> > +	resource_size_t		io_base;
> >  	phys_addr_t		io_bus_addr;
> >  	u32			io_size;
> >  	u64			mem_base;
> > -	u64			mem_mod_base;
> >  	phys_addr_t		mem_bus_addr;
> >  	u32			mem_size;
> > -	struct resource		cfg;
> > -	struct resource		io;
> > -	struct resource		mem;
> > -	struct resource		busn;
> > +	struct resource		*cfg;
> > +	struct resource		*io;
> > +	struct resource		*mem;
> > +	struct resource		*busn;
> >  	int			irq;
> >  	u32			lanes;
> >  	struct pcie_host_ops	*ops;
> > diff --git a/drivers/pci/host/pcie-spear13xx.c
> b/drivers/pci/host/pcie-spear13xx.c
> > index c49fbdc..03eb204 100644
> > --- a/drivers/pci/host/pcie-spear13xx.c
> > +++ b/drivers/pci/host/pcie-spear13xx.c
> > @@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct
> pcie_port *pp,
> >  		return ret;
> >  	}
> >
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = 0;
> >  	pp->ops = &spear13xx_pcie_host_ops;
> >
> >  	ret = dw_pcie_host_init(pp);
> 
> --
> Pengutronix e.K.             | Lucas Stach                 |
> Industrial Linux Solutions   | http://www.pengutronix.de/  |

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

* Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
  2015-08-19 15:16       ` Gabriele Paoloni
  (?)
@ 2015-08-19 15:37         ` Lucas Stach
  -1 siblings, 0 replies; 53+ messages in thread
From: Lucas Stach @ 2015-08-19 15:37 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Wangzhou (B),
	Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, lorenzo.pieralisi, james.morse, Liviu.Dudau,
	jason, robh, linux-pci, linux-arm-kernel, devicetree,
	Yuanzhichang, Zhudacai, zhangjukuo, qiuzhe

Hi Gab,

Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele Paoloni:
> Hi Lucas
> 
> I have rewritten the patch to take into account multiple controllers.
> 
> As you can see now there is a static var in dw_pcie_host_init() that tracks
> the bus numbers used.

This is wrong. The DT specifies the valid bus number range. You can not
just assign the next free bus number to the root bus.

It is perfectly valid to have a bus range of 0x00-0x10 assigned to one
instance and 0x50-0xff to the next instance. Additional with PCIe
hotplug you may not use the full range of the bus numbers on one
instance at the first scan, but only later populate more buses when more
bridges are added to the tree.

> Drivers that do not specify the bus range in the DTB set pp->root_bus_nr = DW_ROOT_NR_UNDEFINED.
> Designware will check if the flag is set and will use the automatic bus range
> assignment.

No, please lets get rid of this assignment altogether. The glue drivers
have no business in assigning the bus range. Please remove the
pp->root_bus_nr assignment from all the glue drivers.

"bus range" is a generic DW PCIe property, so just parse the root bus
number from the DT, it is handled the same way for all the DW based PCIe
drivers. The bindings specifies that if the bus range property is
missing the range is 0x00-0xff, so you can default to 0 as the root bus
number in that case.

Also I would think this conversion warrants a patch on its own and
should not be mixed in the ARM64 support patch.

Regards,
Lucas

> Instead if the driver assigns pp->root_bus_nr according to the dtb, designwware
> will use the value passed in by the driver.
> Below the relevant section:
> 
> 
> +	static int root_bus_nr = 0;
> ...
> +	mutex_lock(&root_bus_nr_mux);
> +
> +	if (pp->root_bus_nr != DW_ROOT_NR_UNDEFINED)
> +		root_bus_nr = pp->root_bus_nr;
> +
> +	bus = pci_create_root_bus(pp->dev, root_bus_nr, &dw_pcie_ops,
> +			      pp, &res);
> +	if (!bus) {
> +		mutex_unlock(&root_bus_nr_mux);
> +		return -ENOMEM;
> +	}
> +
> +	root_bus_nr += bus->busn_res.end + 1;
> +	mutex_unlock(&root_bus_nr_mux);
> 
> Please let me know what you think...
> 
> Many Thanks
> 
> Gab
> ----------
> 
> From: gabriele paoloni <gabriele.paoloni@huawei.com>
> 
> This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete
> function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci,
> move related operations to dw_pcie_host_init.
> Also set pp->root_bus_nr = DW_ROOT_NR_UNDEFINED in all the drivers that
> are based on designware to flag that the drivers do not read the bus
> ranges from DT.
> This patch also adds handling of multiple PCI domains in designware.
> if the PCI host bridge driver does not specify a root bus number, in case
> of multiple domains, designware will automatillay set the next domain root
> bus number to the last bus number used in the last domain + 1.
> 
> This patch also try to use of_pci_get_host_bridge_resources for ARM32 and
> ARM64 according to the suggestion for Gabriele[1]
> 
> This patch is based on Gabriele's patch about of_pci_range fix[2]
> 
> Finally this patch reverts commit f4c55c5a3f7f "PCI: designware:
> Program ATU with untranslated address". This was discussed in [3]
> 
> I have compiled the driver with multi_v7_defconfig. However, I don't have
> ARM32 PCIe related board to do test. It will be appreciated if someone could
> help to test it.
> 
> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> 
> [1] http://www.spinics.net/lists/linux-pci/msg42194.html
> [2] https://patchwork.ozlabs.org/patch/495018/
> [3] http://www.spinics.net/lists/arm-kernel/msg436779.html
> ---
>  drivers/pci/host/pci-dra7xx.c      |  15 +--
>  drivers/pci/host/pci-exynos.c      |   2 +-
>  drivers/pci/host/pci-imx6.c        |   2 +-
>  drivers/pci/host/pci-keystone-dw.c |   2 +-
>  drivers/pci/host/pci-keystone.c    |   2 +-
>  drivers/pci/host/pci-layerscape.c  |   2 +-
>  drivers/pci/host/pcie-designware.c | 247 ++++++++++++++-----------------------
>  drivers/pci/host/pcie-designware.h |  15 +--
>  drivers/pci/host/pcie-spear13xx.c  |   2 +-
>  9 files changed, 110 insertions(+), 179 deletions(-)
> 
> diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
> index 5678b57..8d598fb 100644
> --- a/drivers/pci/host/pci-dra7xx.c
> +++ b/drivers/pci/host/pci-dra7xx.c
> @@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp)
>  {
>  	dw_pcie_setup_rc(pp);
>  
> -	if (pp->io_mod_base)
> -		pp->io_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->io_base)
> +		pp->io_base &= CPU_TO_BUS_ADDR;
>  
> -	if (pp->mem_mod_base)
> -		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->mem_base)
> +		pp->mem_base &= CPU_TO_BUS_ADDR;
>  
> -	if (pp->cfg0_mod_base) {
> -		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
> -		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->cfg0_base) {
> +		pp->cfg0_base &= CPU_TO_BUS_ADDR;
> +		pp->cfg1_base &= CPU_TO_BUS_ADDR;
>  	}
>  
>  	dra7xx_pcie_establish_link(pp);
> @@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
>  
>  	pp = &dra7xx->pp;
>  	pp->dev = dev;
> +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
>  	pp->ops = &dra7xx_pcie_host_ops;
>  
>  	pp->irq = platform_get_irq(pdev, 1);
> diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
> index f9f468d..ed03a8f 100644
> --- a/drivers/pci/host/pci-exynos.c
> +++ b/drivers/pci/host/pci-exynos.c
> @@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
>  		}
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
>  	pp->ops = &exynos_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
> index 233a196..0efac85 100644
> --- a/drivers/pci/host/pci-imx6.c
> +++ b/drivers/pci/host/pci-imx6.c
> @@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
>  		}
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
>  	pp->ops = &imx6_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c
> index f34892e..b1e4135 100644
> --- a/drivers/pci/host/pci-keystone-dw.c
> +++ b/drivers/pci/host/pci-keystone-dw.c
> @@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void __iomem *reg_virt)
>  void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
>  {
>  	struct pcie_port *pp = &ks_pcie->pp;
> -	u32 start = pp->mem.start, end = pp->mem.end;
> +	u32 start = pp->mem->start, end = pp->mem->end;
>  	int i, tr_size;
>  
>  	/* Disable BARs for inbound access */
> diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
> index 734da58..b522956 100644
> --- a/drivers/pci/host/pci-keystone.c
> +++ b/drivers/pci/host/pci-keystone.c
> @@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
>  			return ret;
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
>  	pp->ops = &keystone_pcie_host_ops;
>  	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
>  	if (ret) {
> diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
> index b2328ea1..dd92ffa 100644
> --- a/drivers/pci/host/pci-layerscape.c
> +++ b/drivers/pci/host/pci-layerscape.c
> @@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
>  	pp = &pcie->pp;
>  	pp->dev = pcie->dev;
>  	pp->dbi_base = pcie->dbi;
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
>  	pp->ops = &ls_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
> index 5307b35..bd2606b 100644
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c
> @@ -11,6 +11,7 @@
>   * published by the Free Software Foundation.
>   */
>  
> +#include <linux/hardirq.h>
>  #include <linux/irq.h>
>  #include <linux/irqdomain.h>
>  #include <linux/kernel.h>
> @@ -69,16 +70,9 @@
>  #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
>  #define PCIE_ATU_UPPER_TARGET		0x91C
>  
> -static struct hw_pci dw_pci;
> +static struct pci_ops dw_pcie_ops;
>  
> -static unsigned long global_io_offset;
> -
> -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
> -{
> -	BUG_ON(!sys->private_data);
> -
> -	return sys->private_data;
> -}
> +DEFINE_MUTEX(root_bus_nr_mux);
>  
>  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
>  {
> @@ -255,7 +249,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
>  static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
>  {
>  	int irq, pos0, i;
> -	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
> +	struct pcie_port *pp = desc->dev->bus->sysdata;
>  
>  	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
>  				       order_base_2(no_irqs));
> @@ -298,7 +292,7 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
>  {
>  	int irq, pos;
>  	struct msi_msg msg;
> -	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
> +	struct pcie_port *pp = pdev->bus->sysdata;
>  
>  	if (desc->msi_attrib.is_msix)
>  		return -EINVAL;
> @@ -327,7 +321,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
>  {
>  	struct irq_data *data = irq_get_irq_data(irq);
>  	struct msi_desc *msi = irq_data_get_msi(data);
> -	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
> +	struct pcie_port *pp = msi->dev->bus->sysdata;
>  
>  	clear_irq_range(pp, irq, 1, data->hwirq);
>  }
> @@ -359,22 +353,17 @@ static const struct irq_domain_ops msi_domain_ops = {
>  	.map = dw_pcie_msi_map,
>  };
>  
> -int dw_pcie_host_init(struct pcie_port *pp)
> +int __init dw_pcie_host_init(struct pcie_port *pp)
>  {
>  	struct device_node *np = pp->dev->of_node;
>  	struct platform_device *pdev = to_platform_device(pp->dev);
> -	struct of_pci_range range;
> -	struct of_pci_range_parser parser;
> +	struct pci_bus *bus;
>  	struct resource *cfg_res;
> -	u32 val, na, ns;
> -	const __be32 *addrp;
> -	int i, index, ret;
> -
> -	/* Find the address cell size and the number of cells in order to get
> -	 * the untranslated address.
> -	 */
> -	of_property_read_u32(np, "#address-cells", &na);
> -	ns = of_n_size_cells(np);
> +	LIST_HEAD(res);
> +	u32 val;
> +	int i, ret;
> +	struct resource_entry *win;
> +	static int root_bus_nr = 0;
>  
>  	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
>  	if (cfg_res) {
> @@ -382,85 +371,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  		pp->cfg1_size = resource_size(cfg_res)/2;
>  		pp->cfg0_base = cfg_res->start;
>  		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
> -
> -		/* Find the untranslated configuration space address */
> -		index = of_property_match_string(np, "reg-names", "config");
> -		addrp = of_get_address(np, index, NULL, NULL);
> -		pp->cfg0_mod_base = of_read_number(addrp, ns);
> -		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
>  	} else {
>  		dev_err(pp->dev, "missing *config* reg space\n");
>  	}
>  
> -	if (of_pci_range_parser_init(&parser, np)) {
> -		dev_err(pp->dev, "missing ranges property\n");
> -		return -EINVAL;
> -	}
> +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
> +	if (ret)
> +		return ret;
>  
>  	/* Get the I/O and memory ranges from DT */
> -	for_each_of_pci_range(&parser, &range) {
> -		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
> -
> -		if (restype == IORESOURCE_IO) {
> -			of_pci_range_to_resource(&range, np, &pp->io);
> -			pp->io.name = "I/O";
> -			pp->io.start = max_t(resource_size_t,
> -					     PCIBIOS_MIN_IO,
> -					     range.pci_addr + global_io_offset);
> -			pp->io.end = min_t(resource_size_t,
> -					   IO_SPACE_LIMIT,
> -					   range.pci_addr + range.size
> -					   + global_io_offset - 1);
> -			pp->io_size = resource_size(&pp->io);
> -			pp->io_bus_addr = range.pci_addr;
> -			pp->io_base = range.cpu_addr;
> -
> -			/* Find the untranslated IO space address */
> -			pp->io_mod_base = range.cpu_addr;
> -		}
> -		if (restype == IORESOURCE_MEM) {
> -			of_pci_range_to_resource(&range, np, &pp->mem);
> -			pp->mem.name = "MEM";
> -			pp->mem_size = resource_size(&pp->mem);
> -			pp->mem_bus_addr = range.pci_addr;
> -
> -			/* Find the untranslated MEM space address */
> -			pp->mem_mod_base = range.cpu_addr;
> -		}
> -		if (restype == 0) {
> -			of_pci_range_to_resource(&range, np, &pp->cfg);
> -			pp->cfg0_size = resource_size(&pp->cfg)/2;
> -			pp->cfg1_size = resource_size(&pp->cfg)/2;
> -			pp->cfg0_base = pp->cfg.start;
> -			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
> -
> -			/* Find the untranslated configuration space address */
> -			pp->cfg0_mod_base = range.cpu_addr;
> -			pp->cfg1_mod_base = pp->cfg0_mod_base +
> -					    pp->cfg0_size;
> +	resource_list_for_each_entry(win, &res) {
> +		switch (resource_type(win->res)) {
> +		case IORESOURCE_IO:
> +			pp->io = win->res;
> +			pp->io->name = "I/O";
> +			pp->io_size = resource_size(pp->io);
> +			pp->io_bus_addr = pp->io->start - win->offset;
> +			ret = pci_remap_iospace(pp->io, pp->io_base);
> +			if (ret) {
> +				dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
> +					 ret, pp->io);
> +				continue;
> +			}
> +			break;
> +		case IORESOURCE_MEM:
> +			pp->mem = win->res;
> +			pp->mem->name = "MEM";
> +			pp->mem_size = resource_size(pp->mem);
> +			pp->mem_bus_addr = pp->mem->start - win->offset;
> +			break;
> +		case 0:
> +			pp->cfg = win->res;
> +			pp->cfg0_size = resource_size(pp->cfg)/2;
> +			pp->cfg1_size = resource_size(pp->cfg)/2;
> +			pp->cfg0_base = pp->cfg->start;
> +			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
> +			break;
> +		case IORESOURCE_BUS:
> +			pp->busn = win->res;
> +			break;
> +		default:
> +			continue;
>  		}
>  	}
>  
> -	ret = of_pci_parse_bus_range(np, &pp->busn);
> -	if (ret < 0) {
> -		pp->busn.name = np->name;
> -		pp->busn.start = 0;
> -		pp->busn.end = 0xff;
> -		pp->busn.flags = IORESOURCE_BUS;
> -		dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n",
> -			ret, &pp->busn);
> -	}
> -
>  	if (!pp->dbi_base) {
> -		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
> -					resource_size(&pp->cfg));
> +		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
> +					resource_size(pp->cfg));
>  		if (!pp->dbi_base) {
>  			dev_err(pp->dev, "error with ioremap\n");
>  			return -ENOMEM;
>  		}
>  	}
>  
> -	pp->mem_base = pp->mem.start;
> +	pp->mem_base = pp->mem->start;
>  
>  	if (!pp->va_cfg0_base) {
>  		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
> @@ -509,7 +473,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  
>  	if (!pp->ops->rd_other_conf)
>  		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
> -					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
> +					  PCIE_ATU_TYPE_MEM, pp->mem_base,
>  					  pp->mem_bus_addr, pp->mem_size);
>  
>  	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
> @@ -521,15 +485,40 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  	val |= PORT_LOGIC_SPEED_CHANGE;
>  	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
>  
> -#ifdef CONFIG_PCI_MSI
>  	dw_pcie_msi_chip.dev = pp->dev;
> -	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> +
> +	mutex_lock(&root_bus_nr_mux);
> +
> +	if (pp->root_bus_nr != DW_ROOT_NR_UNDEFINED)
> +		root_bus_nr = pp->root_bus_nr;
> +
> +	bus = pci_create_root_bus(pp->dev, root_bus_nr, &dw_pcie_ops,
> +			      pp, &res);
> +	if (!bus) {
> +		mutex_unlock(&root_bus_nr_mux);
> +		return -ENOMEM;
> +	}
> +
> +	root_bus_nr += bus->busn_res.end + 1;
> +	mutex_unlock(&root_bus_nr_mux);
> +
> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> +	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
> +#else
> +	bus->msi = &dw_pcie_msi_chip;
>  #endif
>  
> -	dw_pci.nr_controllers = 1;
> -	dw_pci.private_data = (void **)&pp;
> +	pci_scan_child_bus(bus);
> +	if (pp->ops->scan_bus)
> +		pp->ops->scan_bus(pp);
> +
> +#ifdef CONFIG_ARM
> +	/* support old dtbs that incorrectly describe IRQs */
> +	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
> +#endif
>  
> -	pci_common_init_dev(pp->dev, &dw_pci);
> +	pci_assign_unassigned_bus_resources(bus);
> +	pci_bus_add_devices(bus);
>  
>  	return 0;
>  }
> @@ -548,12 +537,12 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  
>  	if (bus->parent->number == pp->root_bus_nr) {
>  		type = PCIE_ATU_TYPE_CFG0;
> -		cpu_addr = pp->cfg0_mod_base;
> +		cpu_addr = pp->cfg0_base;
>  		cfg_size = pp->cfg0_size;
>  		va_cfg_base = pp->va_cfg0_base;
>  	} else {
>  		type = PCIE_ATU_TYPE_CFG1;
> -		cpu_addr = pp->cfg1_mod_base;
> +		cpu_addr = pp->cfg1_base;
>  		cfg_size = pp->cfg1_size;
>  		va_cfg_base = pp->va_cfg1_base;
>  	}
> @@ -563,7 +552,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  				  busdev, cfg_size);
>  	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
>  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> +				  PCIE_ATU_TYPE_IO, pp->io_base,
>  				  pp->io_bus_addr, pp->io_size);
>  
>  	return ret;
> @@ -583,12 +572,12 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  
>  	if (bus->parent->number == pp->root_bus_nr) {
>  		type = PCIE_ATU_TYPE_CFG0;
> -		cpu_addr = pp->cfg0_mod_base;
> +		cpu_addr = pp->cfg0_base;
>  		cfg_size = pp->cfg0_size;
>  		va_cfg_base = pp->va_cfg0_base;
>  	} else {
>  		type = PCIE_ATU_TYPE_CFG1;
> -		cpu_addr = pp->cfg1_mod_base;
> +		cpu_addr = pp->cfg1_base;
>  		cfg_size = pp->cfg1_size;
>  		va_cfg_base = pp->va_cfg1_base;
>  	}
> @@ -598,7 +587,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  				  busdev, cfg_size);
>  	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
>  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> +				  PCIE_ATU_TYPE_IO, pp->io_base,
>  				  pp->io_bus_addr, pp->io_size);
>  
>  	return ret;
> @@ -630,7 +619,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
>  static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
>  			int size, u32 *val)
>  {
> -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> +	struct pcie_port *pp = bus->sysdata;
>  	int ret;
>  
>  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
> @@ -654,7 +643,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
>  static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
>  			int where, int size, u32 val)
>  {
> -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> +	struct pcie_port *pp = bus->sysdata;
>  	int ret;
>  
>  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
> @@ -678,62 +667,6 @@ static struct pci_ops dw_pcie_ops = {
>  	.write = dw_pcie_wr_conf,
>  };
>  
> -static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
> -{
> -	struct pcie_port *pp;
> -
> -	pp = sys_to_pcie(sys);
> -
> -	if (global_io_offset < SZ_1M && pp->io_size > 0) {
> -		sys->io_offset = global_io_offset - pp->io_bus_addr;
> -		pci_ioremap_io(global_io_offset, pp->io_base);
> -		global_io_offset += SZ_64K;
> -		pci_add_resource_offset(&sys->resources, &pp->io,
> -					sys->io_offset);
> -	}
> -
> -	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
> -	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
> -	pci_add_resource(&sys->resources, &pp->busn);
> -
> -	return 1;
> -}
> -
> -static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
> -{
> -	struct pci_bus *bus;
> -	struct pcie_port *pp = sys_to_pcie(sys);
> -
> -	pp->root_bus_nr = sys->busnr;
> -	bus = pci_scan_root_bus(pp->dev, sys->busnr,
> -				  &dw_pcie_ops, sys, &sys->resources);
> -	if (!bus)
> -		return NULL;
> -
> -	if (bus && pp->ops->scan_bus)
> -		pp->ops->scan_bus(pp);
> -
> -	return bus;
> -}
> -
> -static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> -{
> -	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
> -	int irq;
> -
> -	irq = of_irq_parse_and_map_pci(dev, slot, pin);
> -	if (!irq)
> -		irq = pp->irq;
> -
> -	return irq;
> -}
> -
> -static struct hw_pci dw_pci = {
> -	.setup		= dw_pcie_setup,
> -	.scan		= dw_pcie_scan_bus,
> -	.map_irq	= dw_pcie_map_irq,
> -};
> -
>  void dw_pcie_setup_rc(struct pcie_port *pp)
>  {
>  	u32 val;
> diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
> index d0bbd27..0c2a7eb 100644
> --- a/drivers/pci/host/pcie-designware.h
> +++ b/drivers/pci/host/pcie-designware.h
> @@ -21,31 +21,28 @@
>   */
>  #define MAX_MSI_IRQS			32
>  #define MAX_MSI_CTRLS			(MAX_MSI_IRQS / 32)
> +#define DW_ROOT_NR_UNDEFINED	-1
>  
>  struct pcie_port {
>  	struct device		*dev;
>  	u8			root_bus_nr;
>  	void __iomem		*dbi_base;
>  	u64			cfg0_base;
> -	u64			cfg0_mod_base;
>  	void __iomem		*va_cfg0_base;
>  	u32			cfg0_size;
>  	u64			cfg1_base;
> -	u64			cfg1_mod_base;
>  	void __iomem		*va_cfg1_base;
>  	u32			cfg1_size;
> -	u64			io_base;
> -	u64			io_mod_base;
> +	resource_size_t		io_base;
>  	phys_addr_t		io_bus_addr;
>  	u32			io_size;
>  	u64			mem_base;
> -	u64			mem_mod_base;
>  	phys_addr_t		mem_bus_addr;
>  	u32			mem_size;
> -	struct resource		cfg;
> -	struct resource		io;
> -	struct resource		mem;
> -	struct resource		busn;
> +	struct resource		*cfg;
> +	struct resource		*io;
> +	struct resource		*mem;
> +	struct resource		*busn;
>  	int			irq;
>  	u32			lanes;
>  	struct pcie_host_ops	*ops;
> diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
> index c49fbdc..b2c59b9 100644
> --- a/drivers/pci/host/pcie-spear13xx.c
> +++ b/drivers/pci/host/pcie-spear13xx.c
> @@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
>  		return ret;
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
>  	pp->ops = &spear13xx_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> -- 
> 1.9.1
> 
> 
> > -----Original Message-----
> > From: Lucas Stach [mailto:l.stach@pengutronix.de]
> > Sent: Wednesday, August 19, 2015 1:54 PM
> > To: Wangzhou (B)
> > Cc: Bjorn Helgaas; jingoohan1@gmail.com; Pratyush Anand; Arnd Bergmann;
> > linux@arm.linux.org.uk; thomas.petazzoni@free-electrons.com; Gabriele
> > Paoloni; lorenzo.pieralisi@arm.com; james.morse@arm.com;
> > Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org; linux-
> > pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> > devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > 
> > Am Montag, den 17.08.2015, 19:55 +0800 schrieb Zhou Wang:
> > > This patch tries to unify ARM32 and ARM64 PCIe in designware driver.
> > Delete
> > > function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct
> > hw_pci,
> > > move related operations to dw_pcie_host_init.
> > >
> > > In past, we use:
> > > pci_common_init_dev
> > > 	-> pcibios_init_hw
> > > 		-> hw->scan (dw_pcie_scan_bus)
> > > to pass 0 to root_bus_nr in struct pcie_port. This patch set pp-
> > >root_bus_nr = 0
> > > in each PCIe host driver which is based on pcie-designware.
> > >
> > This is incorrect at least if there are 2 instances of DW PCIe host in
> > the same SoC without using PCI domains. In that the case the bus range
> > determines the range of valid bus numbers per instance and the first
> > number is the root bus. Please look at the "bus-range" DT property in
> > the DW PCIe bindings.
> > 
> > Also we should finally remove this root-bus setup from the glue drivers
> > altogether. It's something that entirely belongs into the DW core code.
> > 
> > Regards,
> > Lucas
> > 
> > > This patch also try to use of_pci_get_host_bridge_resources for ARM32
> > and ARM64
> > > according to the suggestion for Gabriele[1]
> > >
> > > Finally this patch reverts commit f4c55c5a3f7f "PCI: designware:
> > Program ATU
> > > with untranslated address" based on 1/6 in this series. we delete
> > *_mod_base in
> > > pcie-designware. This was discussed in [2]
> > >
> > > I have compiled the driver with multi_v7_defconfig. However, I don't
> > have
> > > ARM32 PCIe related board to do test. It will be appreciated if
> > someone could
> > > help to test it.
> > >
> > > Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> > > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> > > Tested-By: James Morse <james.morse@arm.com>
> > >
> > > [1] http://www.spinics.net/lists/linux-pci/msg42194.html
> > > [2] http://www.spinics.net/lists/arm-kernel/msg436779.html
> > > ---
> > >  drivers/pci/host/pci-dra7xx.c      |  15 +--
> > >  drivers/pci/host/pci-exynos.c      |   2 +-
> > >  drivers/pci/host/pci-imx6.c        |   2 +-
> > >  drivers/pci/host/pci-keystone-dw.c |   2 +-
> > >  drivers/pci/host/pci-keystone.c    |   2 +-
> > >  drivers/pci/host/pci-layerscape.c  |   2 +-
> > >  drivers/pci/host/pcie-designware.c | 229 ++++++++++++---------------
> > ----------
> > >  drivers/pci/host/pcie-designware.h |  14 +--
> > >  drivers/pci/host/pcie-spear13xx.c  |   2 +-
> > >  9 files changed, 95 insertions(+), 175 deletions(-)
> > >
> > > diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-
> > dra7xx.c
> > > index 18ae7ff..1268c69 100644
> > > --- a/drivers/pci/host/pci-dra7xx.c
> > > +++ b/drivers/pci/host/pci-dra7xx.c
> > > @@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct
> > pcie_port *pp)
> > >  {
> > >  	dw_pcie_setup_rc(pp);
> > >
> > > -	if (pp->io_mod_base)
> > > -		pp->io_mod_base &= CPU_TO_BUS_ADDR;
> > > +	if (pp->io_base)
> > > +		pp->io_base &= CPU_TO_BUS_ADDR;
> > >
> > > -	if (pp->mem_mod_base)
> > > -		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
> > > +	if (pp->mem_base)
> > > +		pp->mem_base &= CPU_TO_BUS_ADDR;
> > >
> > > -	if (pp->cfg0_mod_base) {
> > > -		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
> > > -		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
> > > +	if (pp->cfg0_base) {
> > > +		pp->cfg0_base &= CPU_TO_BUS_ADDR;
> > > +		pp->cfg1_base &= CPU_TO_BUS_ADDR;
> > >  	}
> > >
> > >  	dra7xx_pcie_establish_link(pp);
> > > @@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct
> > dra7xx_pcie *dra7xx,
> > >
> > >  	pp = &dra7xx->pp;
> > >  	pp->dev = dev;
> > > +	pp->root_bus_nr = 0;
> > >  	pp->ops = &dra7xx_pcie_host_ops;
> > >
> > >  	pp->irq = platform_get_irq(pdev, 1);
> > > diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-
> > exynos.c
> > > index f9f468d..9771bb0 100644
> > > --- a/drivers/pci/host/pci-exynos.c
> > > +++ b/drivers/pci/host/pci-exynos.c
> > > @@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct
> > pcie_port *pp,
> > >  		}
> > >  	}
> > >
> > > -	pp->root_bus_nr = -1;
> > > +	pp->root_bus_nr = 0;
> > >  	pp->ops = &exynos_pcie_host_ops;
> > >
> > >  	ret = dw_pcie_host_init(pp);
> > > diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-
> > imx6.c
> > > index 233a196..bec256c 100644
> > > --- a/drivers/pci/host/pci-imx6.c
> > > +++ b/drivers/pci/host/pci-imx6.c
> > > @@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct
> > pcie_port *pp,
> > >  		}
> > >  	}
> > >
> > > -	pp->root_bus_nr = -1;
> > > +	pp->root_bus_nr = 0;
> > >  	pp->ops = &imx6_pcie_host_ops;
> > >
> > >  	ret = dw_pcie_host_init(pp);
> > > diff --git a/drivers/pci/host/pci-keystone-dw.c
> > b/drivers/pci/host/pci-keystone-dw.c
> > > index f34892e..b1e4135 100644
> > > --- a/drivers/pci/host/pci-keystone-dw.c
> > > +++ b/drivers/pci/host/pci-keystone-dw.c
> > > @@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void
> > __iomem *reg_virt)
> > >  void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
> > >  {
> > >  	struct pcie_port *pp = &ks_pcie->pp;
> > > -	u32 start = pp->mem.start, end = pp->mem.end;
> > > +	u32 start = pp->mem->start, end = pp->mem->end;
> > >  	int i, tr_size;
> > >
> > >  	/* Disable BARs for inbound access */
> > > diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-
> > keystone.c
> > > index 734da58..8113832 100644
> > > --- a/drivers/pci/host/pci-keystone.c
> > > +++ b/drivers/pci/host/pci-keystone.c
> > > @@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct
> > keystone_pcie *ks_pcie,
> > >  			return ret;
> > >  	}
> > >
> > > -	pp->root_bus_nr = -1;
> > > +	pp->root_bus_nr = 0;
> > >  	pp->ops = &keystone_pcie_host_ops;
> > >  	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
> > >  	if (ret) {
> > > diff --git a/drivers/pci/host/pci-layerscape.c
> > b/drivers/pci/host/pci-layerscape.c
> > > index b2328ea1..79ff08c 100644
> > > --- a/drivers/pci/host/pci-layerscape.c
> > > +++ b/drivers/pci/host/pci-layerscape.c
> > > @@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
> > >  	pp = &pcie->pp;
> > >  	pp->dev = pcie->dev;
> > >  	pp->dbi_base = pcie->dbi;
> > > -	pp->root_bus_nr = -1;
> > > +	pp->root_bus_nr = 0;
> > >  	pp->ops = &ls_pcie_host_ops;
> > >
> > >  	ret = dw_pcie_host_init(pp);
> > > diff --git a/drivers/pci/host/pcie-designware.c
> > b/drivers/pci/host/pcie-designware.c
> > > index c5d407c..e71a88e 100644
> > > --- a/drivers/pci/host/pcie-designware.c
> > > +++ b/drivers/pci/host/pcie-designware.c
> > > @@ -11,6 +11,7 @@
> > >   * published by the Free Software Foundation.
> > >   */
> > >
> > > +#include <linux/hardirq.h>
> > >  #include <linux/irq.h>
> > >  #include <linux/irqdomain.h>
> > >  #include <linux/kernel.h>
> > > @@ -69,16 +70,7 @@
> > >  #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
> > >  #define PCIE_ATU_UPPER_TARGET		0x91C
> > >
> > > -static struct hw_pci dw_pci;
> > > -
> > > -static unsigned long global_io_offset;
> > > -
> > > -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
> > > -{
> > > -	BUG_ON(!sys->private_data);
> > > -
> > > -	return sys->private_data;
> > > -}
> > > +static struct pci_ops dw_pcie_ops;
> > >
> > >  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32
> > *val)
> > >  {
> > > @@ -255,7 +247,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port
> > *pp, int irq)
> > >  static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
> > >  {
> > >  	int irq, pos0, i;
> > > -	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
> > > +	struct pcie_port *pp = desc->dev->bus->sysdata;
> > >
> > >  	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
> > >  				       order_base_2(no_irqs));
> > > @@ -298,7 +290,7 @@ static int dw_msi_setup_irq(struct msi_controller
> > *chip, struct pci_dev *pdev,
> > >  {
> > >  	int irq, pos;
> > >  	struct msi_msg msg;
> > > -	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
> > > +	struct pcie_port *pp = pdev->bus->sysdata;
> > >
> > >  	if (desc->msi_attrib.is_msix)
> > >  		return -EINVAL;
> > > @@ -327,7 +319,7 @@ static void dw_msi_teardown_irq(struct
> > msi_controller *chip, unsigned int irq)
> > >  {
> > >  	struct irq_data *data = irq_get_irq_data(irq);
> > >  	struct msi_desc *msi = irq_data_get_msi(data);
> > > -	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
> > > +	struct pcie_port *pp = msi->dev->bus->sysdata;
> > >
> > >  	clear_irq_range(pp, irq, 1, data->hwirq);
> > >  }
> > > @@ -363,14 +355,12 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > >  {
> > >  	struct device_node *np = pp->dev->of_node;
> > >  	struct platform_device *pdev = to_platform_device(pp->dev);
> > > -	struct of_pci_range range;
> > > -	struct of_pci_range_parser parser;
> > > +	struct pci_bus *bus;
> > >  	struct resource *cfg_res;
> > > -	u32 val, ns;
> > > -	const __be32 *addrp;
> > > -	int i, index, ret;
> > > -
> > > -	ns = of_n_size_cells(np);
> > > +	LIST_HEAD(res);
> > > +	u32 val;
> > > +	int i, ret;
> > > +	struct resource_entry *win;
> > >
> > >  	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> > "config");
> > >  	if (cfg_res) {
> > > @@ -378,85 +368,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > >  		pp->cfg1_size = resource_size(cfg_res)/2;
> > >  		pp->cfg0_base = cfg_res->start;
> > >  		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
> > > -
> > > -		/* Find the untranslated configuration space address */
> > > -		index = of_property_match_string(np, "reg-names", "config");
> > > -		addrp = of_get_address(np, index, NULL, NULL);
> > > -		pp->cfg0_mod_base = of_read_number(addrp, ns);
> > > -		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
> > >  	} else {
> > >  		dev_err(pp->dev, "missing *config* reg space\n");
> > >  	}
> > >
> > > -	if (of_pci_range_parser_init(&parser, np)) {
> > > -		dev_err(pp->dev, "missing ranges property\n");
> > > -		return -EINVAL;
> > > -	}
> > > +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp-
> > >io_base);
> > > +	if (ret)
> > > +		return ret;
> > >
> > >  	/* Get the I/O and memory ranges from DT */
> > > -	for_each_of_pci_range(&parser, &range) {
> > > -		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
> > > -
> > > -		if (restype == IORESOURCE_IO) {
> > > -			of_pci_range_to_resource(&range, np, &pp->io);
> > > -			pp->io.name = "I/O";
> > > -			pp->io.start = max_t(resource_size_t,
> > > -					     PCIBIOS_MIN_IO,
> > > -					     range.pci_addr + global_io_offset);
> > > -			pp->io.end = min_t(resource_size_t,
> > > -					   IO_SPACE_LIMIT,
> > > -					   range.pci_addr + range.size
> > > -					   + global_io_offset - 1);
> > > -			pp->io_size = resource_size(&pp->io);
> > > -			pp->io_bus_addr = range.pci_addr;
> > > -			pp->io_base = range.cpu_addr;
> > > -
> > > -			/* Find the untranslated IO space address */
> > > -			pp->io_mod_base = range.cpu_addr;
> > > -		}
> > > -		if (restype == IORESOURCE_MEM) {
> > > -			of_pci_range_to_resource(&range, np, &pp->mem);
> > > -			pp->mem.name = "MEM";
> > > -			pp->mem_size = resource_size(&pp->mem);
> > > -			pp->mem_bus_addr = range.pci_addr;
> > > -
> > > -			/* Find the untranslated MEM space address */
> > > -			pp->mem_mod_base = range.cpu_addr;
> > > -		}
> > > -		if (restype == 0) {
> > > -			of_pci_range_to_resource(&range, np, &pp->cfg);
> > > -			pp->cfg0_size = resource_size(&pp->cfg)/2;
> > > -			pp->cfg1_size = resource_size(&pp->cfg)/2;
> > > -			pp->cfg0_base = pp->cfg.start;
> > > -			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
> > > -
> > > -			/* Find the untranslated configuration space address
> > */
> > > -			pp->cfg0_mod_base = range.cpu_addr;
> > > -			pp->cfg1_mod_base = pp->cfg0_mod_base +
> > > -					    pp->cfg0_size;
> > > +	resource_list_for_each_entry(win, &res) {
> > > +		switch (resource_type(win->res)) {
> > > +		case IORESOURCE_IO:
> > > +			pp->io = win->res;
> > > +			pp->io->name = "I/O";
> > > +			pp->io_size = resource_size(pp->io);
> > > +			pp->io_bus_addr = pp->io->start - win->offset;
> > > +			ret = pci_remap_iospace(pp->io, pp->io_base);
> > > +			if (ret) {
> > > +				dev_warn(pp->dev, "error %d: failed to map
> > resource %pR\n",
> > > +					 ret, pp->io);
> > > +				continue;
> > > +			}
> > > +			break;
> > > +		case IORESOURCE_MEM:
> > > +			pp->mem = win->res;
> > > +			pp->mem->name = "MEM";
> > > +			pp->mem_size = resource_size(pp->mem);
> > > +			pp->mem_bus_addr = pp->mem->start - win->offset;
> > > +			break;
> > > +		case 0:
> > > +			pp->cfg = win->res;
> > > +			pp->cfg0_size = resource_size(pp->cfg)/2;
> > > +			pp->cfg1_size = resource_size(pp->cfg)/2;
> > > +			pp->cfg0_base = pp->cfg->start;
> > > +			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
> > > +			break;
> > > +		case IORESOURCE_BUS:
> > > +			pp->busn = win->res;
> > > +			break;
> > > +		default:
> > > +			continue;
> > >  		}
> > >  	}
> > >
> > > -	ret = of_pci_parse_bus_range(np, &pp->busn);
> > > -	if (ret < 0) {
> > > -		pp->busn.name = np->name;
> > > -		pp->busn.start = 0;
> > > -		pp->busn.end = 0xff;
> > > -		pp->busn.flags = IORESOURCE_BUS;
> > > -		dev_dbg(pp->dev, "failed to parse bus-range property: %d,
> > using default %pR\n",
> > > -			ret, &pp->busn);
> > > -	}
> > > -
> > >  	if (!pp->dbi_base) {
> > > -		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
> > > -					resource_size(&pp->cfg));
> > > +		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
> > > +					resource_size(pp->cfg));
> > >  		if (!pp->dbi_base) {
> > >  			dev_err(pp->dev, "error with ioremap\n");
> > >  			return -ENOMEM;
> > >  		}
> > >  	}
> > >
> > > -	pp->mem_base = pp->mem.start;
> > > +	pp->mem_base = pp->mem->start;
> > >
> > >  	if (!pp->va_cfg0_base) {
> > >  		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
> > > @@ -505,7 +470,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > >
> > >  	if (!pp->ops->rd_other_conf)
> > >  		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
> > > -					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
> > > +					  PCIE_ATU_TYPE_MEM, pp->mem_base,
> > >  					  pp->mem_bus_addr, pp->mem_size);
> > >
> > >  	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
> > > @@ -517,15 +482,29 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > >  	val |= PORT_LOGIC_SPEED_CHANGE;
> > >  	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
> > >
> > > -#ifdef CONFIG_PCI_MSI
> > > +	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
> > > +				  pp, &res);
> > > +	if (!bus)
> > > +		return -ENOMEM;
> > > +
> > > +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> > > +	bus->msi = container_of(&pp->irq_domain, struct msi_controller,
> > domain);
> > > +#else
> > >  	dw_pcie_msi_chip.dev = pp->dev;
> > > -	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> > > +	bus->msi = &dw_pcie_msi_chip;
> > >  #endif
> > >
> > > -	dw_pci.nr_controllers = 1;
> > > -	dw_pci.private_data = (void **)&pp;
> > > +	pci_scan_child_bus(bus);
> > > +	if (pp->ops->scan_bus)
> > > +		pp->ops->scan_bus(pp);
> > > +
> > > +#ifdef CONFIG_ARM
> > > +	/* support old dtbs that incorrectly describe IRQs */
> > > +	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
> > > +#endif
> > >
> > > -	pci_common_init_dev(pp->dev, &dw_pci);
> > > +	pci_assign_unassigned_bus_resources(bus);
> > > +	pci_bus_add_devices(bus);
> > >
> > >  	return 0;
> > >  }
> > > @@ -544,12 +523,12 @@ static int dw_pcie_rd_other_conf(struct
> > pcie_port *pp, struct pci_bus *bus,
> > >
> > >  	if (bus->parent->number == pp->root_bus_nr) {
> > >  		type = PCIE_ATU_TYPE_CFG0;
> > > -		cpu_addr = pp->cfg0_mod_base;
> > > +		cpu_addr = pp->cfg0_base;
> > >  		cfg_size = pp->cfg0_size;
> > >  		va_cfg_base = pp->va_cfg0_base;
> > >  	} else {
> > >  		type = PCIE_ATU_TYPE_CFG1;
> > > -		cpu_addr = pp->cfg1_mod_base;
> > > +		cpu_addr = pp->cfg1_base;
> > >  		cfg_size = pp->cfg1_size;
> > >  		va_cfg_base = pp->va_cfg1_base;
> > >  	}
> > > @@ -559,7 +538,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port
> > *pp, struct pci_bus *bus,
> > >  				  busdev, cfg_size);
> > >  	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
> > >  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> > > -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> > > +				  PCIE_ATU_TYPE_IO, pp->io_base,
> > >  				  pp->io_bus_addr, pp->io_size);
> > >
> > >  	return ret;
> > > @@ -579,12 +558,12 @@ static int dw_pcie_wr_other_conf(struct
> > pcie_port *pp, struct pci_bus *bus,
> > >
> > >  	if (bus->parent->number == pp->root_bus_nr) {
> > >  		type = PCIE_ATU_TYPE_CFG0;
> > > -		cpu_addr = pp->cfg0_mod_base;
> > > +		cpu_addr = pp->cfg0_base;
> > >  		cfg_size = pp->cfg0_size;
> > >  		va_cfg_base = pp->va_cfg0_base;
> > >  	} else {
> > >  		type = PCIE_ATU_TYPE_CFG1;
> > > -		cpu_addr = pp->cfg1_mod_base;
> > > +		cpu_addr = pp->cfg1_base;
> > >  		cfg_size = pp->cfg1_size;
> > >  		va_cfg_base = pp->va_cfg1_base;
> > >  	}
> > > @@ -594,7 +573,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port
> > *pp, struct pci_bus *bus,
> > >  				  busdev, cfg_size);
> > >  	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
> > >  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> > > -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> > > +				  PCIE_ATU_TYPE_IO, pp->io_base,
> > >  				  pp->io_bus_addr, pp->io_size);
> > >
> > >  	return ret;
> > > @@ -626,7 +605,7 @@ static int dw_pcie_valid_config(struct pcie_port
> > *pp,
> > >  static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> > >  			int size, u32 *val)
> > >  {
> > > -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> > > +	struct pcie_port *pp = bus->sysdata;
> > >  	int ret;
> > >
> > >  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
> > > @@ -650,7 +629,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus,
> > u32 devfn, int where,
> > >  static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
> > >  			int where, int size, u32 val)
> > >  {
> > > -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> > > +	struct pcie_port *pp = bus->sysdata;
> > >  	int ret;
> > >
> > >  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
> > > @@ -674,62 +653,6 @@ static struct pci_ops dw_pcie_ops = {
> > >  	.write = dw_pcie_wr_conf,
> > >  };
> > >
> > > -static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
> > > -{
> > > -	struct pcie_port *pp;
> > > -
> > > -	pp = sys_to_pcie(sys);
> > > -
> > > -	if (global_io_offset < SZ_1M && pp->io_size > 0) {
> > > -		sys->io_offset = global_io_offset - pp->io_bus_addr;
> > > -		pci_ioremap_io(global_io_offset, pp->io_base);
> > > -		global_io_offset += SZ_64K;
> > > -		pci_add_resource_offset(&sys->resources, &pp->io,
> > > -					sys->io_offset);
> > > -	}
> > > -
> > > -	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
> > > -	pci_add_resource_offset(&sys->resources, &pp->mem, sys-
> > >mem_offset);
> > > -	pci_add_resource(&sys->resources, &pp->busn);
> > > -
> > > -	return 1;
> > > -}
> > > -
> > > -static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data
> > *sys)
> > > -{
> > > -	struct pci_bus *bus;
> > > -	struct pcie_port *pp = sys_to_pcie(sys);
> > > -
> > > -	pp->root_bus_nr = sys->busnr;
> > > -	bus = pci_scan_root_bus(pp->dev, sys->busnr,
> > > -				  &dw_pcie_ops, sys, &sys->resources);
> > > -	if (!bus)
> > > -		return NULL;
> > > -
> > > -	if (bus && pp->ops->scan_bus)
> > > -		pp->ops->scan_bus(pp);
> > > -
> > > -	return bus;
> > > -}
> > > -
> > > -static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8
> > pin)
> > > -{
> > > -	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
> > > -	int irq;
> > > -
> > > -	irq = of_irq_parse_and_map_pci(dev, slot, pin);
> > > -	if (!irq)
> > > -		irq = pp->irq;
> > > -
> > > -	return irq;
> > > -}
> > > -
> > > -static struct hw_pci dw_pci = {
> > > -	.setup		= dw_pcie_setup,
> > > -	.scan		= dw_pcie_scan_bus,
> > > -	.map_irq	= dw_pcie_map_irq,
> > > -};
> > > -
> > >  void dw_pcie_setup_rc(struct pcie_port *pp)
> > >  {
> > >  	u32 val;
> > > diff --git a/drivers/pci/host/pcie-designware.h
> > b/drivers/pci/host/pcie-designware.h
> > > index d0bbd27..264c969 100644
> > > --- a/drivers/pci/host/pcie-designware.h
> > > +++ b/drivers/pci/host/pcie-designware.h
> > > @@ -27,25 +27,21 @@ struct pcie_port {
> > >  	u8			root_bus_nr;
> > >  	void __iomem		*dbi_base;
> > >  	u64			cfg0_base;
> > > -	u64			cfg0_mod_base;
> > >  	void __iomem		*va_cfg0_base;
> > >  	u32			cfg0_size;
> > >  	u64			cfg1_base;
> > > -	u64			cfg1_mod_base;
> > >  	void __iomem		*va_cfg1_base;
> > >  	u32			cfg1_size;
> > > -	u64			io_base;
> > > -	u64			io_mod_base;
> > > +	resource_size_t		io_base;
> > >  	phys_addr_t		io_bus_addr;
> > >  	u32			io_size;
> > >  	u64			mem_base;
> > > -	u64			mem_mod_base;
> > >  	phys_addr_t		mem_bus_addr;
> > >  	u32			mem_size;
> > > -	struct resource		cfg;
> > > -	struct resource		io;
> > > -	struct resource		mem;
> > > -	struct resource		busn;
> > > +	struct resource		*cfg;
> > > +	struct resource		*io;
> > > +	struct resource		*mem;
> > > +	struct resource		*busn;
> > >  	int			irq;
> > >  	u32			lanes;
> > >  	struct pcie_host_ops	*ops;
> > > diff --git a/drivers/pci/host/pcie-spear13xx.c
> > b/drivers/pci/host/pcie-spear13xx.c
> > > index c49fbdc..03eb204 100644
> > > --- a/drivers/pci/host/pcie-spear13xx.c
> > > +++ b/drivers/pci/host/pcie-spear13xx.c
> > > @@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct
> > pcie_port *pp,
> > >  		return ret;
> > >  	}
> > >
> > > -	pp->root_bus_nr = -1;
> > > +	pp->root_bus_nr = 0;
> > >  	pp->ops = &spear13xx_pcie_host_ops;
> > >
> > >  	ret = dw_pcie_host_init(pp);
> > 
> > --
> > Pengutronix e.K.             | Lucas Stach                 |
> > Industrial Linux Solutions   | http://www.pengutronix.de/  |
> 

-- 
Pengutronix e.K.             | Lucas Stach                 |
Industrial Linux Solutions   | http://www.pengutronix.de/  |

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

* Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-19 15:37         ` Lucas Stach
  0 siblings, 0 replies; 53+ messages in thread
From: Lucas Stach @ 2015-08-19 15:37 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Wangzhou (B),
	Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, lorenzo.pieralisi, james.morse, Liviu.Dudau,
	jason, robh, linux-pci, linux-arm-kernel, devicetree,
	Yuanzhichang, Zhudacai, zhangjukuo, qiuzhenfa, liudongdong (C),
	qiujiang, xuwei (O), Liguozhu (Kenneth)

Hi Gab,

Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele Paoloni:
> Hi Lucas
> 
> I have rewritten the patch to take into account multiple controllers.
> 
> As you can see now there is a static var in dw_pcie_host_init() that tracks
> the bus numbers used.

This is wrong. The DT specifies the valid bus number range. You can not
just assign the next free bus number to the root bus.

It is perfectly valid to have a bus range of 0x00-0x10 assigned to one
instance and 0x50-0xff to the next instance. Additional with PCIe
hotplug you may not use the full range of the bus numbers on one
instance at the first scan, but only later populate more buses when more
bridges are added to the tree.

> Drivers that do not specify the bus range in the DTB set pp->root_bus_nr = DW_ROOT_NR_UNDEFINED.
> Designware will check if the flag is set and will use the automatic bus range
> assignment.

No, please lets get rid of this assignment altogether. The glue drivers
have no business in assigning the bus range. Please remove the
pp->root_bus_nr assignment from all the glue drivers.

"bus range" is a generic DW PCIe property, so just parse the root bus
number from the DT, it is handled the same way for all the DW based PCIe
drivers. The bindings specifies that if the bus range property is
missing the range is 0x00-0xff, so you can default to 0 as the root bus
number in that case.

Also I would think this conversion warrants a patch on its own and
should not be mixed in the ARM64 support patch.

Regards,
Lucas

> Instead if the driver assigns pp->root_bus_nr according to the dtb, designwware
> will use the value passed in by the driver.
> Below the relevant section:
> 
> 
> +	static int root_bus_nr = 0;
> ...
> +	mutex_lock(&root_bus_nr_mux);
> +
> +	if (pp->root_bus_nr != DW_ROOT_NR_UNDEFINED)
> +		root_bus_nr = pp->root_bus_nr;
> +
> +	bus = pci_create_root_bus(pp->dev, root_bus_nr, &dw_pcie_ops,
> +			      pp, &res);
> +	if (!bus) {
> +		mutex_unlock(&root_bus_nr_mux);
> +		return -ENOMEM;
> +	}
> +
> +	root_bus_nr += bus->busn_res.end + 1;
> +	mutex_unlock(&root_bus_nr_mux);
> 
> Please let me know what you think...
> 
> Many Thanks
> 
> Gab
> ----------
> 
> From: gabriele paoloni <gabriele.paoloni@huawei.com>
> 
> This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete
> function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci,
> move related operations to dw_pcie_host_init.
> Also set pp->root_bus_nr = DW_ROOT_NR_UNDEFINED in all the drivers that
> are based on designware to flag that the drivers do not read the bus
> ranges from DT.
> This patch also adds handling of multiple PCI domains in designware.
> if the PCI host bridge driver does not specify a root bus number, in case
> of multiple domains, designware will automatillay set the next domain root
> bus number to the last bus number used in the last domain + 1.
> 
> This patch also try to use of_pci_get_host_bridge_resources for ARM32 and
> ARM64 according to the suggestion for Gabriele[1]
> 
> This patch is based on Gabriele's patch about of_pci_range fix[2]
> 
> Finally this patch reverts commit f4c55c5a3f7f "PCI: designware:
> Program ATU with untranslated address". This was discussed in [3]
> 
> I have compiled the driver with multi_v7_defconfig. However, I don't have
> ARM32 PCIe related board to do test. It will be appreciated if someone could
> help to test it.
> 
> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> 
> [1] http://www.spinics.net/lists/linux-pci/msg42194.html
> [2] https://patchwork.ozlabs.org/patch/495018/
> [3] http://www.spinics.net/lists/arm-kernel/msg436779.html
> ---
>  drivers/pci/host/pci-dra7xx.c      |  15 +--
>  drivers/pci/host/pci-exynos.c      |   2 +-
>  drivers/pci/host/pci-imx6.c        |   2 +-
>  drivers/pci/host/pci-keystone-dw.c |   2 +-
>  drivers/pci/host/pci-keystone.c    |   2 +-
>  drivers/pci/host/pci-layerscape.c  |   2 +-
>  drivers/pci/host/pcie-designware.c | 247 ++++++++++++++-----------------------
>  drivers/pci/host/pcie-designware.h |  15 +--
>  drivers/pci/host/pcie-spear13xx.c  |   2 +-
>  9 files changed, 110 insertions(+), 179 deletions(-)
> 
> diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
> index 5678b57..8d598fb 100644
> --- a/drivers/pci/host/pci-dra7xx.c
> +++ b/drivers/pci/host/pci-dra7xx.c
> @@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp)
>  {
>  	dw_pcie_setup_rc(pp);
>  
> -	if (pp->io_mod_base)
> -		pp->io_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->io_base)
> +		pp->io_base &= CPU_TO_BUS_ADDR;
>  
> -	if (pp->mem_mod_base)
> -		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->mem_base)
> +		pp->mem_base &= CPU_TO_BUS_ADDR;
>  
> -	if (pp->cfg0_mod_base) {
> -		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
> -		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->cfg0_base) {
> +		pp->cfg0_base &= CPU_TO_BUS_ADDR;
> +		pp->cfg1_base &= CPU_TO_BUS_ADDR;
>  	}
>  
>  	dra7xx_pcie_establish_link(pp);
> @@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
>  
>  	pp = &dra7xx->pp;
>  	pp->dev = dev;
> +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
>  	pp->ops = &dra7xx_pcie_host_ops;
>  
>  	pp->irq = platform_get_irq(pdev, 1);
> diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
> index f9f468d..ed03a8f 100644
> --- a/drivers/pci/host/pci-exynos.c
> +++ b/drivers/pci/host/pci-exynos.c
> @@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
>  		}
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
>  	pp->ops = &exynos_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
> index 233a196..0efac85 100644
> --- a/drivers/pci/host/pci-imx6.c
> +++ b/drivers/pci/host/pci-imx6.c
> @@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
>  		}
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
>  	pp->ops = &imx6_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c
> index f34892e..b1e4135 100644
> --- a/drivers/pci/host/pci-keystone-dw.c
> +++ b/drivers/pci/host/pci-keystone-dw.c
> @@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void __iomem *reg_virt)
>  void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
>  {
>  	struct pcie_port *pp = &ks_pcie->pp;
> -	u32 start = pp->mem.start, end = pp->mem.end;
> +	u32 start = pp->mem->start, end = pp->mem->end;
>  	int i, tr_size;
>  
>  	/* Disable BARs for inbound access */
> diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
> index 734da58..b522956 100644
> --- a/drivers/pci/host/pci-keystone.c
> +++ b/drivers/pci/host/pci-keystone.c
> @@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
>  			return ret;
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
>  	pp->ops = &keystone_pcie_host_ops;
>  	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
>  	if (ret) {
> diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
> index b2328ea1..dd92ffa 100644
> --- a/drivers/pci/host/pci-layerscape.c
> +++ b/drivers/pci/host/pci-layerscape.c
> @@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
>  	pp = &pcie->pp;
>  	pp->dev = pcie->dev;
>  	pp->dbi_base = pcie->dbi;
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
>  	pp->ops = &ls_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
> index 5307b35..bd2606b 100644
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c
> @@ -11,6 +11,7 @@
>   * published by the Free Software Foundation.
>   */
>  
> +#include <linux/hardirq.h>
>  #include <linux/irq.h>
>  #include <linux/irqdomain.h>
>  #include <linux/kernel.h>
> @@ -69,16 +70,9 @@
>  #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
>  #define PCIE_ATU_UPPER_TARGET		0x91C
>  
> -static struct hw_pci dw_pci;
> +static struct pci_ops dw_pcie_ops;
>  
> -static unsigned long global_io_offset;
> -
> -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
> -{
> -	BUG_ON(!sys->private_data);
> -
> -	return sys->private_data;
> -}
> +DEFINE_MUTEX(root_bus_nr_mux);
>  
>  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
>  {
> @@ -255,7 +249,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
>  static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
>  {
>  	int irq, pos0, i;
> -	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
> +	struct pcie_port *pp = desc->dev->bus->sysdata;
>  
>  	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
>  				       order_base_2(no_irqs));
> @@ -298,7 +292,7 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
>  {
>  	int irq, pos;
>  	struct msi_msg msg;
> -	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
> +	struct pcie_port *pp = pdev->bus->sysdata;
>  
>  	if (desc->msi_attrib.is_msix)
>  		return -EINVAL;
> @@ -327,7 +321,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
>  {
>  	struct irq_data *data = irq_get_irq_data(irq);
>  	struct msi_desc *msi = irq_data_get_msi(data);
> -	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
> +	struct pcie_port *pp = msi->dev->bus->sysdata;
>  
>  	clear_irq_range(pp, irq, 1, data->hwirq);
>  }
> @@ -359,22 +353,17 @@ static const struct irq_domain_ops msi_domain_ops = {
>  	.map = dw_pcie_msi_map,
>  };
>  
> -int dw_pcie_host_init(struct pcie_port *pp)
> +int __init dw_pcie_host_init(struct pcie_port *pp)
>  {
>  	struct device_node *np = pp->dev->of_node;
>  	struct platform_device *pdev = to_platform_device(pp->dev);
> -	struct of_pci_range range;
> -	struct of_pci_range_parser parser;
> +	struct pci_bus *bus;
>  	struct resource *cfg_res;
> -	u32 val, na, ns;
> -	const __be32 *addrp;
> -	int i, index, ret;
> -
> -	/* Find the address cell size and the number of cells in order to get
> -	 * the untranslated address.
> -	 */
> -	of_property_read_u32(np, "#address-cells", &na);
> -	ns = of_n_size_cells(np);
> +	LIST_HEAD(res);
> +	u32 val;
> +	int i, ret;
> +	struct resource_entry *win;
> +	static int root_bus_nr = 0;
>  
>  	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
>  	if (cfg_res) {
> @@ -382,85 +371,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  		pp->cfg1_size = resource_size(cfg_res)/2;
>  		pp->cfg0_base = cfg_res->start;
>  		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
> -
> -		/* Find the untranslated configuration space address */
> -		index = of_property_match_string(np, "reg-names", "config");
> -		addrp = of_get_address(np, index, NULL, NULL);
> -		pp->cfg0_mod_base = of_read_number(addrp, ns);
> -		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
>  	} else {
>  		dev_err(pp->dev, "missing *config* reg space\n");
>  	}
>  
> -	if (of_pci_range_parser_init(&parser, np)) {
> -		dev_err(pp->dev, "missing ranges property\n");
> -		return -EINVAL;
> -	}
> +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
> +	if (ret)
> +		return ret;
>  
>  	/* Get the I/O and memory ranges from DT */
> -	for_each_of_pci_range(&parser, &range) {
> -		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
> -
> -		if (restype == IORESOURCE_IO) {
> -			of_pci_range_to_resource(&range, np, &pp->io);
> -			pp->io.name = "I/O";
> -			pp->io.start = max_t(resource_size_t,
> -					     PCIBIOS_MIN_IO,
> -					     range.pci_addr + global_io_offset);
> -			pp->io.end = min_t(resource_size_t,
> -					   IO_SPACE_LIMIT,
> -					   range.pci_addr + range.size
> -					   + global_io_offset - 1);
> -			pp->io_size = resource_size(&pp->io);
> -			pp->io_bus_addr = range.pci_addr;
> -			pp->io_base = range.cpu_addr;
> -
> -			/* Find the untranslated IO space address */
> -			pp->io_mod_base = range.cpu_addr;
> -		}
> -		if (restype == IORESOURCE_MEM) {
> -			of_pci_range_to_resource(&range, np, &pp->mem);
> -			pp->mem.name = "MEM";
> -			pp->mem_size = resource_size(&pp->mem);
> -			pp->mem_bus_addr = range.pci_addr;
> -
> -			/* Find the untranslated MEM space address */
> -			pp->mem_mod_base = range.cpu_addr;
> -		}
> -		if (restype == 0) {
> -			of_pci_range_to_resource(&range, np, &pp->cfg);
> -			pp->cfg0_size = resource_size(&pp->cfg)/2;
> -			pp->cfg1_size = resource_size(&pp->cfg)/2;
> -			pp->cfg0_base = pp->cfg.start;
> -			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
> -
> -			/* Find the untranslated configuration space address */
> -			pp->cfg0_mod_base = range.cpu_addr;
> -			pp->cfg1_mod_base = pp->cfg0_mod_base +
> -					    pp->cfg0_size;
> +	resource_list_for_each_entry(win, &res) {
> +		switch (resource_type(win->res)) {
> +		case IORESOURCE_IO:
> +			pp->io = win->res;
> +			pp->io->name = "I/O";
> +			pp->io_size = resource_size(pp->io);
> +			pp->io_bus_addr = pp->io->start - win->offset;
> +			ret = pci_remap_iospace(pp->io, pp->io_base);
> +			if (ret) {
> +				dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
> +					 ret, pp->io);
> +				continue;
> +			}
> +			break;
> +		case IORESOURCE_MEM:
> +			pp->mem = win->res;
> +			pp->mem->name = "MEM";
> +			pp->mem_size = resource_size(pp->mem);
> +			pp->mem_bus_addr = pp->mem->start - win->offset;
> +			break;
> +		case 0:
> +			pp->cfg = win->res;
> +			pp->cfg0_size = resource_size(pp->cfg)/2;
> +			pp->cfg1_size = resource_size(pp->cfg)/2;
> +			pp->cfg0_base = pp->cfg->start;
> +			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
> +			break;
> +		case IORESOURCE_BUS:
> +			pp->busn = win->res;
> +			break;
> +		default:
> +			continue;
>  		}
>  	}
>  
> -	ret = of_pci_parse_bus_range(np, &pp->busn);
> -	if (ret < 0) {
> -		pp->busn.name = np->name;
> -		pp->busn.start = 0;
> -		pp->busn.end = 0xff;
> -		pp->busn.flags = IORESOURCE_BUS;
> -		dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n",
> -			ret, &pp->busn);
> -	}
> -
>  	if (!pp->dbi_base) {
> -		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
> -					resource_size(&pp->cfg));
> +		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
> +					resource_size(pp->cfg));
>  		if (!pp->dbi_base) {
>  			dev_err(pp->dev, "error with ioremap\n");
>  			return -ENOMEM;
>  		}
>  	}
>  
> -	pp->mem_base = pp->mem.start;
> +	pp->mem_base = pp->mem->start;
>  
>  	if (!pp->va_cfg0_base) {
>  		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
> @@ -509,7 +473,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  
>  	if (!pp->ops->rd_other_conf)
>  		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
> -					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
> +					  PCIE_ATU_TYPE_MEM, pp->mem_base,
>  					  pp->mem_bus_addr, pp->mem_size);
>  
>  	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
> @@ -521,15 +485,40 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  	val |= PORT_LOGIC_SPEED_CHANGE;
>  	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
>  
> -#ifdef CONFIG_PCI_MSI
>  	dw_pcie_msi_chip.dev = pp->dev;
> -	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> +
> +	mutex_lock(&root_bus_nr_mux);
> +
> +	if (pp->root_bus_nr != DW_ROOT_NR_UNDEFINED)
> +		root_bus_nr = pp->root_bus_nr;
> +
> +	bus = pci_create_root_bus(pp->dev, root_bus_nr, &dw_pcie_ops,
> +			      pp, &res);
> +	if (!bus) {
> +		mutex_unlock(&root_bus_nr_mux);
> +		return -ENOMEM;
> +	}
> +
> +	root_bus_nr += bus->busn_res.end + 1;
> +	mutex_unlock(&root_bus_nr_mux);
> +
> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> +	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
> +#else
> +	bus->msi = &dw_pcie_msi_chip;
>  #endif
>  
> -	dw_pci.nr_controllers = 1;
> -	dw_pci.private_data = (void **)&pp;
> +	pci_scan_child_bus(bus);
> +	if (pp->ops->scan_bus)
> +		pp->ops->scan_bus(pp);
> +
> +#ifdef CONFIG_ARM
> +	/* support old dtbs that incorrectly describe IRQs */
> +	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
> +#endif
>  
> -	pci_common_init_dev(pp->dev, &dw_pci);
> +	pci_assign_unassigned_bus_resources(bus);
> +	pci_bus_add_devices(bus);
>  
>  	return 0;
>  }
> @@ -548,12 +537,12 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  
>  	if (bus->parent->number == pp->root_bus_nr) {
>  		type = PCIE_ATU_TYPE_CFG0;
> -		cpu_addr = pp->cfg0_mod_base;
> +		cpu_addr = pp->cfg0_base;
>  		cfg_size = pp->cfg0_size;
>  		va_cfg_base = pp->va_cfg0_base;
>  	} else {
>  		type = PCIE_ATU_TYPE_CFG1;
> -		cpu_addr = pp->cfg1_mod_base;
> +		cpu_addr = pp->cfg1_base;
>  		cfg_size = pp->cfg1_size;
>  		va_cfg_base = pp->va_cfg1_base;
>  	}
> @@ -563,7 +552,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  				  busdev, cfg_size);
>  	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
>  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> +				  PCIE_ATU_TYPE_IO, pp->io_base,
>  				  pp->io_bus_addr, pp->io_size);
>  
>  	return ret;
> @@ -583,12 +572,12 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  
>  	if (bus->parent->number == pp->root_bus_nr) {
>  		type = PCIE_ATU_TYPE_CFG0;
> -		cpu_addr = pp->cfg0_mod_base;
> +		cpu_addr = pp->cfg0_base;
>  		cfg_size = pp->cfg0_size;
>  		va_cfg_base = pp->va_cfg0_base;
>  	} else {
>  		type = PCIE_ATU_TYPE_CFG1;
> -		cpu_addr = pp->cfg1_mod_base;
> +		cpu_addr = pp->cfg1_base;
>  		cfg_size = pp->cfg1_size;
>  		va_cfg_base = pp->va_cfg1_base;
>  	}
> @@ -598,7 +587,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  				  busdev, cfg_size);
>  	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
>  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> +				  PCIE_ATU_TYPE_IO, pp->io_base,
>  				  pp->io_bus_addr, pp->io_size);
>  
>  	return ret;
> @@ -630,7 +619,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
>  static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
>  			int size, u32 *val)
>  {
> -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> +	struct pcie_port *pp = bus->sysdata;
>  	int ret;
>  
>  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
> @@ -654,7 +643,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
>  static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
>  			int where, int size, u32 val)
>  {
> -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> +	struct pcie_port *pp = bus->sysdata;
>  	int ret;
>  
>  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
> @@ -678,62 +667,6 @@ static struct pci_ops dw_pcie_ops = {
>  	.write = dw_pcie_wr_conf,
>  };
>  
> -static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
> -{
> -	struct pcie_port *pp;
> -
> -	pp = sys_to_pcie(sys);
> -
> -	if (global_io_offset < SZ_1M && pp->io_size > 0) {
> -		sys->io_offset = global_io_offset - pp->io_bus_addr;
> -		pci_ioremap_io(global_io_offset, pp->io_base);
> -		global_io_offset += SZ_64K;
> -		pci_add_resource_offset(&sys->resources, &pp->io,
> -					sys->io_offset);
> -	}
> -
> -	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
> -	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
> -	pci_add_resource(&sys->resources, &pp->busn);
> -
> -	return 1;
> -}
> -
> -static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
> -{
> -	struct pci_bus *bus;
> -	struct pcie_port *pp = sys_to_pcie(sys);
> -
> -	pp->root_bus_nr = sys->busnr;
> -	bus = pci_scan_root_bus(pp->dev, sys->busnr,
> -				  &dw_pcie_ops, sys, &sys->resources);
> -	if (!bus)
> -		return NULL;
> -
> -	if (bus && pp->ops->scan_bus)
> -		pp->ops->scan_bus(pp);
> -
> -	return bus;
> -}
> -
> -static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> -{
> -	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
> -	int irq;
> -
> -	irq = of_irq_parse_and_map_pci(dev, slot, pin);
> -	if (!irq)
> -		irq = pp->irq;
> -
> -	return irq;
> -}
> -
> -static struct hw_pci dw_pci = {
> -	.setup		= dw_pcie_setup,
> -	.scan		= dw_pcie_scan_bus,
> -	.map_irq	= dw_pcie_map_irq,
> -};
> -
>  void dw_pcie_setup_rc(struct pcie_port *pp)
>  {
>  	u32 val;
> diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
> index d0bbd27..0c2a7eb 100644
> --- a/drivers/pci/host/pcie-designware.h
> +++ b/drivers/pci/host/pcie-designware.h
> @@ -21,31 +21,28 @@
>   */
>  #define MAX_MSI_IRQS			32
>  #define MAX_MSI_CTRLS			(MAX_MSI_IRQS / 32)
> +#define DW_ROOT_NR_UNDEFINED	-1
>  
>  struct pcie_port {
>  	struct device		*dev;
>  	u8			root_bus_nr;
>  	void __iomem		*dbi_base;
>  	u64			cfg0_base;
> -	u64			cfg0_mod_base;
>  	void __iomem		*va_cfg0_base;
>  	u32			cfg0_size;
>  	u64			cfg1_base;
> -	u64			cfg1_mod_base;
>  	void __iomem		*va_cfg1_base;
>  	u32			cfg1_size;
> -	u64			io_base;
> -	u64			io_mod_base;
> +	resource_size_t		io_base;
>  	phys_addr_t		io_bus_addr;
>  	u32			io_size;
>  	u64			mem_base;
> -	u64			mem_mod_base;
>  	phys_addr_t		mem_bus_addr;
>  	u32			mem_size;
> -	struct resource		cfg;
> -	struct resource		io;
> -	struct resource		mem;
> -	struct resource		busn;
> +	struct resource		*cfg;
> +	struct resource		*io;
> +	struct resource		*mem;
> +	struct resource		*busn;
>  	int			irq;
>  	u32			lanes;
>  	struct pcie_host_ops	*ops;
> diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
> index c49fbdc..b2c59b9 100644
> --- a/drivers/pci/host/pcie-spear13xx.c
> +++ b/drivers/pci/host/pcie-spear13xx.c
> @@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
>  		return ret;
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
>  	pp->ops = &spear13xx_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> -- 
> 1.9.1
> 
> 
> > -----Original Message-----
> > From: Lucas Stach [mailto:l.stach@pengutronix.de]
> > Sent: Wednesday, August 19, 2015 1:54 PM
> > To: Wangzhou (B)
> > Cc: Bjorn Helgaas; jingoohan1@gmail.com; Pratyush Anand; Arnd Bergmann;
> > linux@arm.linux.org.uk; thomas.petazzoni@free-electrons.com; Gabriele
> > Paoloni; lorenzo.pieralisi@arm.com; james.morse@arm.com;
> > Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org; linux-
> > pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> > devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > 
> > Am Montag, den 17.08.2015, 19:55 +0800 schrieb Zhou Wang:
> > > This patch tries to unify ARM32 and ARM64 PCIe in designware driver.
> > Delete
> > > function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct
> > hw_pci,
> > > move related operations to dw_pcie_host_init.
> > >
> > > In past, we use:
> > > pci_common_init_dev
> > > 	-> pcibios_init_hw
> > > 		-> hw->scan (dw_pcie_scan_bus)
> > > to pass 0 to root_bus_nr in struct pcie_port. This patch set pp-
> > >root_bus_nr = 0
> > > in each PCIe host driver which is based on pcie-designware.
> > >
> > This is incorrect at least if there are 2 instances of DW PCIe host in
> > the same SoC without using PCI domains. In that the case the bus range
> > determines the range of valid bus numbers per instance and the first
> > number is the root bus. Please look at the "bus-range" DT property in
> > the DW PCIe bindings.
> > 
> > Also we should finally remove this root-bus setup from the glue drivers
> > altogether. It's something that entirely belongs into the DW core code.
> > 
> > Regards,
> > Lucas
> > 
> > > This patch also try to use of_pci_get_host_bridge_resources for ARM32
> > and ARM64
> > > according to the suggestion for Gabriele[1]
> > >
> > > Finally this patch reverts commit f4c55c5a3f7f "PCI: designware:
> > Program ATU
> > > with untranslated address" based on 1/6 in this series. we delete
> > *_mod_base in
> > > pcie-designware. This was discussed in [2]
> > >
> > > I have compiled the driver with multi_v7_defconfig. However, I don't
> > have
> > > ARM32 PCIe related board to do test. It will be appreciated if
> > someone could
> > > help to test it.
> > >
> > > Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> > > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> > > Tested-By: James Morse <james.morse@arm.com>
> > >
> > > [1] http://www.spinics.net/lists/linux-pci/msg42194.html
> > > [2] http://www.spinics.net/lists/arm-kernel/msg436779.html
> > > ---
> > >  drivers/pci/host/pci-dra7xx.c      |  15 +--
> > >  drivers/pci/host/pci-exynos.c      |   2 +-
> > >  drivers/pci/host/pci-imx6.c        |   2 +-
> > >  drivers/pci/host/pci-keystone-dw.c |   2 +-
> > >  drivers/pci/host/pci-keystone.c    |   2 +-
> > >  drivers/pci/host/pci-layerscape.c  |   2 +-
> > >  drivers/pci/host/pcie-designware.c | 229 ++++++++++++---------------
> > ----------
> > >  drivers/pci/host/pcie-designware.h |  14 +--
> > >  drivers/pci/host/pcie-spear13xx.c  |   2 +-
> > >  9 files changed, 95 insertions(+), 175 deletions(-)
> > >
> > > diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-
> > dra7xx.c
> > > index 18ae7ff..1268c69 100644
> > > --- a/drivers/pci/host/pci-dra7xx.c
> > > +++ b/drivers/pci/host/pci-dra7xx.c
> > > @@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct
> > pcie_port *pp)
> > >  {
> > >  	dw_pcie_setup_rc(pp);
> > >
> > > -	if (pp->io_mod_base)
> > > -		pp->io_mod_base &= CPU_TO_BUS_ADDR;
> > > +	if (pp->io_base)
> > > +		pp->io_base &= CPU_TO_BUS_ADDR;
> > >
> > > -	if (pp->mem_mod_base)
> > > -		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
> > > +	if (pp->mem_base)
> > > +		pp->mem_base &= CPU_TO_BUS_ADDR;
> > >
> > > -	if (pp->cfg0_mod_base) {
> > > -		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
> > > -		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
> > > +	if (pp->cfg0_base) {
> > > +		pp->cfg0_base &= CPU_TO_BUS_ADDR;
> > > +		pp->cfg1_base &= CPU_TO_BUS_ADDR;
> > >  	}
> > >
> > >  	dra7xx_pcie_establish_link(pp);
> > > @@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct
> > dra7xx_pcie *dra7xx,
> > >
> > >  	pp = &dra7xx->pp;
> > >  	pp->dev = dev;
> > > +	pp->root_bus_nr = 0;
> > >  	pp->ops = &dra7xx_pcie_host_ops;
> > >
> > >  	pp->irq = platform_get_irq(pdev, 1);
> > > diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-
> > exynos.c
> > > index f9f468d..9771bb0 100644
> > > --- a/drivers/pci/host/pci-exynos.c
> > > +++ b/drivers/pci/host/pci-exynos.c
> > > @@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct
> > pcie_port *pp,
> > >  		}
> > >  	}
> > >
> > > -	pp->root_bus_nr = -1;
> > > +	pp->root_bus_nr = 0;
> > >  	pp->ops = &exynos_pcie_host_ops;
> > >
> > >  	ret = dw_pcie_host_init(pp);
> > > diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-
> > imx6.c
> > > index 233a196..bec256c 100644
> > > --- a/drivers/pci/host/pci-imx6.c
> > > +++ b/drivers/pci/host/pci-imx6.c
> > > @@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct
> > pcie_port *pp,
> > >  		}
> > >  	}
> > >
> > > -	pp->root_bus_nr = -1;
> > > +	pp->root_bus_nr = 0;
> > >  	pp->ops = &imx6_pcie_host_ops;
> > >
> > >  	ret = dw_pcie_host_init(pp);
> > > diff --git a/drivers/pci/host/pci-keystone-dw.c
> > b/drivers/pci/host/pci-keystone-dw.c
> > > index f34892e..b1e4135 100644
> > > --- a/drivers/pci/host/pci-keystone-dw.c
> > > +++ b/drivers/pci/host/pci-keystone-dw.c
> > > @@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void
> > __iomem *reg_virt)
> > >  void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
> > >  {
> > >  	struct pcie_port *pp = &ks_pcie->pp;
> > > -	u32 start = pp->mem.start, end = pp->mem.end;
> > > +	u32 start = pp->mem->start, end = pp->mem->end;
> > >  	int i, tr_size;
> > >
> > >  	/* Disable BARs for inbound access */
> > > diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-
> > keystone.c
> > > index 734da58..8113832 100644
> > > --- a/drivers/pci/host/pci-keystone.c
> > > +++ b/drivers/pci/host/pci-keystone.c
> > > @@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct
> > keystone_pcie *ks_pcie,
> > >  			return ret;
> > >  	}
> > >
> > > -	pp->root_bus_nr = -1;
> > > +	pp->root_bus_nr = 0;
> > >  	pp->ops = &keystone_pcie_host_ops;
> > >  	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
> > >  	if (ret) {
> > > diff --git a/drivers/pci/host/pci-layerscape.c
> > b/drivers/pci/host/pci-layerscape.c
> > > index b2328ea1..79ff08c 100644
> > > --- a/drivers/pci/host/pci-layerscape.c
> > > +++ b/drivers/pci/host/pci-layerscape.c
> > > @@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
> > >  	pp = &pcie->pp;
> > >  	pp->dev = pcie->dev;
> > >  	pp->dbi_base = pcie->dbi;
> > > -	pp->root_bus_nr = -1;
> > > +	pp->root_bus_nr = 0;
> > >  	pp->ops = &ls_pcie_host_ops;
> > >
> > >  	ret = dw_pcie_host_init(pp);
> > > diff --git a/drivers/pci/host/pcie-designware.c
> > b/drivers/pci/host/pcie-designware.c
> > > index c5d407c..e71a88e 100644
> > > --- a/drivers/pci/host/pcie-designware.c
> > > +++ b/drivers/pci/host/pcie-designware.c
> > > @@ -11,6 +11,7 @@
> > >   * published by the Free Software Foundation.
> > >   */
> > >
> > > +#include <linux/hardirq.h>
> > >  #include <linux/irq.h>
> > >  #include <linux/irqdomain.h>
> > >  #include <linux/kernel.h>
> > > @@ -69,16 +70,7 @@
> > >  #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
> > >  #define PCIE_ATU_UPPER_TARGET		0x91C
> > >
> > > -static struct hw_pci dw_pci;
> > > -
> > > -static unsigned long global_io_offset;
> > > -
> > > -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
> > > -{
> > > -	BUG_ON(!sys->private_data);
> > > -
> > > -	return sys->private_data;
> > > -}
> > > +static struct pci_ops dw_pcie_ops;
> > >
> > >  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32
> > *val)
> > >  {
> > > @@ -255,7 +247,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port
> > *pp, int irq)
> > >  static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
> > >  {
> > >  	int irq, pos0, i;
> > > -	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
> > > +	struct pcie_port *pp = desc->dev->bus->sysdata;
> > >
> > >  	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
> > >  				       order_base_2(no_irqs));
> > > @@ -298,7 +290,7 @@ static int dw_msi_setup_irq(struct msi_controller
> > *chip, struct pci_dev *pdev,
> > >  {
> > >  	int irq, pos;
> > >  	struct msi_msg msg;
> > > -	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
> > > +	struct pcie_port *pp = pdev->bus->sysdata;
> > >
> > >  	if (desc->msi_attrib.is_msix)
> > >  		return -EINVAL;
> > > @@ -327,7 +319,7 @@ static void dw_msi_teardown_irq(struct
> > msi_controller *chip, unsigned int irq)
> > >  {
> > >  	struct irq_data *data = irq_get_irq_data(irq);
> > >  	struct msi_desc *msi = irq_data_get_msi(data);
> > > -	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
> > > +	struct pcie_port *pp = msi->dev->bus->sysdata;
> > >
> > >  	clear_irq_range(pp, irq, 1, data->hwirq);
> > >  }
> > > @@ -363,14 +355,12 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > >  {
> > >  	struct device_node *np = pp->dev->of_node;
> > >  	struct platform_device *pdev = to_platform_device(pp->dev);
> > > -	struct of_pci_range range;
> > > -	struct of_pci_range_parser parser;
> > > +	struct pci_bus *bus;
> > >  	struct resource *cfg_res;
> > > -	u32 val, ns;
> > > -	const __be32 *addrp;
> > > -	int i, index, ret;
> > > -
> > > -	ns = of_n_size_cells(np);
> > > +	LIST_HEAD(res);
> > > +	u32 val;
> > > +	int i, ret;
> > > +	struct resource_entry *win;
> > >
> > >  	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> > "config");
> > >  	if (cfg_res) {
> > > @@ -378,85 +368,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > >  		pp->cfg1_size = resource_size(cfg_res)/2;
> > >  		pp->cfg0_base = cfg_res->start;
> > >  		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
> > > -
> > > -		/* Find the untranslated configuration space address */
> > > -		index = of_property_match_string(np, "reg-names", "config");
> > > -		addrp = of_get_address(np, index, NULL, NULL);
> > > -		pp->cfg0_mod_base = of_read_number(addrp, ns);
> > > -		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
> > >  	} else {
> > >  		dev_err(pp->dev, "missing *config* reg space\n");
> > >  	}
> > >
> > > -	if (of_pci_range_parser_init(&parser, np)) {
> > > -		dev_err(pp->dev, "missing ranges property\n");
> > > -		return -EINVAL;
> > > -	}
> > > +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp-
> > >io_base);
> > > +	if (ret)
> > > +		return ret;
> > >
> > >  	/* Get the I/O and memory ranges from DT */
> > > -	for_each_of_pci_range(&parser, &range) {
> > > -		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
> > > -
> > > -		if (restype == IORESOURCE_IO) {
> > > -			of_pci_range_to_resource(&range, np, &pp->io);
> > > -			pp->io.name = "I/O";
> > > -			pp->io.start = max_t(resource_size_t,
> > > -					     PCIBIOS_MIN_IO,
> > > -					     range.pci_addr + global_io_offset);
> > > -			pp->io.end = min_t(resource_size_t,
> > > -					   IO_SPACE_LIMIT,
> > > -					   range.pci_addr + range.size
> > > -					   + global_io_offset - 1);
> > > -			pp->io_size = resource_size(&pp->io);
> > > -			pp->io_bus_addr = range.pci_addr;
> > > -			pp->io_base = range.cpu_addr;
> > > -
> > > -			/* Find the untranslated IO space address */
> > > -			pp->io_mod_base = range.cpu_addr;
> > > -		}
> > > -		if (restype == IORESOURCE_MEM) {
> > > -			of_pci_range_to_resource(&range, np, &pp->mem);
> > > -			pp->mem.name = "MEM";
> > > -			pp->mem_size = resource_size(&pp->mem);
> > > -			pp->mem_bus_addr = range.pci_addr;
> > > -
> > > -			/* Find the untranslated MEM space address */
> > > -			pp->mem_mod_base = range.cpu_addr;
> > > -		}
> > > -		if (restype == 0) {
> > > -			of_pci_range_to_resource(&range, np, &pp->cfg);
> > > -			pp->cfg0_size = resource_size(&pp->cfg)/2;
> > > -			pp->cfg1_size = resource_size(&pp->cfg)/2;
> > > -			pp->cfg0_base = pp->cfg.start;
> > > -			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
> > > -
> > > -			/* Find the untranslated configuration space address
> > */
> > > -			pp->cfg0_mod_base = range.cpu_addr;
> > > -			pp->cfg1_mod_base = pp->cfg0_mod_base +
> > > -					    pp->cfg0_size;
> > > +	resource_list_for_each_entry(win, &res) {
> > > +		switch (resource_type(win->res)) {
> > > +		case IORESOURCE_IO:
> > > +			pp->io = win->res;
> > > +			pp->io->name = "I/O";
> > > +			pp->io_size = resource_size(pp->io);
> > > +			pp->io_bus_addr = pp->io->start - win->offset;
> > > +			ret = pci_remap_iospace(pp->io, pp->io_base);
> > > +			if (ret) {
> > > +				dev_warn(pp->dev, "error %d: failed to map
> > resource %pR\n",
> > > +					 ret, pp->io);
> > > +				continue;
> > > +			}
> > > +			break;
> > > +		case IORESOURCE_MEM:
> > > +			pp->mem = win->res;
> > > +			pp->mem->name = "MEM";
> > > +			pp->mem_size = resource_size(pp->mem);
> > > +			pp->mem_bus_addr = pp->mem->start - win->offset;
> > > +			break;
> > > +		case 0:
> > > +			pp->cfg = win->res;
> > > +			pp->cfg0_size = resource_size(pp->cfg)/2;
> > > +			pp->cfg1_size = resource_size(pp->cfg)/2;
> > > +			pp->cfg0_base = pp->cfg->start;
> > > +			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
> > > +			break;
> > > +		case IORESOURCE_BUS:
> > > +			pp->busn = win->res;
> > > +			break;
> > > +		default:
> > > +			continue;
> > >  		}
> > >  	}
> > >
> > > -	ret = of_pci_parse_bus_range(np, &pp->busn);
> > > -	if (ret < 0) {
> > > -		pp->busn.name = np->name;
> > > -		pp->busn.start = 0;
> > > -		pp->busn.end = 0xff;
> > > -		pp->busn.flags = IORESOURCE_BUS;
> > > -		dev_dbg(pp->dev, "failed to parse bus-range property: %d,
> > using default %pR\n",
> > > -			ret, &pp->busn);
> > > -	}
> > > -
> > >  	if (!pp->dbi_base) {
> > > -		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
> > > -					resource_size(&pp->cfg));
> > > +		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
> > > +					resource_size(pp->cfg));
> > >  		if (!pp->dbi_base) {
> > >  			dev_err(pp->dev, "error with ioremap\n");
> > >  			return -ENOMEM;
> > >  		}
> > >  	}
> > >
> > > -	pp->mem_base = pp->mem.start;
> > > +	pp->mem_base = pp->mem->start;
> > >
> > >  	if (!pp->va_cfg0_base) {
> > >  		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
> > > @@ -505,7 +470,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > >
> > >  	if (!pp->ops->rd_other_conf)
> > >  		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
> > > -					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
> > > +					  PCIE_ATU_TYPE_MEM, pp->mem_base,
> > >  					  pp->mem_bus_addr, pp->mem_size);
> > >
> > >  	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
> > > @@ -517,15 +482,29 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > >  	val |= PORT_LOGIC_SPEED_CHANGE;
> > >  	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
> > >
> > > -#ifdef CONFIG_PCI_MSI
> > > +	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
> > > +				  pp, &res);
> > > +	if (!bus)
> > > +		return -ENOMEM;
> > > +
> > > +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> > > +	bus->msi = container_of(&pp->irq_domain, struct msi_controller,
> > domain);
> > > +#else
> > >  	dw_pcie_msi_chip.dev = pp->dev;
> > > -	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> > > +	bus->msi = &dw_pcie_msi_chip;
> > >  #endif
> > >
> > > -	dw_pci.nr_controllers = 1;
> > > -	dw_pci.private_data = (void **)&pp;
> > > +	pci_scan_child_bus(bus);
> > > +	if (pp->ops->scan_bus)
> > > +		pp->ops->scan_bus(pp);
> > > +
> > > +#ifdef CONFIG_ARM
> > > +	/* support old dtbs that incorrectly describe IRQs */
> > > +	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
> > > +#endif
> > >
> > > -	pci_common_init_dev(pp->dev, &dw_pci);
> > > +	pci_assign_unassigned_bus_resources(bus);
> > > +	pci_bus_add_devices(bus);
> > >
> > >  	return 0;
> > >  }
> > > @@ -544,12 +523,12 @@ static int dw_pcie_rd_other_conf(struct
> > pcie_port *pp, struct pci_bus *bus,
> > >
> > >  	if (bus->parent->number == pp->root_bus_nr) {
> > >  		type = PCIE_ATU_TYPE_CFG0;
> > > -		cpu_addr = pp->cfg0_mod_base;
> > > +		cpu_addr = pp->cfg0_base;
> > >  		cfg_size = pp->cfg0_size;
> > >  		va_cfg_base = pp->va_cfg0_base;
> > >  	} else {
> > >  		type = PCIE_ATU_TYPE_CFG1;
> > > -		cpu_addr = pp->cfg1_mod_base;
> > > +		cpu_addr = pp->cfg1_base;
> > >  		cfg_size = pp->cfg1_size;
> > >  		va_cfg_base = pp->va_cfg1_base;
> > >  	}
> > > @@ -559,7 +538,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port
> > *pp, struct pci_bus *bus,
> > >  				  busdev, cfg_size);
> > >  	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
> > >  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> > > -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> > > +				  PCIE_ATU_TYPE_IO, pp->io_base,
> > >  				  pp->io_bus_addr, pp->io_size);
> > >
> > >  	return ret;
> > > @@ -579,12 +558,12 @@ static int dw_pcie_wr_other_conf(struct
> > pcie_port *pp, struct pci_bus *bus,
> > >
> > >  	if (bus->parent->number == pp->root_bus_nr) {
> > >  		type = PCIE_ATU_TYPE_CFG0;
> > > -		cpu_addr = pp->cfg0_mod_base;
> > > +		cpu_addr = pp->cfg0_base;
> > >  		cfg_size = pp->cfg0_size;
> > >  		va_cfg_base = pp->va_cfg0_base;
> > >  	} else {
> > >  		type = PCIE_ATU_TYPE_CFG1;
> > > -		cpu_addr = pp->cfg1_mod_base;
> > > +		cpu_addr = pp->cfg1_base;
> > >  		cfg_size = pp->cfg1_size;
> > >  		va_cfg_base = pp->va_cfg1_base;
> > >  	}
> > > @@ -594,7 +573,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port
> > *pp, struct pci_bus *bus,
> > >  				  busdev, cfg_size);
> > >  	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
> > >  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> > > -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> > > +				  PCIE_ATU_TYPE_IO, pp->io_base,
> > >  				  pp->io_bus_addr, pp->io_size);
> > >
> > >  	return ret;
> > > @@ -626,7 +605,7 @@ static int dw_pcie_valid_config(struct pcie_port
> > *pp,
> > >  static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> > >  			int size, u32 *val)
> > >  {
> > > -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> > > +	struct pcie_port *pp = bus->sysdata;
> > >  	int ret;
> > >
> > >  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
> > > @@ -650,7 +629,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus,
> > u32 devfn, int where,
> > >  static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
> > >  			int where, int size, u32 val)
> > >  {
> > > -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> > > +	struct pcie_port *pp = bus->sysdata;
> > >  	int ret;
> > >
> > >  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
> > > @@ -674,62 +653,6 @@ static struct pci_ops dw_pcie_ops = {
> > >  	.write = dw_pcie_wr_conf,
> > >  };
> > >
> > > -static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
> > > -{
> > > -	struct pcie_port *pp;
> > > -
> > > -	pp = sys_to_pcie(sys);
> > > -
> > > -	if (global_io_offset < SZ_1M && pp->io_size > 0) {
> > > -		sys->io_offset = global_io_offset - pp->io_bus_addr;
> > > -		pci_ioremap_io(global_io_offset, pp->io_base);
> > > -		global_io_offset += SZ_64K;
> > > -		pci_add_resource_offset(&sys->resources, &pp->io,
> > > -					sys->io_offset);
> > > -	}
> > > -
> > > -	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
> > > -	pci_add_resource_offset(&sys->resources, &pp->mem, sys-
> > >mem_offset);
> > > -	pci_add_resource(&sys->resources, &pp->busn);
> > > -
> > > -	return 1;
> > > -}
> > > -
> > > -static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data
> > *sys)
> > > -{
> > > -	struct pci_bus *bus;
> > > -	struct pcie_port *pp = sys_to_pcie(sys);
> > > -
> > > -	pp->root_bus_nr = sys->busnr;
> > > -	bus = pci_scan_root_bus(pp->dev, sys->busnr,
> > > -				  &dw_pcie_ops, sys, &sys->resources);
> > > -	if (!bus)
> > > -		return NULL;
> > > -
> > > -	if (bus && pp->ops->scan_bus)
> > > -		pp->ops->scan_bus(pp);
> > > -
> > > -	return bus;
> > > -}
> > > -
> > > -static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8
> > pin)
> > > -{
> > > -	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
> > > -	int irq;
> > > -
> > > -	irq = of_irq_parse_and_map_pci(dev, slot, pin);
> > > -	if (!irq)
> > > -		irq = pp->irq;
> > > -
> > > -	return irq;
> > > -}
> > > -
> > > -static struct hw_pci dw_pci = {
> > > -	.setup		= dw_pcie_setup,
> > > -	.scan		= dw_pcie_scan_bus,
> > > -	.map_irq	= dw_pcie_map_irq,
> > > -};
> > > -
> > >  void dw_pcie_setup_rc(struct pcie_port *pp)
> > >  {
> > >  	u32 val;
> > > diff --git a/drivers/pci/host/pcie-designware.h
> > b/drivers/pci/host/pcie-designware.h
> > > index d0bbd27..264c969 100644
> > > --- a/drivers/pci/host/pcie-designware.h
> > > +++ b/drivers/pci/host/pcie-designware.h
> > > @@ -27,25 +27,21 @@ struct pcie_port {
> > >  	u8			root_bus_nr;
> > >  	void __iomem		*dbi_base;
> > >  	u64			cfg0_base;
> > > -	u64			cfg0_mod_base;
> > >  	void __iomem		*va_cfg0_base;
> > >  	u32			cfg0_size;
> > >  	u64			cfg1_base;
> > > -	u64			cfg1_mod_base;
> > >  	void __iomem		*va_cfg1_base;
> > >  	u32			cfg1_size;
> > > -	u64			io_base;
> > > -	u64			io_mod_base;
> > > +	resource_size_t		io_base;
> > >  	phys_addr_t		io_bus_addr;
> > >  	u32			io_size;
> > >  	u64			mem_base;
> > > -	u64			mem_mod_base;
> > >  	phys_addr_t		mem_bus_addr;
> > >  	u32			mem_size;
> > > -	struct resource		cfg;
> > > -	struct resource		io;
> > > -	struct resource		mem;
> > > -	struct resource		busn;
> > > +	struct resource		*cfg;
> > > +	struct resource		*io;
> > > +	struct resource		*mem;
> > > +	struct resource		*busn;
> > >  	int			irq;
> > >  	u32			lanes;
> > >  	struct pcie_host_ops	*ops;
> > > diff --git a/drivers/pci/host/pcie-spear13xx.c
> > b/drivers/pci/host/pcie-spear13xx.c
> > > index c49fbdc..03eb204 100644
> > > --- a/drivers/pci/host/pcie-spear13xx.c
> > > +++ b/drivers/pci/host/pcie-spear13xx.c
> > > @@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct
> > pcie_port *pp,
> > >  		return ret;
> > >  	}
> > >
> > > -	pp->root_bus_nr = -1;
> > > +	pp->root_bus_nr = 0;
> > >  	pp->ops = &spear13xx_pcie_host_ops;
> > >
> > >  	ret = dw_pcie_host_init(pp);
> > 
> > --
> > Pengutronix e.K.             | Lucas Stach                 |
> > Industrial Linux Solutions   | http://www.pengutronix.de/  |
> 

-- 
Pengutronix e.K.             | Lucas Stach                 |
Industrial Linux Solutions   | http://www.pengutronix.de/  |


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

* [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-19 15:37         ` Lucas Stach
  0 siblings, 0 replies; 53+ messages in thread
From: Lucas Stach @ 2015-08-19 15:37 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Gab,

Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele Paoloni:
> Hi Lucas
> 
> I have rewritten the patch to take into account multiple controllers.
> 
> As you can see now there is a static var in dw_pcie_host_init() that tracks
> the bus numbers used.

This is wrong. The DT specifies the valid bus number range. You can not
just assign the next free bus number to the root bus.

It is perfectly valid to have a bus range of 0x00-0x10 assigned to one
instance and 0x50-0xff to the next instance. Additional with PCIe
hotplug you may not use the full range of the bus numbers on one
instance at the first scan, but only later populate more buses when more
bridges are added to the tree.

> Drivers that do not specify the bus range in the DTB set pp->root_bus_nr = DW_ROOT_NR_UNDEFINED.
> Designware will check if the flag is set and will use the automatic bus range
> assignment.

No, please lets get rid of this assignment altogether. The glue drivers
have no business in assigning the bus range. Please remove the
pp->root_bus_nr assignment from all the glue drivers.

"bus range" is a generic DW PCIe property, so just parse the root bus
number from the DT, it is handled the same way for all the DW based PCIe
drivers. The bindings specifies that if the bus range property is
missing the range is 0x00-0xff, so you can default to 0 as the root bus
number in that case.

Also I would think this conversion warrants a patch on its own and
should not be mixed in the ARM64 support patch.

Regards,
Lucas

> Instead if the driver assigns pp->root_bus_nr according to the dtb, designwware
> will use the value passed in by the driver.
> Below the relevant section:
> 
> 
> +	static int root_bus_nr = 0;
> ...
> +	mutex_lock(&root_bus_nr_mux);
> +
> +	if (pp->root_bus_nr != DW_ROOT_NR_UNDEFINED)
> +		root_bus_nr = pp->root_bus_nr;
> +
> +	bus = pci_create_root_bus(pp->dev, root_bus_nr, &dw_pcie_ops,
> +			      pp, &res);
> +	if (!bus) {
> +		mutex_unlock(&root_bus_nr_mux);
> +		return -ENOMEM;
> +	}
> +
> +	root_bus_nr += bus->busn_res.end + 1;
> +	mutex_unlock(&root_bus_nr_mux);
> 
> Please let me know what you think...
> 
> Many Thanks
> 
> Gab
> ----------
> 
> From: gabriele paoloni <gabriele.paoloni@huawei.com>
> 
> This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete
> function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci,
> move related operations to dw_pcie_host_init.
> Also set pp->root_bus_nr = DW_ROOT_NR_UNDEFINED in all the drivers that
> are based on designware to flag that the drivers do not read the bus
> ranges from DT.
> This patch also adds handling of multiple PCI domains in designware.
> if the PCI host bridge driver does not specify a root bus number, in case
> of multiple domains, designware will automatillay set the next domain root
> bus number to the last bus number used in the last domain + 1.
> 
> This patch also try to use of_pci_get_host_bridge_resources for ARM32 and
> ARM64 according to the suggestion for Gabriele[1]
> 
> This patch is based on Gabriele's patch about of_pci_range fix[2]
> 
> Finally this patch reverts commit f4c55c5a3f7f "PCI: designware:
> Program ATU with untranslated address". This was discussed in [3]
> 
> I have compiled the driver with multi_v7_defconfig. However, I don't have
> ARM32 PCIe related board to do test. It will be appreciated if someone could
> help to test it.
> 
> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> 
> [1] http://www.spinics.net/lists/linux-pci/msg42194.html
> [2] https://patchwork.ozlabs.org/patch/495018/
> [3] http://www.spinics.net/lists/arm-kernel/msg436779.html
> ---
>  drivers/pci/host/pci-dra7xx.c      |  15 +--
>  drivers/pci/host/pci-exynos.c      |   2 +-
>  drivers/pci/host/pci-imx6.c        |   2 +-
>  drivers/pci/host/pci-keystone-dw.c |   2 +-
>  drivers/pci/host/pci-keystone.c    |   2 +-
>  drivers/pci/host/pci-layerscape.c  |   2 +-
>  drivers/pci/host/pcie-designware.c | 247 ++++++++++++++-----------------------
>  drivers/pci/host/pcie-designware.h |  15 +--
>  drivers/pci/host/pcie-spear13xx.c  |   2 +-
>  9 files changed, 110 insertions(+), 179 deletions(-)
> 
> diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
> index 5678b57..8d598fb 100644
> --- a/drivers/pci/host/pci-dra7xx.c
> +++ b/drivers/pci/host/pci-dra7xx.c
> @@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp)
>  {
>  	dw_pcie_setup_rc(pp);
>  
> -	if (pp->io_mod_base)
> -		pp->io_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->io_base)
> +		pp->io_base &= CPU_TO_BUS_ADDR;
>  
> -	if (pp->mem_mod_base)
> -		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->mem_base)
> +		pp->mem_base &= CPU_TO_BUS_ADDR;
>  
> -	if (pp->cfg0_mod_base) {
> -		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
> -		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
> +	if (pp->cfg0_base) {
> +		pp->cfg0_base &= CPU_TO_BUS_ADDR;
> +		pp->cfg1_base &= CPU_TO_BUS_ADDR;
>  	}
>  
>  	dra7xx_pcie_establish_link(pp);
> @@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
>  
>  	pp = &dra7xx->pp;
>  	pp->dev = dev;
> +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
>  	pp->ops = &dra7xx_pcie_host_ops;
>  
>  	pp->irq = platform_get_irq(pdev, 1);
> diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
> index f9f468d..ed03a8f 100644
> --- a/drivers/pci/host/pci-exynos.c
> +++ b/drivers/pci/host/pci-exynos.c
> @@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
>  		}
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
>  	pp->ops = &exynos_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
> index 233a196..0efac85 100644
> --- a/drivers/pci/host/pci-imx6.c
> +++ b/drivers/pci/host/pci-imx6.c
> @@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
>  		}
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
>  	pp->ops = &imx6_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c
> index f34892e..b1e4135 100644
> --- a/drivers/pci/host/pci-keystone-dw.c
> +++ b/drivers/pci/host/pci-keystone-dw.c
> @@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void __iomem *reg_virt)
>  void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
>  {
>  	struct pcie_port *pp = &ks_pcie->pp;
> -	u32 start = pp->mem.start, end = pp->mem.end;
> +	u32 start = pp->mem->start, end = pp->mem->end;
>  	int i, tr_size;
>  
>  	/* Disable BARs for inbound access */
> diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
> index 734da58..b522956 100644
> --- a/drivers/pci/host/pci-keystone.c
> +++ b/drivers/pci/host/pci-keystone.c
> @@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
>  			return ret;
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
>  	pp->ops = &keystone_pcie_host_ops;
>  	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
>  	if (ret) {
> diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
> index b2328ea1..dd92ffa 100644
> --- a/drivers/pci/host/pci-layerscape.c
> +++ b/drivers/pci/host/pci-layerscape.c
> @@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
>  	pp = &pcie->pp;
>  	pp->dev = pcie->dev;
>  	pp->dbi_base = pcie->dbi;
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
>  	pp->ops = &ls_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
> index 5307b35..bd2606b 100644
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c
> @@ -11,6 +11,7 @@
>   * published by the Free Software Foundation.
>   */
>  
> +#include <linux/hardirq.h>
>  #include <linux/irq.h>
>  #include <linux/irqdomain.h>
>  #include <linux/kernel.h>
> @@ -69,16 +70,9 @@
>  #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
>  #define PCIE_ATU_UPPER_TARGET		0x91C
>  
> -static struct hw_pci dw_pci;
> +static struct pci_ops dw_pcie_ops;
>  
> -static unsigned long global_io_offset;
> -
> -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
> -{
> -	BUG_ON(!sys->private_data);
> -
> -	return sys->private_data;
> -}
> +DEFINE_MUTEX(root_bus_nr_mux);
>  
>  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
>  {
> @@ -255,7 +249,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
>  static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
>  {
>  	int irq, pos0, i;
> -	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
> +	struct pcie_port *pp = desc->dev->bus->sysdata;
>  
>  	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
>  				       order_base_2(no_irqs));
> @@ -298,7 +292,7 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
>  {
>  	int irq, pos;
>  	struct msi_msg msg;
> -	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
> +	struct pcie_port *pp = pdev->bus->sysdata;
>  
>  	if (desc->msi_attrib.is_msix)
>  		return -EINVAL;
> @@ -327,7 +321,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
>  {
>  	struct irq_data *data = irq_get_irq_data(irq);
>  	struct msi_desc *msi = irq_data_get_msi(data);
> -	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
> +	struct pcie_port *pp = msi->dev->bus->sysdata;
>  
>  	clear_irq_range(pp, irq, 1, data->hwirq);
>  }
> @@ -359,22 +353,17 @@ static const struct irq_domain_ops msi_domain_ops = {
>  	.map = dw_pcie_msi_map,
>  };
>  
> -int dw_pcie_host_init(struct pcie_port *pp)
> +int __init dw_pcie_host_init(struct pcie_port *pp)
>  {
>  	struct device_node *np = pp->dev->of_node;
>  	struct platform_device *pdev = to_platform_device(pp->dev);
> -	struct of_pci_range range;
> -	struct of_pci_range_parser parser;
> +	struct pci_bus *bus;
>  	struct resource *cfg_res;
> -	u32 val, na, ns;
> -	const __be32 *addrp;
> -	int i, index, ret;
> -
> -	/* Find the address cell size and the number of cells in order to get
> -	 * the untranslated address.
> -	 */
> -	of_property_read_u32(np, "#address-cells", &na);
> -	ns = of_n_size_cells(np);
> +	LIST_HEAD(res);
> +	u32 val;
> +	int i, ret;
> +	struct resource_entry *win;
> +	static int root_bus_nr = 0;
>  
>  	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
>  	if (cfg_res) {
> @@ -382,85 +371,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  		pp->cfg1_size = resource_size(cfg_res)/2;
>  		pp->cfg0_base = cfg_res->start;
>  		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
> -
> -		/* Find the untranslated configuration space address */
> -		index = of_property_match_string(np, "reg-names", "config");
> -		addrp = of_get_address(np, index, NULL, NULL);
> -		pp->cfg0_mod_base = of_read_number(addrp, ns);
> -		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
>  	} else {
>  		dev_err(pp->dev, "missing *config* reg space\n");
>  	}
>  
> -	if (of_pci_range_parser_init(&parser, np)) {
> -		dev_err(pp->dev, "missing ranges property\n");
> -		return -EINVAL;
> -	}
> +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
> +	if (ret)
> +		return ret;
>  
>  	/* Get the I/O and memory ranges from DT */
> -	for_each_of_pci_range(&parser, &range) {
> -		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
> -
> -		if (restype == IORESOURCE_IO) {
> -			of_pci_range_to_resource(&range, np, &pp->io);
> -			pp->io.name = "I/O";
> -			pp->io.start = max_t(resource_size_t,
> -					     PCIBIOS_MIN_IO,
> -					     range.pci_addr + global_io_offset);
> -			pp->io.end = min_t(resource_size_t,
> -					   IO_SPACE_LIMIT,
> -					   range.pci_addr + range.size
> -					   + global_io_offset - 1);
> -			pp->io_size = resource_size(&pp->io);
> -			pp->io_bus_addr = range.pci_addr;
> -			pp->io_base = range.cpu_addr;
> -
> -			/* Find the untranslated IO space address */
> -			pp->io_mod_base = range.cpu_addr;
> -		}
> -		if (restype == IORESOURCE_MEM) {
> -			of_pci_range_to_resource(&range, np, &pp->mem);
> -			pp->mem.name = "MEM";
> -			pp->mem_size = resource_size(&pp->mem);
> -			pp->mem_bus_addr = range.pci_addr;
> -
> -			/* Find the untranslated MEM space address */
> -			pp->mem_mod_base = range.cpu_addr;
> -		}
> -		if (restype == 0) {
> -			of_pci_range_to_resource(&range, np, &pp->cfg);
> -			pp->cfg0_size = resource_size(&pp->cfg)/2;
> -			pp->cfg1_size = resource_size(&pp->cfg)/2;
> -			pp->cfg0_base = pp->cfg.start;
> -			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
> -
> -			/* Find the untranslated configuration space address */
> -			pp->cfg0_mod_base = range.cpu_addr;
> -			pp->cfg1_mod_base = pp->cfg0_mod_base +
> -					    pp->cfg0_size;
> +	resource_list_for_each_entry(win, &res) {
> +		switch (resource_type(win->res)) {
> +		case IORESOURCE_IO:
> +			pp->io = win->res;
> +			pp->io->name = "I/O";
> +			pp->io_size = resource_size(pp->io);
> +			pp->io_bus_addr = pp->io->start - win->offset;
> +			ret = pci_remap_iospace(pp->io, pp->io_base);
> +			if (ret) {
> +				dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
> +					 ret, pp->io);
> +				continue;
> +			}
> +			break;
> +		case IORESOURCE_MEM:
> +			pp->mem = win->res;
> +			pp->mem->name = "MEM";
> +			pp->mem_size = resource_size(pp->mem);
> +			pp->mem_bus_addr = pp->mem->start - win->offset;
> +			break;
> +		case 0:
> +			pp->cfg = win->res;
> +			pp->cfg0_size = resource_size(pp->cfg)/2;
> +			pp->cfg1_size = resource_size(pp->cfg)/2;
> +			pp->cfg0_base = pp->cfg->start;
> +			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
> +			break;
> +		case IORESOURCE_BUS:
> +			pp->busn = win->res;
> +			break;
> +		default:
> +			continue;
>  		}
>  	}
>  
> -	ret = of_pci_parse_bus_range(np, &pp->busn);
> -	if (ret < 0) {
> -		pp->busn.name = np->name;
> -		pp->busn.start = 0;
> -		pp->busn.end = 0xff;
> -		pp->busn.flags = IORESOURCE_BUS;
> -		dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n",
> -			ret, &pp->busn);
> -	}
> -
>  	if (!pp->dbi_base) {
> -		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
> -					resource_size(&pp->cfg));
> +		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
> +					resource_size(pp->cfg));
>  		if (!pp->dbi_base) {
>  			dev_err(pp->dev, "error with ioremap\n");
>  			return -ENOMEM;
>  		}
>  	}
>  
> -	pp->mem_base = pp->mem.start;
> +	pp->mem_base = pp->mem->start;
>  
>  	if (!pp->va_cfg0_base) {
>  		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
> @@ -509,7 +473,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  
>  	if (!pp->ops->rd_other_conf)
>  		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
> -					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
> +					  PCIE_ATU_TYPE_MEM, pp->mem_base,
>  					  pp->mem_bus_addr, pp->mem_size);
>  
>  	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
> @@ -521,15 +485,40 @@ int dw_pcie_host_init(struct pcie_port *pp)
>  	val |= PORT_LOGIC_SPEED_CHANGE;
>  	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
>  
> -#ifdef CONFIG_PCI_MSI
>  	dw_pcie_msi_chip.dev = pp->dev;
> -	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> +
> +	mutex_lock(&root_bus_nr_mux);
> +
> +	if (pp->root_bus_nr != DW_ROOT_NR_UNDEFINED)
> +		root_bus_nr = pp->root_bus_nr;
> +
> +	bus = pci_create_root_bus(pp->dev, root_bus_nr, &dw_pcie_ops,
> +			      pp, &res);
> +	if (!bus) {
> +		mutex_unlock(&root_bus_nr_mux);
> +		return -ENOMEM;
> +	}
> +
> +	root_bus_nr += bus->busn_res.end + 1;
> +	mutex_unlock(&root_bus_nr_mux);
> +
> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> +	bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
> +#else
> +	bus->msi = &dw_pcie_msi_chip;
>  #endif
>  
> -	dw_pci.nr_controllers = 1;
> -	dw_pci.private_data = (void **)&pp;
> +	pci_scan_child_bus(bus);
> +	if (pp->ops->scan_bus)
> +		pp->ops->scan_bus(pp);
> +
> +#ifdef CONFIG_ARM
> +	/* support old dtbs that incorrectly describe IRQs */
> +	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
> +#endif
>  
> -	pci_common_init_dev(pp->dev, &dw_pci);
> +	pci_assign_unassigned_bus_resources(bus);
> +	pci_bus_add_devices(bus);
>  
>  	return 0;
>  }
> @@ -548,12 +537,12 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  
>  	if (bus->parent->number == pp->root_bus_nr) {
>  		type = PCIE_ATU_TYPE_CFG0;
> -		cpu_addr = pp->cfg0_mod_base;
> +		cpu_addr = pp->cfg0_base;
>  		cfg_size = pp->cfg0_size;
>  		va_cfg_base = pp->va_cfg0_base;
>  	} else {
>  		type = PCIE_ATU_TYPE_CFG1;
> -		cpu_addr = pp->cfg1_mod_base;
> +		cpu_addr = pp->cfg1_base;
>  		cfg_size = pp->cfg1_size;
>  		va_cfg_base = pp->va_cfg1_base;
>  	}
> @@ -563,7 +552,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  				  busdev, cfg_size);
>  	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
>  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> +				  PCIE_ATU_TYPE_IO, pp->io_base,
>  				  pp->io_bus_addr, pp->io_size);
>  
>  	return ret;
> @@ -583,12 +572,12 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  
>  	if (bus->parent->number == pp->root_bus_nr) {
>  		type = PCIE_ATU_TYPE_CFG0;
> -		cpu_addr = pp->cfg0_mod_base;
> +		cpu_addr = pp->cfg0_base;
>  		cfg_size = pp->cfg0_size;
>  		va_cfg_base = pp->va_cfg0_base;
>  	} else {
>  		type = PCIE_ATU_TYPE_CFG1;
> -		cpu_addr = pp->cfg1_mod_base;
> +		cpu_addr = pp->cfg1_base;
>  		cfg_size = pp->cfg1_size;
>  		va_cfg_base = pp->va_cfg1_base;
>  	}
> @@ -598,7 +587,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
>  				  busdev, cfg_size);
>  	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
>  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> +				  PCIE_ATU_TYPE_IO, pp->io_base,
>  				  pp->io_bus_addr, pp->io_size);
>  
>  	return ret;
> @@ -630,7 +619,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
>  static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
>  			int size, u32 *val)
>  {
> -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> +	struct pcie_port *pp = bus->sysdata;
>  	int ret;
>  
>  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
> @@ -654,7 +643,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
>  static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
>  			int where, int size, u32 val)
>  {
> -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> +	struct pcie_port *pp = bus->sysdata;
>  	int ret;
>  
>  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
> @@ -678,62 +667,6 @@ static struct pci_ops dw_pcie_ops = {
>  	.write = dw_pcie_wr_conf,
>  };
>  
> -static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
> -{
> -	struct pcie_port *pp;
> -
> -	pp = sys_to_pcie(sys);
> -
> -	if (global_io_offset < SZ_1M && pp->io_size > 0) {
> -		sys->io_offset = global_io_offset - pp->io_bus_addr;
> -		pci_ioremap_io(global_io_offset, pp->io_base);
> -		global_io_offset += SZ_64K;
> -		pci_add_resource_offset(&sys->resources, &pp->io,
> -					sys->io_offset);
> -	}
> -
> -	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
> -	pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
> -	pci_add_resource(&sys->resources, &pp->busn);
> -
> -	return 1;
> -}
> -
> -static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
> -{
> -	struct pci_bus *bus;
> -	struct pcie_port *pp = sys_to_pcie(sys);
> -
> -	pp->root_bus_nr = sys->busnr;
> -	bus = pci_scan_root_bus(pp->dev, sys->busnr,
> -				  &dw_pcie_ops, sys, &sys->resources);
> -	if (!bus)
> -		return NULL;
> -
> -	if (bus && pp->ops->scan_bus)
> -		pp->ops->scan_bus(pp);
> -
> -	return bus;
> -}
> -
> -static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> -{
> -	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
> -	int irq;
> -
> -	irq = of_irq_parse_and_map_pci(dev, slot, pin);
> -	if (!irq)
> -		irq = pp->irq;
> -
> -	return irq;
> -}
> -
> -static struct hw_pci dw_pci = {
> -	.setup		= dw_pcie_setup,
> -	.scan		= dw_pcie_scan_bus,
> -	.map_irq	= dw_pcie_map_irq,
> -};
> -
>  void dw_pcie_setup_rc(struct pcie_port *pp)
>  {
>  	u32 val;
> diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
> index d0bbd27..0c2a7eb 100644
> --- a/drivers/pci/host/pcie-designware.h
> +++ b/drivers/pci/host/pcie-designware.h
> @@ -21,31 +21,28 @@
>   */
>  #define MAX_MSI_IRQS			32
>  #define MAX_MSI_CTRLS			(MAX_MSI_IRQS / 32)
> +#define DW_ROOT_NR_UNDEFINED	-1
>  
>  struct pcie_port {
>  	struct device		*dev;
>  	u8			root_bus_nr;
>  	void __iomem		*dbi_base;
>  	u64			cfg0_base;
> -	u64			cfg0_mod_base;
>  	void __iomem		*va_cfg0_base;
>  	u32			cfg0_size;
>  	u64			cfg1_base;
> -	u64			cfg1_mod_base;
>  	void __iomem		*va_cfg1_base;
>  	u32			cfg1_size;
> -	u64			io_base;
> -	u64			io_mod_base;
> +	resource_size_t		io_base;
>  	phys_addr_t		io_bus_addr;
>  	u32			io_size;
>  	u64			mem_base;
> -	u64			mem_mod_base;
>  	phys_addr_t		mem_bus_addr;
>  	u32			mem_size;
> -	struct resource		cfg;
> -	struct resource		io;
> -	struct resource		mem;
> -	struct resource		busn;
> +	struct resource		*cfg;
> +	struct resource		*io;
> +	struct resource		*mem;
> +	struct resource		*busn;
>  	int			irq;
>  	u32			lanes;
>  	struct pcie_host_ops	*ops;
> diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
> index c49fbdc..b2c59b9 100644
> --- a/drivers/pci/host/pcie-spear13xx.c
> +++ b/drivers/pci/host/pcie-spear13xx.c
> @@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
>  		return ret;
>  	}
>  
> -	pp->root_bus_nr = -1;
> +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
>  	pp->ops = &spear13xx_pcie_host_ops;
>  
>  	ret = dw_pcie_host_init(pp);
> -- 
> 1.9.1
> 
> 
> > -----Original Message-----
> > From: Lucas Stach [mailto:l.stach at pengutronix.de]
> > Sent: Wednesday, August 19, 2015 1:54 PM
> > To: Wangzhou (B)
> > Cc: Bjorn Helgaas; jingoohan1 at gmail.com; Pratyush Anand; Arnd Bergmann;
> > linux at arm.linux.org.uk; thomas.petazzoni at free-electrons.com; Gabriele
> > Paoloni; lorenzo.pieralisi at arm.com; james.morse at arm.com;
> > Liviu.Dudau at arm.com; jason at lakedaemon.net; robh at kernel.org; linux-
> > pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> > devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > 
> > Am Montag, den 17.08.2015, 19:55 +0800 schrieb Zhou Wang:
> > > This patch tries to unify ARM32 and ARM64 PCIe in designware driver.
> > Delete
> > > function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct
> > hw_pci,
> > > move related operations to dw_pcie_host_init.
> > >
> > > In past, we use:
> > > pci_common_init_dev
> > > 	-> pcibios_init_hw
> > > 		-> hw->scan (dw_pcie_scan_bus)
> > > to pass 0 to root_bus_nr in struct pcie_port. This patch set pp-
> > >root_bus_nr = 0
> > > in each PCIe host driver which is based on pcie-designware.
> > >
> > This is incorrect at least if there are 2 instances of DW PCIe host in
> > the same SoC without using PCI domains. In that the case the bus range
> > determines the range of valid bus numbers per instance and the first
> > number is the root bus. Please look at the "bus-range" DT property in
> > the DW PCIe bindings.
> > 
> > Also we should finally remove this root-bus setup from the glue drivers
> > altogether. It's something that entirely belongs into the DW core code.
> > 
> > Regards,
> > Lucas
> > 
> > > This patch also try to use of_pci_get_host_bridge_resources for ARM32
> > and ARM64
> > > according to the suggestion for Gabriele[1]
> > >
> > > Finally this patch reverts commit f4c55c5a3f7f "PCI: designware:
> > Program ATU
> > > with untranslated address" based on 1/6 in this series. we delete
> > *_mod_base in
> > > pcie-designware. This was discussed in [2]
> > >
> > > I have compiled the driver with multi_v7_defconfig. However, I don't
> > have
> > > ARM32 PCIe related board to do test. It will be appreciated if
> > someone could
> > > help to test it.
> > >
> > > Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> > > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> > > Tested-By: James Morse <james.morse@arm.com>
> > >
> > > [1] http://www.spinics.net/lists/linux-pci/msg42194.html
> > > [2] http://www.spinics.net/lists/arm-kernel/msg436779.html
> > > ---
> > >  drivers/pci/host/pci-dra7xx.c      |  15 +--
> > >  drivers/pci/host/pci-exynos.c      |   2 +-
> > >  drivers/pci/host/pci-imx6.c        |   2 +-
> > >  drivers/pci/host/pci-keystone-dw.c |   2 +-
> > >  drivers/pci/host/pci-keystone.c    |   2 +-
> > >  drivers/pci/host/pci-layerscape.c  |   2 +-
> > >  drivers/pci/host/pcie-designware.c | 229 ++++++++++++---------------
> > ----------
> > >  drivers/pci/host/pcie-designware.h |  14 +--
> > >  drivers/pci/host/pcie-spear13xx.c  |   2 +-
> > >  9 files changed, 95 insertions(+), 175 deletions(-)
> > >
> > > diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-
> > dra7xx.c
> > > index 18ae7ff..1268c69 100644
> > > --- a/drivers/pci/host/pci-dra7xx.c
> > > +++ b/drivers/pci/host/pci-dra7xx.c
> > > @@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct
> > pcie_port *pp)
> > >  {
> > >  	dw_pcie_setup_rc(pp);
> > >
> > > -	if (pp->io_mod_base)
> > > -		pp->io_mod_base &= CPU_TO_BUS_ADDR;
> > > +	if (pp->io_base)
> > > +		pp->io_base &= CPU_TO_BUS_ADDR;
> > >
> > > -	if (pp->mem_mod_base)
> > > -		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
> > > +	if (pp->mem_base)
> > > +		pp->mem_base &= CPU_TO_BUS_ADDR;
> > >
> > > -	if (pp->cfg0_mod_base) {
> > > -		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
> > > -		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
> > > +	if (pp->cfg0_base) {
> > > +		pp->cfg0_base &= CPU_TO_BUS_ADDR;
> > > +		pp->cfg1_base &= CPU_TO_BUS_ADDR;
> > >  	}
> > >
> > >  	dra7xx_pcie_establish_link(pp);
> > > @@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct
> > dra7xx_pcie *dra7xx,
> > >
> > >  	pp = &dra7xx->pp;
> > >  	pp->dev = dev;
> > > +	pp->root_bus_nr = 0;
> > >  	pp->ops = &dra7xx_pcie_host_ops;
> > >
> > >  	pp->irq = platform_get_irq(pdev, 1);
> > > diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-
> > exynos.c
> > > index f9f468d..9771bb0 100644
> > > --- a/drivers/pci/host/pci-exynos.c
> > > +++ b/drivers/pci/host/pci-exynos.c
> > > @@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct
> > pcie_port *pp,
> > >  		}
> > >  	}
> > >
> > > -	pp->root_bus_nr = -1;
> > > +	pp->root_bus_nr = 0;
> > >  	pp->ops = &exynos_pcie_host_ops;
> > >
> > >  	ret = dw_pcie_host_init(pp);
> > > diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-
> > imx6.c
> > > index 233a196..bec256c 100644
> > > --- a/drivers/pci/host/pci-imx6.c
> > > +++ b/drivers/pci/host/pci-imx6.c
> > > @@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct
> > pcie_port *pp,
> > >  		}
> > >  	}
> > >
> > > -	pp->root_bus_nr = -1;
> > > +	pp->root_bus_nr = 0;
> > >  	pp->ops = &imx6_pcie_host_ops;
> > >
> > >  	ret = dw_pcie_host_init(pp);
> > > diff --git a/drivers/pci/host/pci-keystone-dw.c
> > b/drivers/pci/host/pci-keystone-dw.c
> > > index f34892e..b1e4135 100644
> > > --- a/drivers/pci/host/pci-keystone-dw.c
> > > +++ b/drivers/pci/host/pci-keystone-dw.c
> > > @@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void
> > __iomem *reg_virt)
> > >  void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
> > >  {
> > >  	struct pcie_port *pp = &ks_pcie->pp;
> > > -	u32 start = pp->mem.start, end = pp->mem.end;
> > > +	u32 start = pp->mem->start, end = pp->mem->end;
> > >  	int i, tr_size;
> > >
> > >  	/* Disable BARs for inbound access */
> > > diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-
> > keystone.c
> > > index 734da58..8113832 100644
> > > --- a/drivers/pci/host/pci-keystone.c
> > > +++ b/drivers/pci/host/pci-keystone.c
> > > @@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct
> > keystone_pcie *ks_pcie,
> > >  			return ret;
> > >  	}
> > >
> > > -	pp->root_bus_nr = -1;
> > > +	pp->root_bus_nr = 0;
> > >  	pp->ops = &keystone_pcie_host_ops;
> > >  	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
> > >  	if (ret) {
> > > diff --git a/drivers/pci/host/pci-layerscape.c
> > b/drivers/pci/host/pci-layerscape.c
> > > index b2328ea1..79ff08c 100644
> > > --- a/drivers/pci/host/pci-layerscape.c
> > > +++ b/drivers/pci/host/pci-layerscape.c
> > > @@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
> > >  	pp = &pcie->pp;
> > >  	pp->dev = pcie->dev;
> > >  	pp->dbi_base = pcie->dbi;
> > > -	pp->root_bus_nr = -1;
> > > +	pp->root_bus_nr = 0;
> > >  	pp->ops = &ls_pcie_host_ops;
> > >
> > >  	ret = dw_pcie_host_init(pp);
> > > diff --git a/drivers/pci/host/pcie-designware.c
> > b/drivers/pci/host/pcie-designware.c
> > > index c5d407c..e71a88e 100644
> > > --- a/drivers/pci/host/pcie-designware.c
> > > +++ b/drivers/pci/host/pcie-designware.c
> > > @@ -11,6 +11,7 @@
> > >   * published by the Free Software Foundation.
> > >   */
> > >
> > > +#include <linux/hardirq.h>
> > >  #include <linux/irq.h>
> > >  #include <linux/irqdomain.h>
> > >  #include <linux/kernel.h>
> > > @@ -69,16 +70,7 @@
> > >  #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
> > >  #define PCIE_ATU_UPPER_TARGET		0x91C
> > >
> > > -static struct hw_pci dw_pci;
> > > -
> > > -static unsigned long global_io_offset;
> > > -
> > > -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
> > > -{
> > > -	BUG_ON(!sys->private_data);
> > > -
> > > -	return sys->private_data;
> > > -}
> > > +static struct pci_ops dw_pcie_ops;
> > >
> > >  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32
> > *val)
> > >  {
> > > @@ -255,7 +247,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port
> > *pp, int irq)
> > >  static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
> > >  {
> > >  	int irq, pos0, i;
> > > -	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
> > > +	struct pcie_port *pp = desc->dev->bus->sysdata;
> > >
> > >  	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
> > >  				       order_base_2(no_irqs));
> > > @@ -298,7 +290,7 @@ static int dw_msi_setup_irq(struct msi_controller
> > *chip, struct pci_dev *pdev,
> > >  {
> > >  	int irq, pos;
> > >  	struct msi_msg msg;
> > > -	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
> > > +	struct pcie_port *pp = pdev->bus->sysdata;
> > >
> > >  	if (desc->msi_attrib.is_msix)
> > >  		return -EINVAL;
> > > @@ -327,7 +319,7 @@ static void dw_msi_teardown_irq(struct
> > msi_controller *chip, unsigned int irq)
> > >  {
> > >  	struct irq_data *data = irq_get_irq_data(irq);
> > >  	struct msi_desc *msi = irq_data_get_msi(data);
> > > -	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
> > > +	struct pcie_port *pp = msi->dev->bus->sysdata;
> > >
> > >  	clear_irq_range(pp, irq, 1, data->hwirq);
> > >  }
> > > @@ -363,14 +355,12 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > >  {
> > >  	struct device_node *np = pp->dev->of_node;
> > >  	struct platform_device *pdev = to_platform_device(pp->dev);
> > > -	struct of_pci_range range;
> > > -	struct of_pci_range_parser parser;
> > > +	struct pci_bus *bus;
> > >  	struct resource *cfg_res;
> > > -	u32 val, ns;
> > > -	const __be32 *addrp;
> > > -	int i, index, ret;
> > > -
> > > -	ns = of_n_size_cells(np);
> > > +	LIST_HEAD(res);
> > > +	u32 val;
> > > +	int i, ret;
> > > +	struct resource_entry *win;
> > >
> > >  	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> > "config");
> > >  	if (cfg_res) {
> > > @@ -378,85 +368,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > >  		pp->cfg1_size = resource_size(cfg_res)/2;
> > >  		pp->cfg0_base = cfg_res->start;
> > >  		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
> > > -
> > > -		/* Find the untranslated configuration space address */
> > > -		index = of_property_match_string(np, "reg-names", "config");
> > > -		addrp = of_get_address(np, index, NULL, NULL);
> > > -		pp->cfg0_mod_base = of_read_number(addrp, ns);
> > > -		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
> > >  	} else {
> > >  		dev_err(pp->dev, "missing *config* reg space\n");
> > >  	}
> > >
> > > -	if (of_pci_range_parser_init(&parser, np)) {
> > > -		dev_err(pp->dev, "missing ranges property\n");
> > > -		return -EINVAL;
> > > -	}
> > > +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp-
> > >io_base);
> > > +	if (ret)
> > > +		return ret;
> > >
> > >  	/* Get the I/O and memory ranges from DT */
> > > -	for_each_of_pci_range(&parser, &range) {
> > > -		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
> > > -
> > > -		if (restype == IORESOURCE_IO) {
> > > -			of_pci_range_to_resource(&range, np, &pp->io);
> > > -			pp->io.name = "I/O";
> > > -			pp->io.start = max_t(resource_size_t,
> > > -					     PCIBIOS_MIN_IO,
> > > -					     range.pci_addr + global_io_offset);
> > > -			pp->io.end = min_t(resource_size_t,
> > > -					   IO_SPACE_LIMIT,
> > > -					   range.pci_addr + range.size
> > > -					   + global_io_offset - 1);
> > > -			pp->io_size = resource_size(&pp->io);
> > > -			pp->io_bus_addr = range.pci_addr;
> > > -			pp->io_base = range.cpu_addr;
> > > -
> > > -			/* Find the untranslated IO space address */
> > > -			pp->io_mod_base = range.cpu_addr;
> > > -		}
> > > -		if (restype == IORESOURCE_MEM) {
> > > -			of_pci_range_to_resource(&range, np, &pp->mem);
> > > -			pp->mem.name = "MEM";
> > > -			pp->mem_size = resource_size(&pp->mem);
> > > -			pp->mem_bus_addr = range.pci_addr;
> > > -
> > > -			/* Find the untranslated MEM space address */
> > > -			pp->mem_mod_base = range.cpu_addr;
> > > -		}
> > > -		if (restype == 0) {
> > > -			of_pci_range_to_resource(&range, np, &pp->cfg);
> > > -			pp->cfg0_size = resource_size(&pp->cfg)/2;
> > > -			pp->cfg1_size = resource_size(&pp->cfg)/2;
> > > -			pp->cfg0_base = pp->cfg.start;
> > > -			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
> > > -
> > > -			/* Find the untranslated configuration space address
> > */
> > > -			pp->cfg0_mod_base = range.cpu_addr;
> > > -			pp->cfg1_mod_base = pp->cfg0_mod_base +
> > > -					    pp->cfg0_size;
> > > +	resource_list_for_each_entry(win, &res) {
> > > +		switch (resource_type(win->res)) {
> > > +		case IORESOURCE_IO:
> > > +			pp->io = win->res;
> > > +			pp->io->name = "I/O";
> > > +			pp->io_size = resource_size(pp->io);
> > > +			pp->io_bus_addr = pp->io->start - win->offset;
> > > +			ret = pci_remap_iospace(pp->io, pp->io_base);
> > > +			if (ret) {
> > > +				dev_warn(pp->dev, "error %d: failed to map
> > resource %pR\n",
> > > +					 ret, pp->io);
> > > +				continue;
> > > +			}
> > > +			break;
> > > +		case IORESOURCE_MEM:
> > > +			pp->mem = win->res;
> > > +			pp->mem->name = "MEM";
> > > +			pp->mem_size = resource_size(pp->mem);
> > > +			pp->mem_bus_addr = pp->mem->start - win->offset;
> > > +			break;
> > > +		case 0:
> > > +			pp->cfg = win->res;
> > > +			pp->cfg0_size = resource_size(pp->cfg)/2;
> > > +			pp->cfg1_size = resource_size(pp->cfg)/2;
> > > +			pp->cfg0_base = pp->cfg->start;
> > > +			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
> > > +			break;
> > > +		case IORESOURCE_BUS:
> > > +			pp->busn = win->res;
> > > +			break;
> > > +		default:
> > > +			continue;
> > >  		}
> > >  	}
> > >
> > > -	ret = of_pci_parse_bus_range(np, &pp->busn);
> > > -	if (ret < 0) {
> > > -		pp->busn.name = np->name;
> > > -		pp->busn.start = 0;
> > > -		pp->busn.end = 0xff;
> > > -		pp->busn.flags = IORESOURCE_BUS;
> > > -		dev_dbg(pp->dev, "failed to parse bus-range property: %d,
> > using default %pR\n",
> > > -			ret, &pp->busn);
> > > -	}
> > > -
> > >  	if (!pp->dbi_base) {
> > > -		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
> > > -					resource_size(&pp->cfg));
> > > +		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
> > > +					resource_size(pp->cfg));
> > >  		if (!pp->dbi_base) {
> > >  			dev_err(pp->dev, "error with ioremap\n");
> > >  			return -ENOMEM;
> > >  		}
> > >  	}
> > >
> > > -	pp->mem_base = pp->mem.start;
> > > +	pp->mem_base = pp->mem->start;
> > >
> > >  	if (!pp->va_cfg0_base) {
> > >  		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
> > > @@ -505,7 +470,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > >
> > >  	if (!pp->ops->rd_other_conf)
> > >  		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
> > > -					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
> > > +					  PCIE_ATU_TYPE_MEM, pp->mem_base,
> > >  					  pp->mem_bus_addr, pp->mem_size);
> > >
> > >  	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
> > > @@ -517,15 +482,29 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > >  	val |= PORT_LOGIC_SPEED_CHANGE;
> > >  	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
> > >
> > > -#ifdef CONFIG_PCI_MSI
> > > +	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
> > > +				  pp, &res);
> > > +	if (!bus)
> > > +		return -ENOMEM;
> > > +
> > > +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> > > +	bus->msi = container_of(&pp->irq_domain, struct msi_controller,
> > domain);
> > > +#else
> > >  	dw_pcie_msi_chip.dev = pp->dev;
> > > -	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> > > +	bus->msi = &dw_pcie_msi_chip;
> > >  #endif
> > >
> > > -	dw_pci.nr_controllers = 1;
> > > -	dw_pci.private_data = (void **)&pp;
> > > +	pci_scan_child_bus(bus);
> > > +	if (pp->ops->scan_bus)
> > > +		pp->ops->scan_bus(pp);
> > > +
> > > +#ifdef CONFIG_ARM
> > > +	/* support old dtbs that incorrectly describe IRQs */
> > > +	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
> > > +#endif
> > >
> > > -	pci_common_init_dev(pp->dev, &dw_pci);
> > > +	pci_assign_unassigned_bus_resources(bus);
> > > +	pci_bus_add_devices(bus);
> > >
> > >  	return 0;
> > >  }
> > > @@ -544,12 +523,12 @@ static int dw_pcie_rd_other_conf(struct
> > pcie_port *pp, struct pci_bus *bus,
> > >
> > >  	if (bus->parent->number == pp->root_bus_nr) {
> > >  		type = PCIE_ATU_TYPE_CFG0;
> > > -		cpu_addr = pp->cfg0_mod_base;
> > > +		cpu_addr = pp->cfg0_base;
> > >  		cfg_size = pp->cfg0_size;
> > >  		va_cfg_base = pp->va_cfg0_base;
> > >  	} else {
> > >  		type = PCIE_ATU_TYPE_CFG1;
> > > -		cpu_addr = pp->cfg1_mod_base;
> > > +		cpu_addr = pp->cfg1_base;
> > >  		cfg_size = pp->cfg1_size;
> > >  		va_cfg_base = pp->va_cfg1_base;
> > >  	}
> > > @@ -559,7 +538,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port
> > *pp, struct pci_bus *bus,
> > >  				  busdev, cfg_size);
> > >  	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
> > >  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> > > -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> > > +				  PCIE_ATU_TYPE_IO, pp->io_base,
> > >  				  pp->io_bus_addr, pp->io_size);
> > >
> > >  	return ret;
> > > @@ -579,12 +558,12 @@ static int dw_pcie_wr_other_conf(struct
> > pcie_port *pp, struct pci_bus *bus,
> > >
> > >  	if (bus->parent->number == pp->root_bus_nr) {
> > >  		type = PCIE_ATU_TYPE_CFG0;
> > > -		cpu_addr = pp->cfg0_mod_base;
> > > +		cpu_addr = pp->cfg0_base;
> > >  		cfg_size = pp->cfg0_size;
> > >  		va_cfg_base = pp->va_cfg0_base;
> > >  	} else {
> > >  		type = PCIE_ATU_TYPE_CFG1;
> > > -		cpu_addr = pp->cfg1_mod_base;
> > > +		cpu_addr = pp->cfg1_base;
> > >  		cfg_size = pp->cfg1_size;
> > >  		va_cfg_base = pp->va_cfg1_base;
> > >  	}
> > > @@ -594,7 +573,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port
> > *pp, struct pci_bus *bus,
> > >  				  busdev, cfg_size);
> > >  	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
> > >  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> > > -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> > > +				  PCIE_ATU_TYPE_IO, pp->io_base,
> > >  				  pp->io_bus_addr, pp->io_size);
> > >
> > >  	return ret;
> > > @@ -626,7 +605,7 @@ static int dw_pcie_valid_config(struct pcie_port
> > *pp,
> > >  static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> > >  			int size, u32 *val)
> > >  {
> > > -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> > > +	struct pcie_port *pp = bus->sysdata;
> > >  	int ret;
> > >
> > >  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
> > > @@ -650,7 +629,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus,
> > u32 devfn, int where,
> > >  static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
> > >  			int where, int size, u32 val)
> > >  {
> > > -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> > > +	struct pcie_port *pp = bus->sysdata;
> > >  	int ret;
> > >
> > >  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
> > > @@ -674,62 +653,6 @@ static struct pci_ops dw_pcie_ops = {
> > >  	.write = dw_pcie_wr_conf,
> > >  };
> > >
> > > -static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
> > > -{
> > > -	struct pcie_port *pp;
> > > -
> > > -	pp = sys_to_pcie(sys);
> > > -
> > > -	if (global_io_offset < SZ_1M && pp->io_size > 0) {
> > > -		sys->io_offset = global_io_offset - pp->io_bus_addr;
> > > -		pci_ioremap_io(global_io_offset, pp->io_base);
> > > -		global_io_offset += SZ_64K;
> > > -		pci_add_resource_offset(&sys->resources, &pp->io,
> > > -					sys->io_offset);
> > > -	}
> > > -
> > > -	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
> > > -	pci_add_resource_offset(&sys->resources, &pp->mem, sys-
> > >mem_offset);
> > > -	pci_add_resource(&sys->resources, &pp->busn);
> > > -
> > > -	return 1;
> > > -}
> > > -
> > > -static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data
> > *sys)
> > > -{
> > > -	struct pci_bus *bus;
> > > -	struct pcie_port *pp = sys_to_pcie(sys);
> > > -
> > > -	pp->root_bus_nr = sys->busnr;
> > > -	bus = pci_scan_root_bus(pp->dev, sys->busnr,
> > > -				  &dw_pcie_ops, sys, &sys->resources);
> > > -	if (!bus)
> > > -		return NULL;
> > > -
> > > -	if (bus && pp->ops->scan_bus)
> > > -		pp->ops->scan_bus(pp);
> > > -
> > > -	return bus;
> > > -}
> > > -
> > > -static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8
> > pin)
> > > -{
> > > -	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
> > > -	int irq;
> > > -
> > > -	irq = of_irq_parse_and_map_pci(dev, slot, pin);
> > > -	if (!irq)
> > > -		irq = pp->irq;
> > > -
> > > -	return irq;
> > > -}
> > > -
> > > -static struct hw_pci dw_pci = {
> > > -	.setup		= dw_pcie_setup,
> > > -	.scan		= dw_pcie_scan_bus,
> > > -	.map_irq	= dw_pcie_map_irq,
> > > -};
> > > -
> > >  void dw_pcie_setup_rc(struct pcie_port *pp)
> > >  {
> > >  	u32 val;
> > > diff --git a/drivers/pci/host/pcie-designware.h
> > b/drivers/pci/host/pcie-designware.h
> > > index d0bbd27..264c969 100644
> > > --- a/drivers/pci/host/pcie-designware.h
> > > +++ b/drivers/pci/host/pcie-designware.h
> > > @@ -27,25 +27,21 @@ struct pcie_port {
> > >  	u8			root_bus_nr;
> > >  	void __iomem		*dbi_base;
> > >  	u64			cfg0_base;
> > > -	u64			cfg0_mod_base;
> > >  	void __iomem		*va_cfg0_base;
> > >  	u32			cfg0_size;
> > >  	u64			cfg1_base;
> > > -	u64			cfg1_mod_base;
> > >  	void __iomem		*va_cfg1_base;
> > >  	u32			cfg1_size;
> > > -	u64			io_base;
> > > -	u64			io_mod_base;
> > > +	resource_size_t		io_base;
> > >  	phys_addr_t		io_bus_addr;
> > >  	u32			io_size;
> > >  	u64			mem_base;
> > > -	u64			mem_mod_base;
> > >  	phys_addr_t		mem_bus_addr;
> > >  	u32			mem_size;
> > > -	struct resource		cfg;
> > > -	struct resource		io;
> > > -	struct resource		mem;
> > > -	struct resource		busn;
> > > +	struct resource		*cfg;
> > > +	struct resource		*io;
> > > +	struct resource		*mem;
> > > +	struct resource		*busn;
> > >  	int			irq;
> > >  	u32			lanes;
> > >  	struct pcie_host_ops	*ops;
> > > diff --git a/drivers/pci/host/pcie-spear13xx.c
> > b/drivers/pci/host/pcie-spear13xx.c
> > > index c49fbdc..03eb204 100644
> > > --- a/drivers/pci/host/pcie-spear13xx.c
> > > +++ b/drivers/pci/host/pcie-spear13xx.c
> > > @@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct
> > pcie_port *pp,
> > >  		return ret;
> > >  	}
> > >
> > > -	pp->root_bus_nr = -1;
> > > +	pp->root_bus_nr = 0;
> > >  	pp->ops = &spear13xx_pcie_host_ops;
> > >
> > >  	ret = dw_pcie_host_init(pp);
> > 
> > --
> > Pengutronix e.K.             | Lucas Stach                 |
> > Industrial Linux Solutions   | http://www.pengutronix.de/  |
> 

-- 
Pengutronix e.K.             | Lucas Stach                 |
Industrial Linux Solutions   | http://www.pengutronix.de/  |

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

* RE: [PATCH v7 3/6] PCI: designware: Add ARM64 support
  2015-08-19 15:37         ` Lucas Stach
  (?)
@ 2015-08-19 16:34           ` Gabriele Paoloni
  -1 siblings, 0 replies; 53+ messages in thread
From: Gabriele Paoloni @ 2015-08-19 16:34 UTC (permalink / raw)
  To: Lucas Stach
  Cc: Wangzhou (B),
	Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, lorenzo.pieralisi, james.morse, Liviu.Dudau,
	jason, robh, linux-pci, linux-arm-kernel, devicetree,
	Yuanzhichang, Zhudacai, zhangjukuo, qiuzhe

Hi Lucas

First of all many thanks for the quick reply, really appreciated

> -----Original Message-----
> From: Lucas Stach [mailto:l.stach@pengutronix.de]
> Sent: Wednesday, August 19, 2015 4:37 PM
> To: Gabriele Paoloni
> Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com; Pratyush Anand;
> Arnd Bergmann; linux@arm.linux.org.uk; thomas.petazzoni@free-
> electrons.com; lorenzo.pieralisi@arm.com; james.morse@arm.com;
> Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org; linux-
> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> 
> Hi Gab,
> 
> Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele Paoloni:
> > Hi Lucas
> >
> > I have rewritten the patch to take into account multiple controllers.
> >
> > As you can see now there is a static var in dw_pcie_host_init() that
> tracks
> > the bus numbers used.
> 
> This is wrong. The DT specifies the valid bus number range. You can not
> just assign the next free bus number to the root bus.

I think this is what is being done in
http://lxr.free-electrons.com/source/arch/arm/kernel/bios32.c#L495
and currently designware assigns the root bus number in
http://lxr.free-electrons.com/source/drivers/pci/host/pcie-designware.c#L730


In general I agree with you but if you look at all the current drivers 
based on designware none of them define the "bus-range" dtb property.
Therefore doing as you say would break the current driver when we have
multiple controllers...am I right?

If that is the case in order to fix this in the way you say I would need
to assign "bus-range" for all the PCIe drivers with multiple controllers:
in this case I would split the default range evenly (that is, if we have 
two controllers I would define "bus-range"  0-127 and 128-255)

If you think this solution is ok I can go for it. My only doubt was about
touching other vendors DTBs....


> 
> It is perfectly valid to have a bus range of 0x00-0x10 assigned to one
> instance and 0x50-0xff to the next instance. Additional with PCIe
> hotplug you may not use the full range of the bus numbers on one
> instance at the first scan, but only later populate more buses when
> more
> bridges are added to the tree.
> 
> > Drivers that do not specify the bus range in the DTB set pp-
> >root_bus_nr = DW_ROOT_NR_UNDEFINED.
> > Designware will check if the flag is set and will use the automatic
> bus range
> > assignment.
> 
> No, please lets get rid of this assignment altogether. The glue drivers
> have no business in assigning the bus range. Please remove the
> pp->root_bus_nr assignment from all the glue drivers.
> 
> "bus range" is a generic DW PCIe property, so just parse the root bus
> number from the DT, it is handled the same way for all the DW based
> PCIe
> drivers. The bindings specifies that if the bus range property is
> missing the range is 0x00-0xff, so you can default to 0 as the root bus
> number in that case.
> 
> Also I would think this conversion warrants a patch on its own and
> should not be mixed in the ARM64 support patch.
> 
> Regards,
> Lucas
> 
> > Instead if the driver assigns pp->root_bus_nr according to the dtb,
> designwware
> > will use the value passed in by the driver.
> > Below the relevant section:
> >
> >
> > +	static int root_bus_nr = 0;
> > ...
> > +	mutex_lock(&root_bus_nr_mux);
> > +
> > +	if (pp->root_bus_nr != DW_ROOT_NR_UNDEFINED)
> > +		root_bus_nr = pp->root_bus_nr;
> > +
> > +	bus = pci_create_root_bus(pp->dev, root_bus_nr, &dw_pcie_ops,
> > +			      pp, &res);
> > +	if (!bus) {
> > +		mutex_unlock(&root_bus_nr_mux);
> > +		return -ENOMEM;
> > +	}
> > +
> > +	root_bus_nr += bus->busn_res.end + 1;
> > +	mutex_unlock(&root_bus_nr_mux);
> >
> > Please let me know what you think...
> >
> > Many Thanks
> >
> > Gab
> > ----------
> >
> > From: gabriele paoloni <gabriele.paoloni@huawei.com>
> >
> > This patch tries to unify ARM32 and ARM64 PCIe in designware driver.
> Delete
> > function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct
> hw_pci,
> > move related operations to dw_pcie_host_init.
> > Also set pp->root_bus_nr = DW_ROOT_NR_UNDEFINED in all the drivers
> that
> > are based on designware to flag that the drivers do not read the bus
> > ranges from DT.
> > This patch also adds handling of multiple PCI domains in designware.
> > if the PCI host bridge driver does not specify a root bus number, in
> case
> > of multiple domains, designware will automatillay set the next domain
> root
> > bus number to the last bus number used in the last domain + 1.
> >
> > This patch also try to use of_pci_get_host_bridge_resources for ARM32
> and
> > ARM64 according to the suggestion for Gabriele[1]
> >
> > This patch is based on Gabriele's patch about of_pci_range fix[2]
> >
> > Finally this patch reverts commit f4c55c5a3f7f "PCI: designware:
> > Program ATU with untranslated address". This was discussed in [3]
> >
> > I have compiled the driver with multi_v7_defconfig. However, I don't
> have
> > ARM32 PCIe related board to do test. It will be appreciated if
> someone could
> > help to test it.
> >
> > Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> >
> > [1] http://www.spinics.net/lists/linux-pci/msg42194.html
> > [2] https://patchwork.ozlabs.org/patch/495018/
> > [3] http://www.spinics.net/lists/arm-kernel/msg436779.html
> > ---
> >  drivers/pci/host/pci-dra7xx.c      |  15 +--
> >  drivers/pci/host/pci-exynos.c      |   2 +-
> >  drivers/pci/host/pci-imx6.c        |   2 +-
> >  drivers/pci/host/pci-keystone-dw.c |   2 +-
> >  drivers/pci/host/pci-keystone.c    |   2 +-
> >  drivers/pci/host/pci-layerscape.c  |   2 +-
> >  drivers/pci/host/pcie-designware.c | 247 ++++++++++++++-------------
> ----------
> >  drivers/pci/host/pcie-designware.h |  15 +--
> >  drivers/pci/host/pcie-spear13xx.c  |   2 +-
> >  9 files changed, 110 insertions(+), 179 deletions(-)
> >
> > diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-
> dra7xx.c
> > index 5678b57..8d598fb 100644
> > --- a/drivers/pci/host/pci-dra7xx.c
> > +++ b/drivers/pci/host/pci-dra7xx.c
> > @@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct
> pcie_port *pp)
> >  {
> >  	dw_pcie_setup_rc(pp);
> >
> > -	if (pp->io_mod_base)
> > -		pp->io_mod_base &= CPU_TO_BUS_ADDR;
> > +	if (pp->io_base)
> > +		pp->io_base &= CPU_TO_BUS_ADDR;
> >
> > -	if (pp->mem_mod_base)
> > -		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
> > +	if (pp->mem_base)
> > +		pp->mem_base &= CPU_TO_BUS_ADDR;
> >
> > -	if (pp->cfg0_mod_base) {
> > -		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
> > -		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
> > +	if (pp->cfg0_base) {
> > +		pp->cfg0_base &= CPU_TO_BUS_ADDR;
> > +		pp->cfg1_base &= CPU_TO_BUS_ADDR;
> >  	}
> >
> >  	dra7xx_pcie_establish_link(pp);
> > @@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct
> dra7xx_pcie *dra7xx,
> >
> >  	pp = &dra7xx->pp;
> >  	pp->dev = dev;
> > +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
> >  	pp->ops = &dra7xx_pcie_host_ops;
> >
> >  	pp->irq = platform_get_irq(pdev, 1);
> > diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-
> exynos.c
> > index f9f468d..ed03a8f 100644
> > --- a/drivers/pci/host/pci-exynos.c
> > +++ b/drivers/pci/host/pci-exynos.c
> > @@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct
> pcie_port *pp,
> >  		}
> >  	}
> >
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
> >  	pp->ops = &exynos_pcie_host_ops;
> >
> >  	ret = dw_pcie_host_init(pp);
> > diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-
> imx6.c
> > index 233a196..0efac85 100644
> > --- a/drivers/pci/host/pci-imx6.c
> > +++ b/drivers/pci/host/pci-imx6.c
> > @@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct
> pcie_port *pp,
> >  		}
> >  	}
> >
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
> >  	pp->ops = &imx6_pcie_host_ops;
> >
> >  	ret = dw_pcie_host_init(pp);
> > diff --git a/drivers/pci/host/pci-keystone-dw.c
> b/drivers/pci/host/pci-keystone-dw.c
> > index f34892e..b1e4135 100644
> > --- a/drivers/pci/host/pci-keystone-dw.c
> > +++ b/drivers/pci/host/pci-keystone-dw.c
> > @@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void
> __iomem *reg_virt)
> >  void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
> >  {
> >  	struct pcie_port *pp = &ks_pcie->pp;
> > -	u32 start = pp->mem.start, end = pp->mem.end;
> > +	u32 start = pp->mem->start, end = pp->mem->end;
> >  	int i, tr_size;
> >
> >  	/* Disable BARs for inbound access */
> > diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-
> keystone.c
> > index 734da58..b522956 100644
> > --- a/drivers/pci/host/pci-keystone.c
> > +++ b/drivers/pci/host/pci-keystone.c
> > @@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct
> keystone_pcie *ks_pcie,
> >  			return ret;
> >  	}
> >
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
> >  	pp->ops = &keystone_pcie_host_ops;
> >  	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
> >  	if (ret) {
> > diff --git a/drivers/pci/host/pci-layerscape.c
> b/drivers/pci/host/pci-layerscape.c
> > index b2328ea1..dd92ffa 100644
> > --- a/drivers/pci/host/pci-layerscape.c
> > +++ b/drivers/pci/host/pci-layerscape.c
> > @@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
> >  	pp = &pcie->pp;
> >  	pp->dev = pcie->dev;
> >  	pp->dbi_base = pcie->dbi;
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
> >  	pp->ops = &ls_pcie_host_ops;
> >
> >  	ret = dw_pcie_host_init(pp);
> > diff --git a/drivers/pci/host/pcie-designware.c
> b/drivers/pci/host/pcie-designware.c
> > index 5307b35..bd2606b 100644
> > --- a/drivers/pci/host/pcie-designware.c
> > +++ b/drivers/pci/host/pcie-designware.c
> > @@ -11,6 +11,7 @@
> >   * published by the Free Software Foundation.
> >   */
> >
> > +#include <linux/hardirq.h>
> >  #include <linux/irq.h>
> >  #include <linux/irqdomain.h>
> >  #include <linux/kernel.h>
> > @@ -69,16 +70,9 @@
> >  #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
> >  #define PCIE_ATU_UPPER_TARGET		0x91C
> >
> > -static struct hw_pci dw_pci;
> > +static struct pci_ops dw_pcie_ops;
> >
> > -static unsigned long global_io_offset;
> > -
> > -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
> > -{
> > -	BUG_ON(!sys->private_data);
> > -
> > -	return sys->private_data;
> > -}
> > +DEFINE_MUTEX(root_bus_nr_mux);
> >
> >  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32
> *val)
> >  {
> > @@ -255,7 +249,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port
> *pp, int irq)
> >  static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
> >  {
> >  	int irq, pos0, i;
> > -	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
> > +	struct pcie_port *pp = desc->dev->bus->sysdata;
> >
> >  	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
> >  				       order_base_2(no_irqs));
> > @@ -298,7 +292,7 @@ static int dw_msi_setup_irq(struct msi_controller
> *chip, struct pci_dev *pdev,
> >  {
> >  	int irq, pos;
> >  	struct msi_msg msg;
> > -	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
> > +	struct pcie_port *pp = pdev->bus->sysdata;
> >
> >  	if (desc->msi_attrib.is_msix)
> >  		return -EINVAL;
> > @@ -327,7 +321,7 @@ static void dw_msi_teardown_irq(struct
> msi_controller *chip, unsigned int irq)
> >  {
> >  	struct irq_data *data = irq_get_irq_data(irq);
> >  	struct msi_desc *msi = irq_data_get_msi(data);
> > -	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
> > +	struct pcie_port *pp = msi->dev->bus->sysdata;
> >
> >  	clear_irq_range(pp, irq, 1, data->hwirq);
> >  }
> > @@ -359,22 +353,17 @@ static const struct irq_domain_ops
> msi_domain_ops = {
> >  	.map = dw_pcie_msi_map,
> >  };
> >
> > -int dw_pcie_host_init(struct pcie_port *pp)
> > +int __init dw_pcie_host_init(struct pcie_port *pp)
> >  {
> >  	struct device_node *np = pp->dev->of_node;
> >  	struct platform_device *pdev = to_platform_device(pp->dev);
> > -	struct of_pci_range range;
> > -	struct of_pci_range_parser parser;
> > +	struct pci_bus *bus;
> >  	struct resource *cfg_res;
> > -	u32 val, na, ns;
> > -	const __be32 *addrp;
> > -	int i, index, ret;
> > -
> > -	/* Find the address cell size and the number of cells in order to
> get
> > -	 * the untranslated address.
> > -	 */
> > -	of_property_read_u32(np, "#address-cells", &na);
> > -	ns = of_n_size_cells(np);
> > +	LIST_HEAD(res);
> > +	u32 val;
> > +	int i, ret;
> > +	struct resource_entry *win;
> > +	static int root_bus_nr = 0;
> >
> >  	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> "config");
> >  	if (cfg_res) {
> > @@ -382,85 +371,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
> >  		pp->cfg1_size = resource_size(cfg_res)/2;
> >  		pp->cfg0_base = cfg_res->start;
> >  		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
> > -
> > -		/* Find the untranslated configuration space address */
> > -		index = of_property_match_string(np, "reg-names", "config");
> > -		addrp = of_get_address(np, index, NULL, NULL);
> > -		pp->cfg0_mod_base = of_read_number(addrp, ns);
> > -		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
> >  	} else {
> >  		dev_err(pp->dev, "missing *config* reg space\n");
> >  	}
> >
> > -	if (of_pci_range_parser_init(&parser, np)) {
> > -		dev_err(pp->dev, "missing ranges property\n");
> > -		return -EINVAL;
> > -	}
> > +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp-
> >io_base);
> > +	if (ret)
> > +		return ret;
> >
> >  	/* Get the I/O and memory ranges from DT */
> > -	for_each_of_pci_range(&parser, &range) {
> > -		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
> > -
> > -		if (restype == IORESOURCE_IO) {
> > -			of_pci_range_to_resource(&range, np, &pp->io);
> > -			pp->io.name = "I/O";
> > -			pp->io.start = max_t(resource_size_t,
> > -					     PCIBIOS_MIN_IO,
> > -					     range.pci_addr + global_io_offset);
> > -			pp->io.end = min_t(resource_size_t,
> > -					   IO_SPACE_LIMIT,
> > -					   range.pci_addr + range.size
> > -					   + global_io_offset - 1);
> > -			pp->io_size = resource_size(&pp->io);
> > -			pp->io_bus_addr = range.pci_addr;
> > -			pp->io_base = range.cpu_addr;
> > -
> > -			/* Find the untranslated IO space address */
> > -			pp->io_mod_base = range.cpu_addr;
> > -		}
> > -		if (restype == IORESOURCE_MEM) {
> > -			of_pci_range_to_resource(&range, np, &pp->mem);
> > -			pp->mem.name = "MEM";
> > -			pp->mem_size = resource_size(&pp->mem);
> > -			pp->mem_bus_addr = range.pci_addr;
> > -
> > -			/* Find the untranslated MEM space address */
> > -			pp->mem_mod_base = range.cpu_addr;
> > -		}
> > -		if (restype == 0) {
> > -			of_pci_range_to_resource(&range, np, &pp->cfg);
> > -			pp->cfg0_size = resource_size(&pp->cfg)/2;
> > -			pp->cfg1_size = resource_size(&pp->cfg)/2;
> > -			pp->cfg0_base = pp->cfg.start;
> > -			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
> > -
> > -			/* Find the untranslated configuration space address
> */
> > -			pp->cfg0_mod_base = range.cpu_addr;
> > -			pp->cfg1_mod_base = pp->cfg0_mod_base +
> > -					    pp->cfg0_size;
> > +	resource_list_for_each_entry(win, &res) {
> > +		switch (resource_type(win->res)) {
> > +		case IORESOURCE_IO:
> > +			pp->io = win->res;
> > +			pp->io->name = "I/O";
> > +			pp->io_size = resource_size(pp->io);
> > +			pp->io_bus_addr = pp->io->start - win->offset;
> > +			ret = pci_remap_iospace(pp->io, pp->io_base);
> > +			if (ret) {
> > +				dev_warn(pp->dev, "error %d: failed to map
> resource %pR\n",
> > +					 ret, pp->io);
> > +				continue;
> > +			}
> > +			break;
> > +		case IORESOURCE_MEM:
> > +			pp->mem = win->res;
> > +			pp->mem->name = "MEM";
> > +			pp->mem_size = resource_size(pp->mem);
> > +			pp->mem_bus_addr = pp->mem->start - win->offset;
> > +			break;
> > +		case 0:
> > +			pp->cfg = win->res;
> > +			pp->cfg0_size = resource_size(pp->cfg)/2;
> > +			pp->cfg1_size = resource_size(pp->cfg)/2;
> > +			pp->cfg0_base = pp->cfg->start;
> > +			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
> > +			break;
> > +		case IORESOURCE_BUS:
> > +			pp->busn = win->res;
> > +			break;
> > +		default:
> > +			continue;
> >  		}
> >  	}
> >
> > -	ret = of_pci_parse_bus_range(np, &pp->busn);
> > -	if (ret < 0) {
> > -		pp->busn.name = np->name;
> > -		pp->busn.start = 0;
> > -		pp->busn.end = 0xff;
> > -		pp->busn.flags = IORESOURCE_BUS;
> > -		dev_dbg(pp->dev, "failed to parse bus-range property: %d,
> using default %pR\n",
> > -			ret, &pp->busn);
> > -	}
> > -
> >  	if (!pp->dbi_base) {
> > -		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
> > -					resource_size(&pp->cfg));
> > +		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
> > +					resource_size(pp->cfg));
> >  		if (!pp->dbi_base) {
> >  			dev_err(pp->dev, "error with ioremap\n");
> >  			return -ENOMEM;
> >  		}
> >  	}
> >
> > -	pp->mem_base = pp->mem.start;
> > +	pp->mem_base = pp->mem->start;
> >
> >  	if (!pp->va_cfg0_base) {
> >  		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
> > @@ -509,7 +473,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
> >
> >  	if (!pp->ops->rd_other_conf)
> >  		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
> > -					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
> > +					  PCIE_ATU_TYPE_MEM, pp->mem_base,
> >  					  pp->mem_bus_addr, pp->mem_size);
> >
> >  	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
> > @@ -521,15 +485,40 @@ int dw_pcie_host_init(struct pcie_port *pp)
> >  	val |= PORT_LOGIC_SPEED_CHANGE;
> >  	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
> >
> > -#ifdef CONFIG_PCI_MSI
> >  	dw_pcie_msi_chip.dev = pp->dev;
> > -	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> > +
> > +	mutex_lock(&root_bus_nr_mux);
> > +
> > +	if (pp->root_bus_nr != DW_ROOT_NR_UNDEFINED)
> > +		root_bus_nr = pp->root_bus_nr;
> > +
> > +	bus = pci_create_root_bus(pp->dev, root_bus_nr, &dw_pcie_ops,
> > +			      pp, &res);
> > +	if (!bus) {
> > +		mutex_unlock(&root_bus_nr_mux);
> > +		return -ENOMEM;
> > +	}
> > +
> > +	root_bus_nr += bus->busn_res.end + 1;
> > +	mutex_unlock(&root_bus_nr_mux);
> > +
> > +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> > +	bus->msi = container_of(&pp->irq_domain, struct msi_controller,
> domain);
> > +#else
> > +	bus->msi = &dw_pcie_msi_chip;
> >  #endif
> >
> > -	dw_pci.nr_controllers = 1;
> > -	dw_pci.private_data = (void **)&pp;
> > +	pci_scan_child_bus(bus);
> > +	if (pp->ops->scan_bus)
> > +		pp->ops->scan_bus(pp);
> > +
> > +#ifdef CONFIG_ARM
> > +	/* support old dtbs that incorrectly describe IRQs */
> > +	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
> > +#endif
> >
> > -	pci_common_init_dev(pp->dev, &dw_pci);
> > +	pci_assign_unassigned_bus_resources(bus);
> > +	pci_bus_add_devices(bus);
> >
> >  	return 0;
> >  }
> > @@ -548,12 +537,12 @@ static int dw_pcie_rd_other_conf(struct
> pcie_port *pp, struct pci_bus *bus,
> >
> >  	if (bus->parent->number == pp->root_bus_nr) {
> >  		type = PCIE_ATU_TYPE_CFG0;
> > -		cpu_addr = pp->cfg0_mod_base;
> > +		cpu_addr = pp->cfg0_base;
> >  		cfg_size = pp->cfg0_size;
> >  		va_cfg_base = pp->va_cfg0_base;
> >  	} else {
> >  		type = PCIE_ATU_TYPE_CFG1;
> > -		cpu_addr = pp->cfg1_mod_base;
> > +		cpu_addr = pp->cfg1_base;
> >  		cfg_size = pp->cfg1_size;
> >  		va_cfg_base = pp->va_cfg1_base;
> >  	}
> > @@ -563,7 +552,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port
> *pp, struct pci_bus *bus,
> >  				  busdev, cfg_size);
> >  	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
> >  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> > -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> > +				  PCIE_ATU_TYPE_IO, pp->io_base,
> >  				  pp->io_bus_addr, pp->io_size);
> >
> >  	return ret;
> > @@ -583,12 +572,12 @@ static int dw_pcie_wr_other_conf(struct
> pcie_port *pp, struct pci_bus *bus,
> >
> >  	if (bus->parent->number == pp->root_bus_nr) {
> >  		type = PCIE_ATU_TYPE_CFG0;
> > -		cpu_addr = pp->cfg0_mod_base;
> > +		cpu_addr = pp->cfg0_base;
> >  		cfg_size = pp->cfg0_size;
> >  		va_cfg_base = pp->va_cfg0_base;
> >  	} else {
> >  		type = PCIE_ATU_TYPE_CFG1;
> > -		cpu_addr = pp->cfg1_mod_base;
> > +		cpu_addr = pp->cfg1_base;
> >  		cfg_size = pp->cfg1_size;
> >  		va_cfg_base = pp->va_cfg1_base;
> >  	}
> > @@ -598,7 +587,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port
> *pp, struct pci_bus *bus,
> >  				  busdev, cfg_size);
> >  	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
> >  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> > -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> > +				  PCIE_ATU_TYPE_IO, pp->io_base,
> >  				  pp->io_bus_addr, pp->io_size);
> >
> >  	return ret;
> > @@ -630,7 +619,7 @@ static int dw_pcie_valid_config(struct pcie_port
> *pp,
> >  static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> >  			int size, u32 *val)
> >  {
> > -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> > +	struct pcie_port *pp = bus->sysdata;
> >  	int ret;
> >
> >  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
> > @@ -654,7 +643,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus,
> u32 devfn, int where,
> >  static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
> >  			int where, int size, u32 val)
> >  {
> > -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> > +	struct pcie_port *pp = bus->sysdata;
> >  	int ret;
> >
> >  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
> > @@ -678,62 +667,6 @@ static struct pci_ops dw_pcie_ops = {
> >  	.write = dw_pcie_wr_conf,
> >  };
> >
> > -static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
> > -{
> > -	struct pcie_port *pp;
> > -
> > -	pp = sys_to_pcie(sys);
> > -
> > -	if (global_io_offset < SZ_1M && pp->io_size > 0) {
> > -		sys->io_offset = global_io_offset - pp->io_bus_addr;
> > -		pci_ioremap_io(global_io_offset, pp->io_base);
> > -		global_io_offset += SZ_64K;
> > -		pci_add_resource_offset(&sys->resources, &pp->io,
> > -					sys->io_offset);
> > -	}
> > -
> > -	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
> > -	pci_add_resource_offset(&sys->resources, &pp->mem, sys-
> >mem_offset);
> > -	pci_add_resource(&sys->resources, &pp->busn);
> > -
> > -	return 1;
> > -}
> > -
> > -static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data
> *sys)
> > -{
> > -	struct pci_bus *bus;
> > -	struct pcie_port *pp = sys_to_pcie(sys);
> > -
> > -	pp->root_bus_nr = sys->busnr;
> > -	bus = pci_scan_root_bus(pp->dev, sys->busnr,
> > -				  &dw_pcie_ops, sys, &sys->resources);
> > -	if (!bus)
> > -		return NULL;
> > -
> > -	if (bus && pp->ops->scan_bus)
> > -		pp->ops->scan_bus(pp);
> > -
> > -	return bus;
> > -}
> > -
> > -static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8
> pin)
> > -{
> > -	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
> > -	int irq;
> > -
> > -	irq = of_irq_parse_and_map_pci(dev, slot, pin);
> > -	if (!irq)
> > -		irq = pp->irq;
> > -
> > -	return irq;
> > -}
> > -
> > -static struct hw_pci dw_pci = {
> > -	.setup		= dw_pcie_setup,
> > -	.scan		= dw_pcie_scan_bus,
> > -	.map_irq	= dw_pcie_map_irq,
> > -};
> > -
> >  void dw_pcie_setup_rc(struct pcie_port *pp)
> >  {
> >  	u32 val;
> > diff --git a/drivers/pci/host/pcie-designware.h
> b/drivers/pci/host/pcie-designware.h
> > index d0bbd27..0c2a7eb 100644
> > --- a/drivers/pci/host/pcie-designware.h
> > +++ b/drivers/pci/host/pcie-designware.h
> > @@ -21,31 +21,28 @@
> >   */
> >  #define MAX_MSI_IRQS			32
> >  #define MAX_MSI_CTRLS			(MAX_MSI_IRQS / 32)
> > +#define DW_ROOT_NR_UNDEFINED	-1
> >
> >  struct pcie_port {
> >  	struct device		*dev;
> >  	u8			root_bus_nr;
> >  	void __iomem		*dbi_base;
> >  	u64			cfg0_base;
> > -	u64			cfg0_mod_base;
> >  	void __iomem		*va_cfg0_base;
> >  	u32			cfg0_size;
> >  	u64			cfg1_base;
> > -	u64			cfg1_mod_base;
> >  	void __iomem		*va_cfg1_base;
> >  	u32			cfg1_size;
> > -	u64			io_base;
> > -	u64			io_mod_base;
> > +	resource_size_t		io_base;
> >  	phys_addr_t		io_bus_addr;
> >  	u32			io_size;
> >  	u64			mem_base;
> > -	u64			mem_mod_base;
> >  	phys_addr_t		mem_bus_addr;
> >  	u32			mem_size;
> > -	struct resource		cfg;
> > -	struct resource		io;
> > -	struct resource		mem;
> > -	struct resource		busn;
> > +	struct resource		*cfg;
> > +	struct resource		*io;
> > +	struct resource		*mem;
> > +	struct resource		*busn;
> >  	int			irq;
> >  	u32			lanes;
> >  	struct pcie_host_ops	*ops;
> > diff --git a/drivers/pci/host/pcie-spear13xx.c
> b/drivers/pci/host/pcie-spear13xx.c
> > index c49fbdc..b2c59b9 100644
> > --- a/drivers/pci/host/pcie-spear13xx.c
> > +++ b/drivers/pci/host/pcie-spear13xx.c
> > @@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct
> pcie_port *pp,
> >  		return ret;
> >  	}
> >
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
> >  	pp->ops = &spear13xx_pcie_host_ops;
> >
> >  	ret = dw_pcie_host_init(pp);
> > --
> > 1.9.1
> >
> >
> > > -----Original Message-----
> > > From: Lucas Stach [mailto:l.stach@pengutronix.de]
> > > Sent: Wednesday, August 19, 2015 1:54 PM
> > > To: Wangzhou (B)
> > > Cc: Bjorn Helgaas; jingoohan1@gmail.com; Pratyush Anand; Arnd
> Bergmann;
> > > linux@arm.linux.org.uk; thomas.petazzoni@free-electrons.com;
> Gabriele
> > > Paoloni; lorenzo.pieralisi@arm.com; james.morse@arm.com;
> > > Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org; linux-
> > > pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> > > devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> > > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > >
> > > Am Montag, den 17.08.2015, 19:55 +0800 schrieb Zhou Wang:
> > > > This patch tries to unify ARM32 and ARM64 PCIe in designware
> driver.
> > > Delete
> > > > function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and
> struct
> > > hw_pci,
> > > > move related operations to dw_pcie_host_init.
> > > >
> > > > In past, we use:
> > > > pci_common_init_dev
> > > > 	-> pcibios_init_hw
> > > > 		-> hw->scan (dw_pcie_scan_bus)
> > > > to pass 0 to root_bus_nr in struct pcie_port. This patch set pp-
> > > >root_bus_nr = 0
> > > > in each PCIe host driver which is based on pcie-designware.
> > > >
> > > This is incorrect at least if there are 2 instances of DW PCIe host
> in
> > > the same SoC without using PCI domains. In that the case the bus
> range
> > > determines the range of valid bus numbers per instance and the
> first
> > > number is the root bus. Please look at the "bus-range" DT property
> in
> > > the DW PCIe bindings.
> > >
> > > Also we should finally remove this root-bus setup from the glue
> drivers
> > > altogether. It's something that entirely belongs into the DW core
> code.
> > >
> > > Regards,
> > > Lucas
> > >
> > > > This patch also try to use of_pci_get_host_bridge_resources for
> ARM32
> > > and ARM64
> > > > according to the suggestion for Gabriele[1]
> > > >
> > > > Finally this patch reverts commit f4c55c5a3f7f "PCI: designware:
> > > Program ATU
> > > > with untranslated address" based on 1/6 in this series. we delete
> > > *_mod_base in
> > > > pcie-designware. This was discussed in [2]
> > > >
> > > > I have compiled the driver with multi_v7_defconfig. However, I
> don't
> > > have
> > > > ARM32 PCIe related board to do test. It will be appreciated if
> > > someone could
> > > > help to test it.
> > > >
> > > > Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> > > > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > > > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> > > > Tested-By: James Morse <james.morse@arm.com>
> > > >
> > > > [1] http://www.spinics.net/lists/linux-pci/msg42194.html
> > > > [2] http://www.spinics.net/lists/arm-kernel/msg436779.html
> > > > ---
> > > >  drivers/pci/host/pci-dra7xx.c      |  15 +--
> > > >  drivers/pci/host/pci-exynos.c      |   2 +-
> > > >  drivers/pci/host/pci-imx6.c        |   2 +-
> > > >  drivers/pci/host/pci-keystone-dw.c |   2 +-
> > > >  drivers/pci/host/pci-keystone.c    |   2 +-
> > > >  drivers/pci/host/pci-layerscape.c  |   2 +-
> > > >  drivers/pci/host/pcie-designware.c | 229 ++++++++++++-----------
> ----
> > > ----------
> > > >  drivers/pci/host/pcie-designware.h |  14 +--
> > > >  drivers/pci/host/pcie-spear13xx.c  |   2 +-
> > > >  9 files changed, 95 insertions(+), 175 deletions(-)
> > > >
> > > > diff --git a/drivers/pci/host/pci-dra7xx.c
> b/drivers/pci/host/pci-
> > > dra7xx.c
> > > > index 18ae7ff..1268c69 100644
> > > > --- a/drivers/pci/host/pci-dra7xx.c
> > > > +++ b/drivers/pci/host/pci-dra7xx.c
> > > > @@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct
> > > pcie_port *pp)
> > > >  {
> > > >  	dw_pcie_setup_rc(pp);
> > > >
> > > > -	if (pp->io_mod_base)
> > > > -		pp->io_mod_base &= CPU_TO_BUS_ADDR;
> > > > +	if (pp->io_base)
> > > > +		pp->io_base &= CPU_TO_BUS_ADDR;
> > > >
> > > > -	if (pp->mem_mod_base)
> > > > -		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
> > > > +	if (pp->mem_base)
> > > > +		pp->mem_base &= CPU_TO_BUS_ADDR;
> > > >
> > > > -	if (pp->cfg0_mod_base) {
> > > > -		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
> > > > -		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
> > > > +	if (pp->cfg0_base) {
> > > > +		pp->cfg0_base &= CPU_TO_BUS_ADDR;
> > > > +		pp->cfg1_base &= CPU_TO_BUS_ADDR;
> > > >  	}
> > > >
> > > >  	dra7xx_pcie_establish_link(pp);
> > > > @@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct
> > > dra7xx_pcie *dra7xx,
> > > >
> > > >  	pp = &dra7xx->pp;
> > > >  	pp->dev = dev;
> > > > +	pp->root_bus_nr = 0;
> > > >  	pp->ops = &dra7xx_pcie_host_ops;
> > > >
> > > >  	pp->irq = platform_get_irq(pdev, 1);
> > > > diff --git a/drivers/pci/host/pci-exynos.c
> b/drivers/pci/host/pci-
> > > exynos.c
> > > > index f9f468d..9771bb0 100644
> > > > --- a/drivers/pci/host/pci-exynos.c
> > > > +++ b/drivers/pci/host/pci-exynos.c
> > > > @@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct
> > > pcie_port *pp,
> > > >  		}
> > > >  	}
> > > >
> > > > -	pp->root_bus_nr = -1;
> > > > +	pp->root_bus_nr = 0;
> > > >  	pp->ops = &exynos_pcie_host_ops;
> > > >
> > > >  	ret = dw_pcie_host_init(pp);
> > > > diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-
> > > imx6.c
> > > > index 233a196..bec256c 100644
> > > > --- a/drivers/pci/host/pci-imx6.c
> > > > +++ b/drivers/pci/host/pci-imx6.c
> > > > @@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct
> > > pcie_port *pp,
> > > >  		}
> > > >  	}
> > > >
> > > > -	pp->root_bus_nr = -1;
> > > > +	pp->root_bus_nr = 0;
> > > >  	pp->ops = &imx6_pcie_host_ops;
> > > >
> > > >  	ret = dw_pcie_host_init(pp);
> > > > diff --git a/drivers/pci/host/pci-keystone-dw.c
> > > b/drivers/pci/host/pci-keystone-dw.c
> > > > index f34892e..b1e4135 100644
> > > > --- a/drivers/pci/host/pci-keystone-dw.c
> > > > +++ b/drivers/pci/host/pci-keystone-dw.c
> > > > @@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void
> > > __iomem *reg_virt)
> > > >  void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
> > > >  {
> > > >  	struct pcie_port *pp = &ks_pcie->pp;
> > > > -	u32 start = pp->mem.start, end = pp->mem.end;
> > > > +	u32 start = pp->mem->start, end = pp->mem->end;
> > > >  	int i, tr_size;
> > > >
> > > >  	/* Disable BARs for inbound access */
> > > > diff --git a/drivers/pci/host/pci-keystone.c
> b/drivers/pci/host/pci-
> > > keystone.c
> > > > index 734da58..8113832 100644
> > > > --- a/drivers/pci/host/pci-keystone.c
> > > > +++ b/drivers/pci/host/pci-keystone.c
> > > > @@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct
> > > keystone_pcie *ks_pcie,
> > > >  			return ret;
> > > >  	}
> > > >
> > > > -	pp->root_bus_nr = -1;
> > > > +	pp->root_bus_nr = 0;
> > > >  	pp->ops = &keystone_pcie_host_ops;
> > > >  	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
> > > >  	if (ret) {
> > > > diff --git a/drivers/pci/host/pci-layerscape.c
> > > b/drivers/pci/host/pci-layerscape.c
> > > > index b2328ea1..79ff08c 100644
> > > > --- a/drivers/pci/host/pci-layerscape.c
> > > > +++ b/drivers/pci/host/pci-layerscape.c
> > > > @@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie
> *pcie)
> > > >  	pp = &pcie->pp;
> > > >  	pp->dev = pcie->dev;
> > > >  	pp->dbi_base = pcie->dbi;
> > > > -	pp->root_bus_nr = -1;
> > > > +	pp->root_bus_nr = 0;
> > > >  	pp->ops = &ls_pcie_host_ops;
> > > >
> > > >  	ret = dw_pcie_host_init(pp);
> > > > diff --git a/drivers/pci/host/pcie-designware.c
> > > b/drivers/pci/host/pcie-designware.c
> > > > index c5d407c..e71a88e 100644
> > > > --- a/drivers/pci/host/pcie-designware.c
> > > > +++ b/drivers/pci/host/pcie-designware.c
> > > > @@ -11,6 +11,7 @@
> > > >   * published by the Free Software Foundation.
> > > >   */
> > > >
> > > > +#include <linux/hardirq.h>
> > > >  #include <linux/irq.h>
> > > >  #include <linux/irqdomain.h>
> > > >  #include <linux/kernel.h>
> > > > @@ -69,16 +70,7 @@
> > > >  #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
> > > >  #define PCIE_ATU_UPPER_TARGET		0x91C
> > > >
> > > > -static struct hw_pci dw_pci;
> > > > -
> > > > -static unsigned long global_io_offset;
> > > > -
> > > > -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data
> *sys)
> > > > -{
> > > > -	BUG_ON(!sys->private_data);
> > > > -
> > > > -	return sys->private_data;
> > > > -}
> > > > +static struct pci_ops dw_pcie_ops;
> > > >
> > > >  int dw_pcie_cfg_read(void __iomem *addr, int where, int size,
> u32
> > > *val)
> > > >  {
> > > > @@ -255,7 +247,7 @@ static void dw_pcie_msi_set_irq(struct
> pcie_port
> > > *pp, int irq)
> > > >  static int assign_irq(int no_irqs, struct msi_desc *desc, int
> *pos)
> > > >  {
> > > >  	int irq, pos0, i;
> > > > -	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
> > > > +	struct pcie_port *pp = desc->dev->bus->sysdata;
> > > >
> > > >  	pos0 = bitmap_find_free_region(pp->msi_irq_in_use,
> MAX_MSI_IRQS,
> > > >  				       order_base_2(no_irqs));
> > > > @@ -298,7 +290,7 @@ static int dw_msi_setup_irq(struct
> msi_controller
> > > *chip, struct pci_dev *pdev,
> > > >  {
> > > >  	int irq, pos;
> > > >  	struct msi_msg msg;
> > > > -	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
> > > > +	struct pcie_port *pp = pdev->bus->sysdata;
> > > >
> > > >  	if (desc->msi_attrib.is_msix)
> > > >  		return -EINVAL;
> > > > @@ -327,7 +319,7 @@ static void dw_msi_teardown_irq(struct
> > > msi_controller *chip, unsigned int irq)
> > > >  {
> > > >  	struct irq_data *data = irq_get_irq_data(irq);
> > > >  	struct msi_desc *msi = irq_data_get_msi(data);
> > > > -	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
> > > > +	struct pcie_port *pp = msi->dev->bus->sysdata;
> > > >
> > > >  	clear_irq_range(pp, irq, 1, data->hwirq);
> > > >  }
> > > > @@ -363,14 +355,12 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > > >  {
> > > >  	struct device_node *np = pp->dev->of_node;
> > > >  	struct platform_device *pdev = to_platform_device(pp->dev);
> > > > -	struct of_pci_range range;
> > > > -	struct of_pci_range_parser parser;
> > > > +	struct pci_bus *bus;
> > > >  	struct resource *cfg_res;
> > > > -	u32 val, ns;
> > > > -	const __be32 *addrp;
> > > > -	int i, index, ret;
> > > > -
> > > > -	ns = of_n_size_cells(np);
> > > > +	LIST_HEAD(res);
> > > > +	u32 val;
> > > > +	int i, ret;
> > > > +	struct resource_entry *win;
> > > >
> > > >  	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> > > "config");
> > > >  	if (cfg_res) {
> > > > @@ -378,85 +368,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > > >  		pp->cfg1_size = resource_size(cfg_res)/2;
> > > >  		pp->cfg0_base = cfg_res->start;
> > > >  		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
> > > > -
> > > > -		/* Find the untranslated configuration space address
> */
> > > > -		index = of_property_match_string(np, "reg-names",
> "config");
> > > > -		addrp = of_get_address(np, index, NULL, NULL);
> > > > -		pp->cfg0_mod_base = of_read_number(addrp, ns);
> > > > -		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
> > > >  	} else {
> > > >  		dev_err(pp->dev, "missing *config* reg space\n");
> > > >  	}
> > > >
> > > > -	if (of_pci_range_parser_init(&parser, np)) {
> > > > -		dev_err(pp->dev, "missing ranges property\n");
> > > > -		return -EINVAL;
> > > > -	}
> > > > +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res,
> &pp-
> > > >io_base);
> > > > +	if (ret)
> > > > +		return ret;
> > > >
> > > >  	/* Get the I/O and memory ranges from DT */
> > > > -	for_each_of_pci_range(&parser, &range) {
> > > > -		unsigned long restype = range.flags &
> IORESOURCE_TYPE_BITS;
> > > > -
> > > > -		if (restype == IORESOURCE_IO) {
> > > > -			of_pci_range_to_resource(&range, np, &pp->io);
> > > > -			pp->io.name = "I/O";
> > > > -			pp->io.start = max_t(resource_size_t,
> > > > -					     PCIBIOS_MIN_IO,
> > > > -					     range.pci_addr +
> global_io_offset);
> > > > -			pp->io.end = min_t(resource_size_t,
> > > > -					   IO_SPACE_LIMIT,
> > > > -					   range.pci_addr + range.size
> > > > -					   + global_io_offset - 1);
> > > > -			pp->io_size = resource_size(&pp->io);
> > > > -			pp->io_bus_addr = range.pci_addr;
> > > > -			pp->io_base = range.cpu_addr;
> > > > -
> > > > -			/* Find the untranslated IO space address */
> > > > -			pp->io_mod_base = range.cpu_addr;
> > > > -		}
> > > > -		if (restype == IORESOURCE_MEM) {
> > > > -			of_pci_range_to_resource(&range, np, &pp->mem);
> > > > -			pp->mem.name = "MEM";
> > > > -			pp->mem_size = resource_size(&pp->mem);
> > > > -			pp->mem_bus_addr = range.pci_addr;
> > > > -
> > > > -			/* Find the untranslated MEM space address */
> > > > -			pp->mem_mod_base = range.cpu_addr;
> > > > -		}
> > > > -		if (restype == 0) {
> > > > -			of_pci_range_to_resource(&range, np, &pp->cfg);
> > > > -			pp->cfg0_size = resource_size(&pp->cfg)/2;
> > > > -			pp->cfg1_size = resource_size(&pp->cfg)/2;
> > > > -			pp->cfg0_base = pp->cfg.start;
> > > > -			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
> > > > -
> > > > -			/* Find the untranslated configuration space
> address
> > > */
> > > > -			pp->cfg0_mod_base = range.cpu_addr;
> > > > -			pp->cfg1_mod_base = pp->cfg0_mod_base +
> > > > -					    pp->cfg0_size;
> > > > +	resource_list_for_each_entry(win, &res) {
> > > > +		switch (resource_type(win->res)) {
> > > > +		case IORESOURCE_IO:
> > > > +			pp->io = win->res;
> > > > +			pp->io->name = "I/O";
> > > > +			pp->io_size = resource_size(pp->io);
> > > > +			pp->io_bus_addr = pp->io->start - win->offset;
> > > > +			ret = pci_remap_iospace(pp->io, pp->io_base);
> > > > +			if (ret) {
> > > > +				dev_warn(pp->dev, "error %d: failed to
> map
> > > resource %pR\n",
> > > > +					 ret, pp->io);
> > > > +				continue;
> > > > +			}
> > > > +			break;
> > > > +		case IORESOURCE_MEM:
> > > > +			pp->mem = win->res;
> > > > +			pp->mem->name = "MEM";
> > > > +			pp->mem_size = resource_size(pp->mem);
> > > > +			pp->mem_bus_addr = pp->mem->start - win->offset;
> > > > +			break;
> > > > +		case 0:
> > > > +			pp->cfg = win->res;
> > > > +			pp->cfg0_size = resource_size(pp->cfg)/2;
> > > > +			pp->cfg1_size = resource_size(pp->cfg)/2;
> > > > +			pp->cfg0_base = pp->cfg->start;
> > > > +			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
> > > > +			break;
> > > > +		case IORESOURCE_BUS:
> > > > +			pp->busn = win->res;
> > > > +			break;
> > > > +		default:
> > > > +			continue;
> > > >  		}
> > > >  	}
> > > >
> > > > -	ret = of_pci_parse_bus_range(np, &pp->busn);
> > > > -	if (ret < 0) {
> > > > -		pp->busn.name = np->name;
> > > > -		pp->busn.start = 0;
> > > > -		pp->busn.end = 0xff;
> > > > -		pp->busn.flags = IORESOURCE_BUS;
> > > > -		dev_dbg(pp->dev, "failed to parse bus-range
> property: %d,
> > > using default %pR\n",
> > > > -			ret, &pp->busn);
> > > > -	}
> > > > -
> > > >  	if (!pp->dbi_base) {
> > > > -		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
> > > > -					resource_size(&pp->cfg));
> > > > +		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
> > > > +					resource_size(pp->cfg));
> > > >  		if (!pp->dbi_base) {
> > > >  			dev_err(pp->dev, "error with ioremap\n");
> > > >  			return -ENOMEM;
> > > >  		}
> > > >  	}
> > > >
> > > > -	pp->mem_base = pp->mem.start;
> > > > +	pp->mem_base = pp->mem->start;
> > > >
> > > >  	if (!pp->va_cfg0_base) {
> > > >  		pp->va_cfg0_base = devm_ioremap(pp->dev, pp-
> >cfg0_base,
> > > > @@ -505,7 +470,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > > >
> > > >  	if (!pp->ops->rd_other_conf)
> > > >  		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
> > > > -					  PCIE_ATU_TYPE_MEM, pp-
> >mem_mod_base,
> > > > +					  PCIE_ATU_TYPE_MEM, pp->mem_base,
> > > >  					  pp->mem_bus_addr, pp->mem_size);
> > > >
> > > >  	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
> > > > @@ -517,15 +482,29 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > > >  	val |= PORT_LOGIC_SPEED_CHANGE;
> > > >  	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,
> val);
> > > >
> > > > -#ifdef CONFIG_PCI_MSI
> > > > +	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr,
> &dw_pcie_ops,
> > > > +				  pp, &res);
> > > > +	if (!bus)
> > > > +		return -ENOMEM;
> > > > +
> > > > +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> > > > +	bus->msi = container_of(&pp->irq_domain, struct
> msi_controller,
> > > domain);
> > > > +#else
> > > >  	dw_pcie_msi_chip.dev = pp->dev;
> > > > -	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> > > > +	bus->msi = &dw_pcie_msi_chip;
> > > >  #endif
> > > >
> > > > -	dw_pci.nr_controllers = 1;
> > > > -	dw_pci.private_data = (void **)&pp;
> > > > +	pci_scan_child_bus(bus);
> > > > +	if (pp->ops->scan_bus)
> > > > +		pp->ops->scan_bus(pp);
> > > > +
> > > > +#ifdef CONFIG_ARM
> > > > +	/* support old dtbs that incorrectly describe IRQs */
> > > > +	pci_fixup_irqs(pci_common_swizzle,
> of_irq_parse_and_map_pci);
> > > > +#endif
> > > >
> > > > -	pci_common_init_dev(pp->dev, &dw_pci);
> > > > +	pci_assign_unassigned_bus_resources(bus);
> > > > +	pci_bus_add_devices(bus);
> > > >
> > > >  	return 0;
> > > >  }
> > > > @@ -544,12 +523,12 @@ static int dw_pcie_rd_other_conf(struct
> > > pcie_port *pp, struct pci_bus *bus,
> > > >
> > > >  	if (bus->parent->number == pp->root_bus_nr) {
> > > >  		type = PCIE_ATU_TYPE_CFG0;
> > > > -		cpu_addr = pp->cfg0_mod_base;
> > > > +		cpu_addr = pp->cfg0_base;
> > > >  		cfg_size = pp->cfg0_size;
> > > >  		va_cfg_base = pp->va_cfg0_base;
> > > >  	} else {
> > > >  		type = PCIE_ATU_TYPE_CFG1;
> > > > -		cpu_addr = pp->cfg1_mod_base;
> > > > +		cpu_addr = pp->cfg1_base;
> > > >  		cfg_size = pp->cfg1_size;
> > > >  		va_cfg_base = pp->va_cfg1_base;
> > > >  	}
> > > > @@ -559,7 +538,7 @@ static int dw_pcie_rd_other_conf(struct
> pcie_port
> > > *pp, struct pci_bus *bus,
> > > >  				  busdev, cfg_size);
> > > >  	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size,
> val);
> > > >  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> > > > -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> > > > +				  PCIE_ATU_TYPE_IO, pp->io_base,
> > > >  				  pp->io_bus_addr, pp->io_size);
> > > >
> > > >  	return ret;
> > > > @@ -579,12 +558,12 @@ static int dw_pcie_wr_other_conf(struct
> > > pcie_port *pp, struct pci_bus *bus,
> > > >
> > > >  	if (bus->parent->number == pp->root_bus_nr) {
> > > >  		type = PCIE_ATU_TYPE_CFG0;
> > > > -		cpu_addr = pp->cfg0_mod_base;
> > > > +		cpu_addr = pp->cfg0_base;
> > > >  		cfg_size = pp->cfg0_size;
> > > >  		va_cfg_base = pp->va_cfg0_base;
> > > >  	} else {
> > > >  		type = PCIE_ATU_TYPE_CFG1;
> > > > -		cpu_addr = pp->cfg1_mod_base;
> > > > +		cpu_addr = pp->cfg1_base;
> > > >  		cfg_size = pp->cfg1_size;
> > > >  		va_cfg_base = pp->va_cfg1_base;
> > > >  	}
> > > > @@ -594,7 +573,7 @@ static int dw_pcie_wr_other_conf(struct
> pcie_port
> > > *pp, struct pci_bus *bus,
> > > >  				  busdev, cfg_size);
> > > >  	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size,
> val);
> > > >  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> > > > -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> > > > +				  PCIE_ATU_TYPE_IO, pp->io_base,
> > > >  				  pp->io_bus_addr, pp->io_size);
> > > >
> > > >  	return ret;
> > > > @@ -626,7 +605,7 @@ static int dw_pcie_valid_config(struct
> pcie_port
> > > *pp,
> > > >  static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int
> where,
> > > >  			int size, u32 *val)
> > > >  {
> > > > -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> > > > +	struct pcie_port *pp = bus->sysdata;
> > > >  	int ret;
> > > >
> > > >  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
> > > > @@ -650,7 +629,7 @@ static int dw_pcie_rd_conf(struct pci_bus
> *bus,
> > > u32 devfn, int where,
> > > >  static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
> > > >  			int where, int size, u32 val)
> > > >  {
> > > > -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> > > > +	struct pcie_port *pp = bus->sysdata;
> > > >  	int ret;
> > > >
> > > >  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
> > > > @@ -674,62 +653,6 @@ static struct pci_ops dw_pcie_ops = {
> > > >  	.write = dw_pcie_wr_conf,
> > > >  };
> > > >
> > > > -static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
> > > > -{
> > > > -	struct pcie_port *pp;
> > > > -
> > > > -	pp = sys_to_pcie(sys);
> > > > -
> > > > -	if (global_io_offset < SZ_1M && pp->io_size > 0) {
> > > > -		sys->io_offset = global_io_offset - pp->io_bus_addr;
> > > > -		pci_ioremap_io(global_io_offset, pp->io_base);
> > > > -		global_io_offset += SZ_64K;
> > > > -		pci_add_resource_offset(&sys->resources, &pp->io,
> > > > -					sys->io_offset);
> > > > -	}
> > > > -
> > > > -	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
> > > > -	pci_add_resource_offset(&sys->resources, &pp->mem, sys-
> > > >mem_offset);
> > > > -	pci_add_resource(&sys->resources, &pp->busn);
> > > > -
> > > > -	return 1;
> > > > -}
> > > > -
> > > > -static struct pci_bus *dw_pcie_scan_bus(int nr, struct
> pci_sys_data
> > > *sys)
> > > > -{
> > > > -	struct pci_bus *bus;
> > > > -	struct pcie_port *pp = sys_to_pcie(sys);
> > > > -
> > > > -	pp->root_bus_nr = sys->busnr;
> > > > -	bus = pci_scan_root_bus(pp->dev, sys->busnr,
> > > > -				  &dw_pcie_ops, sys, &sys->resources);
> > > > -	if (!bus)
> > > > -		return NULL;
> > > > -
> > > > -	if (bus && pp->ops->scan_bus)
> > > > -		pp->ops->scan_bus(pp);
> > > > -
> > > > -	return bus;
> > > > -}
> > > > -
> > > > -static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot,
> u8
> > > pin)
> > > > -{
> > > > -	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
> > > > -	int irq;
> > > > -
> > > > -	irq = of_irq_parse_and_map_pci(dev, slot, pin);
> > > > -	if (!irq)
> > > > -		irq = pp->irq;
> > > > -
> > > > -	return irq;
> > > > -}
> > > > -
> > > > -static struct hw_pci dw_pci = {
> > > > -	.setup		= dw_pcie_setup,
> > > > -	.scan		= dw_pcie_scan_bus,
> > > > -	.map_irq	= dw_pcie_map_irq,
> > > > -};
> > > > -
> > > >  void dw_pcie_setup_rc(struct pcie_port *pp)
> > > >  {
> > > >  	u32 val;
> > > > diff --git a/drivers/pci/host/pcie-designware.h
> > > b/drivers/pci/host/pcie-designware.h
> > > > index d0bbd27..264c969 100644
> > > > --- a/drivers/pci/host/pcie-designware.h
> > > > +++ b/drivers/pci/host/pcie-designware.h
> > > > @@ -27,25 +27,21 @@ struct pcie_port {
> > > >  	u8			root_bus_nr;
> > > >  	void __iomem		*dbi_base;
> > > >  	u64			cfg0_base;
> > > > -	u64			cfg0_mod_base;
> > > >  	void __iomem		*va_cfg0_base;
> > > >  	u32			cfg0_size;
> > > >  	u64			cfg1_base;
> > > > -	u64			cfg1_mod_base;
> > > >  	void __iomem		*va_cfg1_base;
> > > >  	u32			cfg1_size;
> > > > -	u64			io_base;
> > > > -	u64			io_mod_base;
> > > > +	resource_size_t		io_base;
> > > >  	phys_addr_t		io_bus_addr;
> > > >  	u32			io_size;
> > > >  	u64			mem_base;
> > > > -	u64			mem_mod_base;
> > > >  	phys_addr_t		mem_bus_addr;
> > > >  	u32			mem_size;
> > > > -	struct resource		cfg;
> > > > -	struct resource		io;
> > > > -	struct resource		mem;
> > > > -	struct resource		busn;
> > > > +	struct resource		*cfg;
> > > > +	struct resource		*io;
> > > > +	struct resource		*mem;
> > > > +	struct resource		*busn;
> > > >  	int			irq;
> > > >  	u32			lanes;
> > > >  	struct pcie_host_ops	*ops;
> > > > diff --git a/drivers/pci/host/pcie-spear13xx.c
> > > b/drivers/pci/host/pcie-spear13xx.c
> > > > index c49fbdc..03eb204 100644
> > > > --- a/drivers/pci/host/pcie-spear13xx.c
> > > > +++ b/drivers/pci/host/pcie-spear13xx.c
> > > > @@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct
> > > pcie_port *pp,
> > > >  		return ret;
> > > >  	}
> > > >
> > > > -	pp->root_bus_nr = -1;
> > > > +	pp->root_bus_nr = 0;
> > > >  	pp->ops = &spear13xx_pcie_host_ops;
> > > >
> > > >  	ret = dw_pcie_host_init(pp);
> > >
> > > --
> > > Pengutronix e.K.             | Lucas Stach                 |
> > > Industrial Linux Solutions   | http://www.pengutronix.de/  |
> >
> 
> --
> Pengutronix e.K.             | Lucas Stach                 |
> Industrial Linux Solutions   | http://www.pengutronix.de/  |


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

* RE: [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-19 16:34           ` Gabriele Paoloni
  0 siblings, 0 replies; 53+ messages in thread
From: Gabriele Paoloni @ 2015-08-19 16:34 UTC (permalink / raw)
  To: Lucas Stach
  Cc: Wangzhou (B),
	Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, lorenzo.pieralisi, james.morse, Liviu.Dudau,
	jason, robh, linux-pci, linux-arm-kernel, devicetree,
	Yuanzhichang, Zhudacai, zhangjukuo, qiuzhenfa, liudongdong (C),
	qiujiang, xuwei (O), Liguozhu (Kenneth)

SGkgTHVjYXMNCg0KRmlyc3Qgb2YgYWxsIG1hbnkgdGhhbmtzIGZvciB0aGUgcXVpY2sgcmVwbHks
IHJlYWxseSBhcHByZWNpYXRlZA0KDQo+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+IEZy
b206IEx1Y2FzIFN0YWNoIFttYWlsdG86bC5zdGFjaEBwZW5ndXRyb25peC5kZV0NCj4gU2VudDog
V2VkbmVzZGF5LCBBdWd1c3QgMTksIDIwMTUgNDozNyBQTQ0KPiBUbzogR2FicmllbGUgUGFvbG9u
aQ0KPiBDYzogV2FuZ3pob3UgKEIpOyBCam9ybiBIZWxnYWFzOyBqaW5nb29oYW4xQGdtYWlsLmNv
bTsgUHJhdHl1c2ggQW5hbmQ7DQo+IEFybmQgQmVyZ21hbm47IGxpbnV4QGFybS5saW51eC5vcmcu
dWs7IHRob21hcy5wZXRhenpvbmlAZnJlZS0NCj4gZWxlY3Ryb25zLmNvbTsgbG9yZW56by5waWVy
YWxpc2lAYXJtLmNvbTsgamFtZXMubW9yc2VAYXJtLmNvbTsNCj4gTGl2aXUuRHVkYXVAYXJtLmNv
bTsgamFzb25AbGFrZWRhZW1vbi5uZXQ7IHJvYmhAa2VybmVsLm9yZzsgbGludXgtDQo+IHBjaUB2
Z2VyLmtlcm5lbC5vcmc7IGxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZzsNCj4g
ZGV2aWNldHJlZUB2Z2VyLmtlcm5lbC5vcmc7IFl1YW56aGljaGFuZzsgWmh1ZGFjYWk7IHpoYW5n
anVrdW87DQo+IHFpdXpoZW5mYTsgbGl1ZG9uZ2RvbmcgKEMpOyBxaXVqaWFuZzsgeHV3ZWkgKE8p
OyBMaWd1b3podSAoS2VubmV0aCkNCj4gU3ViamVjdDogUmU6IFtQQVRDSCB2NyAzLzZdIFBDSTog
ZGVzaWdud2FyZTogQWRkIEFSTTY0IHN1cHBvcnQNCj4gDQo+IEhpIEdhYiwNCj4gDQo+IEFtIE1p
dHR3b2NoLCBkZW4gMTkuMDguMjAxNSwgMTU6MTYgKzAwMDAgc2NocmllYiBHYWJyaWVsZSBQYW9s
b25pOg0KPiA+IEhpIEx1Y2FzDQo+ID4NCj4gPiBJIGhhdmUgcmV3cml0dGVuIHRoZSBwYXRjaCB0
byB0YWtlIGludG8gYWNjb3VudCBtdWx0aXBsZSBjb250cm9sbGVycy4NCj4gPg0KPiA+IEFzIHlv
dSBjYW4gc2VlIG5vdyB0aGVyZSBpcyBhIHN0YXRpYyB2YXIgaW4gZHdfcGNpZV9ob3N0X2luaXQo
KSB0aGF0DQo+IHRyYWNrcw0KPiA+IHRoZSBidXMgbnVtYmVycyB1c2VkLg0KPiANCj4gVGhpcyBp
cyB3cm9uZy4gVGhlIERUIHNwZWNpZmllcyB0aGUgdmFsaWQgYnVzIG51bWJlciByYW5nZS4gWW91
IGNhbiBub3QNCj4ganVzdCBhc3NpZ24gdGhlIG5leHQgZnJlZSBidXMgbnVtYmVyIHRvIHRoZSBy
b290IGJ1cy4NCg0KSSB0aGluayB0aGlzIGlzIHdoYXQgaXMgYmVpbmcgZG9uZSBpbg0KaHR0cDov
L2x4ci5mcmVlLWVsZWN0cm9ucy5jb20vc291cmNlL2FyY2gvYXJtL2tlcm5lbC9iaW9zMzIuYyNM
NDk1DQphbmQgY3VycmVudGx5IGRlc2lnbndhcmUgYXNzaWducyB0aGUgcm9vdCBidXMgbnVtYmVy
IGluDQpodHRwOi8vbHhyLmZyZWUtZWxlY3Ryb25zLmNvbS9zb3VyY2UvZHJpdmVycy9wY2kvaG9z
dC9wY2llLWRlc2lnbndhcmUuYyNMNzMwDQoNCg0KSW4gZ2VuZXJhbCBJIGFncmVlIHdpdGggeW91
IGJ1dCBpZiB5b3UgbG9vayBhdCBhbGwgdGhlIGN1cnJlbnQgZHJpdmVycyANCmJhc2VkIG9uIGRl
c2lnbndhcmUgbm9uZSBvZiB0aGVtIGRlZmluZSB0aGUgImJ1cy1yYW5nZSIgZHRiIHByb3BlcnR5
Lg0KVGhlcmVmb3JlIGRvaW5nIGFzIHlvdSBzYXkgd291bGQgYnJlYWsgdGhlIGN1cnJlbnQgZHJp
dmVyIHdoZW4gd2UgaGF2ZQ0KbXVsdGlwbGUgY29udHJvbGxlcnMuLi5hbSBJIHJpZ2h0Pw0KDQpJ
ZiB0aGF0IGlzIHRoZSBjYXNlIGluIG9yZGVyIHRvIGZpeCB0aGlzIGluIHRoZSB3YXkgeW91IHNh
eSBJIHdvdWxkIG5lZWQNCnRvIGFzc2lnbiAiYnVzLXJhbmdlIiBmb3IgYWxsIHRoZSBQQ0llIGRy
aXZlcnMgd2l0aCBtdWx0aXBsZSBjb250cm9sbGVyczoNCmluIHRoaXMgY2FzZSBJIHdvdWxkIHNw
bGl0IHRoZSBkZWZhdWx0IHJhbmdlIGV2ZW5seSAodGhhdCBpcywgaWYgd2UgaGF2ZSANCnR3byBj
b250cm9sbGVycyBJIHdvdWxkIGRlZmluZSAiYnVzLXJhbmdlIiAgMC0xMjcgYW5kIDEyOC0yNTUp
DQoNCklmIHlvdSB0aGluayB0aGlzIHNvbHV0aW9uIGlzIG9rIEkgY2FuIGdvIGZvciBpdC4gTXkg
b25seSBkb3VidCB3YXMgYWJvdXQNCnRvdWNoaW5nIG90aGVyIHZlbmRvcnMgRFRCcy4uLi4NCg0K
DQo+IA0KPiBJdCBpcyBwZXJmZWN0bHkgdmFsaWQgdG8gaGF2ZSBhIGJ1cyByYW5nZSBvZiAweDAw
LTB4MTAgYXNzaWduZWQgdG8gb25lDQo+IGluc3RhbmNlIGFuZCAweDUwLTB4ZmYgdG8gdGhlIG5l
eHQgaW5zdGFuY2UuIEFkZGl0aW9uYWwgd2l0aCBQQ0llDQo+IGhvdHBsdWcgeW91IG1heSBub3Qg
dXNlIHRoZSBmdWxsIHJhbmdlIG9mIHRoZSBidXMgbnVtYmVycyBvbiBvbmUNCj4gaW5zdGFuY2Ug
YXQgdGhlIGZpcnN0IHNjYW4sIGJ1dCBvbmx5IGxhdGVyIHBvcHVsYXRlIG1vcmUgYnVzZXMgd2hl
bg0KPiBtb3JlDQo+IGJyaWRnZXMgYXJlIGFkZGVkIHRvIHRoZSB0cmVlLg0KPiANCj4gPiBEcml2
ZXJzIHRoYXQgZG8gbm90IHNwZWNpZnkgdGhlIGJ1cyByYW5nZSBpbiB0aGUgRFRCIHNldCBwcC0N
Cj4gPnJvb3RfYnVzX25yID0gRFdfUk9PVF9OUl9VTkRFRklORUQuDQo+ID4gRGVzaWdud2FyZSB3
aWxsIGNoZWNrIGlmIHRoZSBmbGFnIGlzIHNldCBhbmQgd2lsbCB1c2UgdGhlIGF1dG9tYXRpYw0K
PiBidXMgcmFuZ2UNCj4gPiBhc3NpZ25tZW50Lg0KPiANCj4gTm8sIHBsZWFzZSBsZXRzIGdldCBy
aWQgb2YgdGhpcyBhc3NpZ25tZW50IGFsdG9nZXRoZXIuIFRoZSBnbHVlIGRyaXZlcnMNCj4gaGF2
ZSBubyBidXNpbmVzcyBpbiBhc3NpZ25pbmcgdGhlIGJ1cyByYW5nZS4gUGxlYXNlIHJlbW92ZSB0
aGUNCj4gcHAtPnJvb3RfYnVzX25yIGFzc2lnbm1lbnQgZnJvbSBhbGwgdGhlIGdsdWUgZHJpdmVy
cy4NCj4gDQo+ICJidXMgcmFuZ2UiIGlzIGEgZ2VuZXJpYyBEVyBQQ0llIHByb3BlcnR5LCBzbyBq
dXN0IHBhcnNlIHRoZSByb290IGJ1cw0KPiBudW1iZXIgZnJvbSB0aGUgRFQsIGl0IGlzIGhhbmRs
ZWQgdGhlIHNhbWUgd2F5IGZvciBhbGwgdGhlIERXIGJhc2VkDQo+IFBDSWUNCj4gZHJpdmVycy4g
VGhlIGJpbmRpbmdzIHNwZWNpZmllcyB0aGF0IGlmIHRoZSBidXMgcmFuZ2UgcHJvcGVydHkgaXMN
Cj4gbWlzc2luZyB0aGUgcmFuZ2UgaXMgMHgwMC0weGZmLCBzbyB5b3UgY2FuIGRlZmF1bHQgdG8g
MCBhcyB0aGUgcm9vdCBidXMNCj4gbnVtYmVyIGluIHRoYXQgY2FzZS4NCj4gDQo+IEFsc28gSSB3
b3VsZCB0aGluayB0aGlzIGNvbnZlcnNpb24gd2FycmFudHMgYSBwYXRjaCBvbiBpdHMgb3duIGFu
ZA0KPiBzaG91bGQgbm90IGJlIG1peGVkIGluIHRoZSBBUk02NCBzdXBwb3J0IHBhdGNoLg0KPiAN
Cj4gUmVnYXJkcywNCj4gTHVjYXMNCj4gDQo+ID4gSW5zdGVhZCBpZiB0aGUgZHJpdmVyIGFzc2ln
bnMgcHAtPnJvb3RfYnVzX25yIGFjY29yZGluZyB0byB0aGUgZHRiLA0KPiBkZXNpZ253d2FyZQ0K
PiA+IHdpbGwgdXNlIHRoZSB2YWx1ZSBwYXNzZWQgaW4gYnkgdGhlIGRyaXZlci4NCj4gPiBCZWxv
dyB0aGUgcmVsZXZhbnQgc2VjdGlvbjoNCj4gPg0KPiA+DQo+ID4gKwlzdGF0aWMgaW50IHJvb3Rf
YnVzX25yID0gMDsNCj4gPiAuLi4NCj4gPiArCW11dGV4X2xvY2soJnJvb3RfYnVzX25yX211eCk7
DQo+ID4gKw0KPiA+ICsJaWYgKHBwLT5yb290X2J1c19uciAhPSBEV19ST09UX05SX1VOREVGSU5F
RCkNCj4gPiArCQlyb290X2J1c19uciA9IHBwLT5yb290X2J1c19ucjsNCj4gPiArDQo+ID4gKwli
dXMgPSBwY2lfY3JlYXRlX3Jvb3RfYnVzKHBwLT5kZXYsIHJvb3RfYnVzX25yLCAmZHdfcGNpZV9v
cHMsDQo+ID4gKwkJCSAgICAgIHBwLCAmcmVzKTsNCj4gPiArCWlmICghYnVzKSB7DQo+ID4gKwkJ
bXV0ZXhfdW5sb2NrKCZyb290X2J1c19ucl9tdXgpOw0KPiA+ICsJCXJldHVybiAtRU5PTUVNOw0K
PiA+ICsJfQ0KPiA+ICsNCj4gPiArCXJvb3RfYnVzX25yICs9IGJ1cy0+YnVzbl9yZXMuZW5kICsg
MTsNCj4gPiArCW11dGV4X3VubG9jaygmcm9vdF9idXNfbnJfbXV4KTsNCj4gPg0KPiA+IFBsZWFz
ZSBsZXQgbWUga25vdyB3aGF0IHlvdSB0aGluay4uLg0KPiA+DQo+ID4gTWFueSBUaGFua3MNCj4g
Pg0KPiA+IEdhYg0KPiA+IC0tLS0tLS0tLS0NCj4gPg0KPiA+IEZyb206IGdhYnJpZWxlIHBhb2xv
bmkgPGdhYnJpZWxlLnBhb2xvbmlAaHVhd2VpLmNvbT4NCj4gPg0KPiA+IFRoaXMgcGF0Y2ggdHJp
ZXMgdG8gdW5pZnkgQVJNMzIgYW5kIEFSTTY0IFBDSWUgaW4gZGVzaWdud2FyZSBkcml2ZXIuDQo+
IERlbGV0ZQ0KPiA+IGZ1bmN0aW9uIGR3X3BjaWVfc2V0dXAsIGR3X3BjaWVfc2Nhbl9idXMsIGR3
X3BjaWVfbWFwX2lycSBhbmQgc3RydWN0DQo+IGh3X3BjaSwNCj4gPiBtb3ZlIHJlbGF0ZWQgb3Bl
cmF0aW9ucyB0byBkd19wY2llX2hvc3RfaW5pdC4NCj4gPiBBbHNvIHNldCBwcC0+cm9vdF9idXNf
bnIgPSBEV19ST09UX05SX1VOREVGSU5FRCBpbiBhbGwgdGhlIGRyaXZlcnMNCj4gdGhhdA0KPiA+
IGFyZSBiYXNlZCBvbiBkZXNpZ253YXJlIHRvIGZsYWcgdGhhdCB0aGUgZHJpdmVycyBkbyBub3Qg
cmVhZCB0aGUgYnVzDQo+ID4gcmFuZ2VzIGZyb20gRFQuDQo+ID4gVGhpcyBwYXRjaCBhbHNvIGFk
ZHMgaGFuZGxpbmcgb2YgbXVsdGlwbGUgUENJIGRvbWFpbnMgaW4gZGVzaWdud2FyZS4NCj4gPiBp
ZiB0aGUgUENJIGhvc3QgYnJpZGdlIGRyaXZlciBkb2VzIG5vdCBzcGVjaWZ5IGEgcm9vdCBidXMg
bnVtYmVyLCBpbg0KPiBjYXNlDQo+ID4gb2YgbXVsdGlwbGUgZG9tYWlucywgZGVzaWdud2FyZSB3
aWxsIGF1dG9tYXRpbGxheSBzZXQgdGhlIG5leHQgZG9tYWluDQo+IHJvb3QNCj4gPiBidXMgbnVt
YmVyIHRvIHRoZSBsYXN0IGJ1cyBudW1iZXIgdXNlZCBpbiB0aGUgbGFzdCBkb21haW4gKyAxLg0K
PiA+DQo+ID4gVGhpcyBwYXRjaCBhbHNvIHRyeSB0byB1c2Ugb2ZfcGNpX2dldF9ob3N0X2JyaWRn
ZV9yZXNvdXJjZXMgZm9yIEFSTTMyDQo+IGFuZA0KPiA+IEFSTTY0IGFjY29yZGluZyB0byB0aGUg
c3VnZ2VzdGlvbiBmb3IgR2FicmllbGVbMV0NCj4gPg0KPiA+IFRoaXMgcGF0Y2ggaXMgYmFzZWQg
b24gR2FicmllbGUncyBwYXRjaCBhYm91dCBvZl9wY2lfcmFuZ2UgZml4WzJdDQo+ID4NCj4gPiBG
aW5hbGx5IHRoaXMgcGF0Y2ggcmV2ZXJ0cyBjb21taXQgZjRjNTVjNWEzZjdmICJQQ0k6IGRlc2ln
bndhcmU6DQo+ID4gUHJvZ3JhbSBBVFUgd2l0aCB1bnRyYW5zbGF0ZWQgYWRkcmVzcyIuIFRoaXMg
d2FzIGRpc2N1c3NlZCBpbiBbM10NCj4gPg0KPiA+IEkgaGF2ZSBjb21waWxlZCB0aGUgZHJpdmVy
IHdpdGggbXVsdGlfdjdfZGVmY29uZmlnLiBIb3dldmVyLCBJIGRvbid0DQo+IGhhdmUNCj4gPiBB
Uk0zMiBQQ0llIHJlbGF0ZWQgYm9hcmQgdG8gZG8gdGVzdC4gSXQgd2lsbCBiZSBhcHByZWNpYXRl
ZCBpZg0KPiBzb21lb25lIGNvdWxkDQo+ID4gaGVscCB0byB0ZXN0IGl0Lg0KPiA+DQo+ID4gU2ln
bmVkLW9mZi1ieTogWmhvdSBXYW5nIDx3YW5nemhvdTFAaGlzaWxpY29uLmNvbT4NCj4gPiBTaWdu
ZWQtb2ZmLWJ5OiBBcm5kIEJlcmdtYW5uIDxhcm5kQGFybmRiLmRlPg0KPiA+IFNpZ25lZC1vZmYt
Ynk6IEdhYnJpZWxlIFBhb2xvbmkgPGdhYnJpZWxlLnBhb2xvbmlAaHVhd2VpLmNvbT4NCj4gPg0K
PiA+IFsxXSBodHRwOi8vd3d3LnNwaW5pY3MubmV0L2xpc3RzL2xpbnV4LXBjaS9tc2c0MjE5NC5o
dG1sDQo+ID4gWzJdIGh0dHBzOi8vcGF0Y2h3b3JrLm96bGFicy5vcmcvcGF0Y2gvNDk1MDE4Lw0K
PiA+IFszXSBodHRwOi8vd3d3LnNwaW5pY3MubmV0L2xpc3RzL2FybS1rZXJuZWwvbXNnNDM2Nzc5
Lmh0bWwNCj4gPiAtLS0NCj4gPiAgZHJpdmVycy9wY2kvaG9zdC9wY2ktZHJhN3h4LmMgICAgICB8
ICAxNSArLS0NCj4gPiAgZHJpdmVycy9wY2kvaG9zdC9wY2ktZXh5bm9zLmMgICAgICB8ICAgMiAr
LQ0KPiA+ICBkcml2ZXJzL3BjaS9ob3N0L3BjaS1pbXg2LmMgICAgICAgIHwgICAyICstDQo+ID4g
IGRyaXZlcnMvcGNpL2hvc3QvcGNpLWtleXN0b25lLWR3LmMgfCAgIDIgKy0NCj4gPiAgZHJpdmVy
cy9wY2kvaG9zdC9wY2kta2V5c3RvbmUuYyAgICB8ICAgMiArLQ0KPiA+ICBkcml2ZXJzL3BjaS9o
b3N0L3BjaS1sYXllcnNjYXBlLmMgIHwgICAyICstDQo+ID4gIGRyaXZlcnMvcGNpL2hvc3QvcGNp
ZS1kZXNpZ253YXJlLmMgfCAyNDcgKysrKysrKysrKysrKystLS0tLS0tLS0tLS0tDQo+IC0tLS0t
LS0tLS0NCj4gPiAgZHJpdmVycy9wY2kvaG9zdC9wY2llLWRlc2lnbndhcmUuaCB8ICAxNSArLS0N
Cj4gPiAgZHJpdmVycy9wY2kvaG9zdC9wY2llLXNwZWFyMTN4eC5jICB8ICAgMiArLQ0KPiA+ICA5
IGZpbGVzIGNoYW5nZWQsIDExMCBpbnNlcnRpb25zKCspLCAxNzkgZGVsZXRpb25zKC0pDQo+ID4N
Cj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9wY2kvaG9zdC9wY2ktZHJhN3h4LmMgYi9kcml2ZXJz
L3BjaS9ob3N0L3BjaS0NCj4gZHJhN3h4LmMNCj4gPiBpbmRleCA1Njc4YjU3Li44ZDU5OGZiIDEw
MDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvcGNpL2hvc3QvcGNpLWRyYTd4eC5jDQo+ID4gKysrIGIv
ZHJpdmVycy9wY2kvaG9zdC9wY2ktZHJhN3h4LmMNCj4gPiBAQCAtMTQxLDE1ICsxNDEsMTUgQEAg
c3RhdGljIHZvaWQgZHJhN3h4X3BjaWVfaG9zdF9pbml0KHN0cnVjdA0KPiBwY2llX3BvcnQgKnBw
KQ0KPiA+ICB7DQo+ID4gIAlkd19wY2llX3NldHVwX3JjKHBwKTsNCj4gPg0KPiA+IC0JaWYgKHBw
LT5pb19tb2RfYmFzZSkNCj4gPiAtCQlwcC0+aW9fbW9kX2Jhc2UgJj0gQ1BVX1RPX0JVU19BRERS
Ow0KPiA+ICsJaWYgKHBwLT5pb19iYXNlKQ0KPiA+ICsJCXBwLT5pb19iYXNlICY9IENQVV9UT19C
VVNfQUREUjsNCj4gPg0KPiA+IC0JaWYgKHBwLT5tZW1fbW9kX2Jhc2UpDQo+ID4gLQkJcHAtPm1l
bV9tb2RfYmFzZSAmPSBDUFVfVE9fQlVTX0FERFI7DQo+ID4gKwlpZiAocHAtPm1lbV9iYXNlKQ0K
PiA+ICsJCXBwLT5tZW1fYmFzZSAmPSBDUFVfVE9fQlVTX0FERFI7DQo+ID4NCj4gPiAtCWlmIChw
cC0+Y2ZnMF9tb2RfYmFzZSkgew0KPiA+IC0JCXBwLT5jZmcwX21vZF9iYXNlICY9IENQVV9UT19C
VVNfQUREUjsNCj4gPiAtCQlwcC0+Y2ZnMV9tb2RfYmFzZSAmPSBDUFVfVE9fQlVTX0FERFI7DQo+
ID4gKwlpZiAocHAtPmNmZzBfYmFzZSkgew0KPiA+ICsJCXBwLT5jZmcwX2Jhc2UgJj0gQ1BVX1RP
X0JVU19BRERSOw0KPiA+ICsJCXBwLT5jZmcxX2Jhc2UgJj0gQ1BVX1RPX0JVU19BRERSOw0KPiA+
ICAJfQ0KPiA+DQo+ID4gIAlkcmE3eHhfcGNpZV9lc3RhYmxpc2hfbGluayhwcCk7DQo+ID4gQEAg
LTI4OCw2ICsyODgsNyBAQCBzdGF0aWMgaW50IF9faW5pdCBkcmE3eHhfYWRkX3BjaWVfcG9ydChz
dHJ1Y3QNCj4gZHJhN3h4X3BjaWUgKmRyYTd4eCwNCj4gPg0KPiA+ICAJcHAgPSAmZHJhN3h4LT5w
cDsNCj4gPiAgCXBwLT5kZXYgPSBkZXY7DQo+ID4gKwlwcC0+cm9vdF9idXNfbnIgPSBEV19ST09U
X05SX1VOREVGSU5FRDsNCj4gPiAgCXBwLT5vcHMgPSAmZHJhN3h4X3BjaWVfaG9zdF9vcHM7DQo+
ID4NCj4gPiAgCXBwLT5pcnEgPSBwbGF0Zm9ybV9nZXRfaXJxKHBkZXYsIDEpOw0KPiA+IGRpZmYg
LS1naXQgYS9kcml2ZXJzL3BjaS9ob3N0L3BjaS1leHlub3MuYyBiL2RyaXZlcnMvcGNpL2hvc3Qv
cGNpLQ0KPiBleHlub3MuYw0KPiA+IGluZGV4IGY5ZjQ2OGQuLmVkMDNhOGYgMTAwNjQ0DQo+ID4g
LS0tIGEvZHJpdmVycy9wY2kvaG9zdC9wY2ktZXh5bm9zLmMNCj4gPiArKysgYi9kcml2ZXJzL3Bj
aS9ob3N0L3BjaS1leHlub3MuYw0KPiA+IEBAIC01MzAsNyArNTMwLDcgQEAgc3RhdGljIGludCBf
X2luaXQgZXh5bm9zX2FkZF9wY2llX3BvcnQoc3RydWN0DQo+IHBjaWVfcG9ydCAqcHAsDQo+ID4g
IAkJfQ0KPiA+ICAJfQ0KPiA+DQo+ID4gLQlwcC0+cm9vdF9idXNfbnIgPSAtMTsNCj4gPiArCXBw
LT5yb290X2J1c19uciA9IERXX1JPT1RfTlJfVU5ERUZJTkVEOw0KPiA+ICAJcHAtPm9wcyA9ICZl
eHlub3NfcGNpZV9ob3N0X29wczsNCj4gPg0KPiA+ICAJcmV0ID0gZHdfcGNpZV9ob3N0X2luaXQo
cHApOw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3BjaS9ob3N0L3BjaS1pbXg2LmMgYi9kcml2
ZXJzL3BjaS9ob3N0L3BjaS0NCj4gaW14Ni5jDQo+ID4gaW5kZXggMjMzYTE5Ni4uMGVmYWM4NSAx
MDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL3BjaS9ob3N0L3BjaS1pbXg2LmMNCj4gPiArKysgYi9k
cml2ZXJzL3BjaS9ob3N0L3BjaS1pbXg2LmMNCj4gPiBAQCAtNTUxLDcgKzU1MSw3IEBAIHN0YXRp
YyBpbnQgX19pbml0IGlteDZfYWRkX3BjaWVfcG9ydChzdHJ1Y3QNCj4gcGNpZV9wb3J0ICpwcCwN
Cj4gPiAgCQl9DQo+ID4gIAl9DQo+ID4NCj4gPiAtCXBwLT5yb290X2J1c19uciA9IC0xOw0KPiA+
ICsJcHAtPnJvb3RfYnVzX25yID0gRFdfUk9PVF9OUl9VTkRFRklORUQ7DQo+ID4gIAlwcC0+b3Bz
ID0gJmlteDZfcGNpZV9ob3N0X29wczsNCj4gPg0KPiA+ICAJcmV0ID0gZHdfcGNpZV9ob3N0X2lu
aXQocHApOw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3BjaS9ob3N0L3BjaS1rZXlzdG9uZS1k
dy5jDQo+IGIvZHJpdmVycy9wY2kvaG9zdC9wY2kta2V5c3RvbmUtZHcuYw0KPiA+IGluZGV4IGYz
NDg5MmUuLmIxZTQxMzUgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9wY2kvaG9zdC9wY2kta2V5
c3RvbmUtZHcuYw0KPiA+ICsrKyBiL2RyaXZlcnMvcGNpL2hvc3QvcGNpLWtleXN0b25lLWR3LmMN
Cj4gPiBAQCAtMzI3LDcgKzMyNyw3IEBAIHN0YXRpYyB2b2lkIGtzX2R3X3BjaWVfY2xlYXJfZGJp
X21vZGUodm9pZA0KPiBfX2lvbWVtICpyZWdfdmlydCkNCj4gPiAgdm9pZCBrc19kd19wY2llX3Nl
dHVwX3JjX2FwcF9yZWdzKHN0cnVjdCBrZXlzdG9uZV9wY2llICprc19wY2llKQ0KPiA+ICB7DQo+
ID4gIAlzdHJ1Y3QgcGNpZV9wb3J0ICpwcCA9ICZrc19wY2llLT5wcDsNCj4gPiAtCXUzMiBzdGFy
dCA9IHBwLT5tZW0uc3RhcnQsIGVuZCA9IHBwLT5tZW0uZW5kOw0KPiA+ICsJdTMyIHN0YXJ0ID0g
cHAtPm1lbS0+c3RhcnQsIGVuZCA9IHBwLT5tZW0tPmVuZDsNCj4gPiAgCWludCBpLCB0cl9zaXpl
Ow0KPiA+DQo+ID4gIAkvKiBEaXNhYmxlIEJBUnMgZm9yIGluYm91bmQgYWNjZXNzICovDQo+ID4g
ZGlmZiAtLWdpdCBhL2RyaXZlcnMvcGNpL2hvc3QvcGNpLWtleXN0b25lLmMgYi9kcml2ZXJzL3Bj
aS9ob3N0L3BjaS0NCj4ga2V5c3RvbmUuYw0KPiA+IGluZGV4IDczNGRhNTguLmI1MjI5NTYgMTAw
NjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9wY2kvaG9zdC9wY2kta2V5c3RvbmUuYw0KPiA+ICsrKyBi
L2RyaXZlcnMvcGNpL2hvc3QvcGNpLWtleXN0b25lLmMNCj4gPiBAQCAtMzA5LDcgKzMwOSw3IEBA
IHN0YXRpYyBpbnQgX19pbml0IGtzX2FkZF9wY2llX3BvcnQoc3RydWN0DQo+IGtleXN0b25lX3Bj
aWUgKmtzX3BjaWUsDQo+ID4gIAkJCXJldHVybiByZXQ7DQo+ID4gIAl9DQo+ID4NCj4gPiAtCXBw
LT5yb290X2J1c19uciA9IC0xOw0KPiA+ICsJcHAtPnJvb3RfYnVzX25yID0gRFdfUk9PVF9OUl9V
TkRFRklORUQ7DQo+ID4gIAlwcC0+b3BzID0gJmtleXN0b25lX3BjaWVfaG9zdF9vcHM7DQo+ID4g
IAlyZXQgPSBrc19kd19wY2llX2hvc3RfaW5pdChrc19wY2llLCBrc19wY2llLT5tc2lfaW50Y19u
cCk7DQo+ID4gIAlpZiAocmV0KSB7DQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvcGNpL2hvc3Qv
cGNpLWxheWVyc2NhcGUuYw0KPiBiL2RyaXZlcnMvcGNpL2hvc3QvcGNpLWxheWVyc2NhcGUuYw0K
PiA+IGluZGV4IGIyMzI4ZWExLi5kZDkyZmZhIDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvcGNp
L2hvc3QvcGNpLWxheWVyc2NhcGUuYw0KPiA+ICsrKyBiL2RyaXZlcnMvcGNpL2hvc3QvcGNpLWxh
eWVyc2NhcGUuYw0KPiA+IEBAIC0xMDYsNyArMTA2LDcgQEAgc3RhdGljIGludCBsc19hZGRfcGNp
ZV9wb3J0KHN0cnVjdCBsc19wY2llICpwY2llKQ0KPiA+ICAJcHAgPSAmcGNpZS0+cHA7DQo+ID4g
IAlwcC0+ZGV2ID0gcGNpZS0+ZGV2Ow0KPiA+ICAJcHAtPmRiaV9iYXNlID0gcGNpZS0+ZGJpOw0K
PiA+IC0JcHAtPnJvb3RfYnVzX25yID0gLTE7DQo+ID4gKwlwcC0+cm9vdF9idXNfbnIgPSBEV19S
T09UX05SX1VOREVGSU5FRDsNCj4gPiAgCXBwLT5vcHMgPSAmbHNfcGNpZV9ob3N0X29wczsNCj4g
Pg0KPiA+ICAJcmV0ID0gZHdfcGNpZV9ob3N0X2luaXQocHApOw0KPiA+IGRpZmYgLS1naXQgYS9k
cml2ZXJzL3BjaS9ob3N0L3BjaWUtZGVzaWdud2FyZS5jDQo+IGIvZHJpdmVycy9wY2kvaG9zdC9w
Y2llLWRlc2lnbndhcmUuYw0KPiA+IGluZGV4IDUzMDdiMzUuLmJkMjYwNmIgMTAwNjQ0DQo+ID4g
LS0tIGEvZHJpdmVycy9wY2kvaG9zdC9wY2llLWRlc2lnbndhcmUuYw0KPiA+ICsrKyBiL2RyaXZl
cnMvcGNpL2hvc3QvcGNpZS1kZXNpZ253YXJlLmMNCj4gPiBAQCAtMTEsNiArMTEsNyBAQA0KPiA+
ICAgKiBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbi4NCj4gPiAgICov
DQo+ID4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L2hhcmRpcnEuaD4NCj4gPiAgI2luY2x1ZGUgPGxp
bnV4L2lycS5oPg0KPiA+ICAjaW5jbHVkZSA8bGludXgvaXJxZG9tYWluLmg+DQo+ID4gICNpbmNs
dWRlIDxsaW51eC9rZXJuZWwuaD4NCj4gPiBAQCAtNjksMTYgKzcwLDkgQEANCj4gPiAgI2RlZmlu
ZSBQQ0lFX0FUVV9GVU5DKHgpCQkoKCh4KSAmIDB4NykgPDwgMTYpDQo+ID4gICNkZWZpbmUgUENJ
RV9BVFVfVVBQRVJfVEFSR0VUCQkweDkxQw0KPiA+DQo+ID4gLXN0YXRpYyBzdHJ1Y3QgaHdfcGNp
IGR3X3BjaTsNCj4gPiArc3RhdGljIHN0cnVjdCBwY2lfb3BzIGR3X3BjaWVfb3BzOw0KPiA+DQo+
ID4gLXN0YXRpYyB1bnNpZ25lZCBsb25nIGdsb2JhbF9pb19vZmZzZXQ7DQo+ID4gLQ0KPiA+IC1z
dGF0aWMgaW5saW5lIHN0cnVjdCBwY2llX3BvcnQgKnN5c190b19wY2llKHN0cnVjdCBwY2lfc3lz
X2RhdGEgKnN5cykNCj4gPiAtew0KPiA+IC0JQlVHX09OKCFzeXMtPnByaXZhdGVfZGF0YSk7DQo+
ID4gLQ0KPiA+IC0JcmV0dXJuIHN5cy0+cHJpdmF0ZV9kYXRhOw0KPiA+IC19DQo+ID4gK0RFRklO
RV9NVVRFWChyb290X2J1c19ucl9tdXgpOw0KPiA+DQo+ID4gIGludCBkd19wY2llX2NmZ19yZWFk
KHZvaWQgX19pb21lbSAqYWRkciwgaW50IHdoZXJlLCBpbnQgc2l6ZSwgdTMyDQo+ICp2YWwpDQo+
ID4gIHsNCj4gPiBAQCAtMjU1LDcgKzI0OSw3IEBAIHN0YXRpYyB2b2lkIGR3X3BjaWVfbXNpX3Nl
dF9pcnEoc3RydWN0IHBjaWVfcG9ydA0KPiAqcHAsIGludCBpcnEpDQo+ID4gIHN0YXRpYyBpbnQg
YXNzaWduX2lycShpbnQgbm9faXJxcywgc3RydWN0IG1zaV9kZXNjICpkZXNjLCBpbnQgKnBvcykN
Cj4gPiAgew0KPiA+ICAJaW50IGlycSwgcG9zMCwgaTsNCj4gPiAtCXN0cnVjdCBwY2llX3BvcnQg
KnBwID0gc3lzX3RvX3BjaWUoZGVzYy0+ZGV2LT5idXMtPnN5c2RhdGEpOw0KPiA+ICsJc3RydWN0
IHBjaWVfcG9ydCAqcHAgPSBkZXNjLT5kZXYtPmJ1cy0+c3lzZGF0YTsNCj4gPg0KPiA+ICAJcG9z
MCA9IGJpdG1hcF9maW5kX2ZyZWVfcmVnaW9uKHBwLT5tc2lfaXJxX2luX3VzZSwgTUFYX01TSV9J
UlFTLA0KPiA+ICAJCQkJICAgICAgIG9yZGVyX2Jhc2VfMihub19pcnFzKSk7DQo+ID4gQEAgLTI5
OCw3ICsyOTIsNyBAQCBzdGF0aWMgaW50IGR3X21zaV9zZXR1cF9pcnEoc3RydWN0IG1zaV9jb250
cm9sbGVyDQo+ICpjaGlwLCBzdHJ1Y3QgcGNpX2RldiAqcGRldiwNCj4gPiAgew0KPiA+ICAJaW50
IGlycSwgcG9zOw0KPiA+ICAJc3RydWN0IG1zaV9tc2cgbXNnOw0KPiA+IC0Jc3RydWN0IHBjaWVf
cG9ydCAqcHAgPSBzeXNfdG9fcGNpZShwZGV2LT5idXMtPnN5c2RhdGEpOw0KPiA+ICsJc3RydWN0
IHBjaWVfcG9ydCAqcHAgPSBwZGV2LT5idXMtPnN5c2RhdGE7DQo+ID4NCj4gPiAgCWlmIChkZXNj
LT5tc2lfYXR0cmliLmlzX21zaXgpDQo+ID4gIAkJcmV0dXJuIC1FSU5WQUw7DQo+ID4gQEAgLTMy
Nyw3ICszMjEsNyBAQCBzdGF0aWMgdm9pZCBkd19tc2lfdGVhcmRvd25faXJxKHN0cnVjdA0KPiBt
c2lfY29udHJvbGxlciAqY2hpcCwgdW5zaWduZWQgaW50IGlycSkNCj4gPiAgew0KPiA+ICAJc3Ry
dWN0IGlycV9kYXRhICpkYXRhID0gaXJxX2dldF9pcnFfZGF0YShpcnEpOw0KPiA+ICAJc3RydWN0
IG1zaV9kZXNjICptc2kgPSBpcnFfZGF0YV9nZXRfbXNpKGRhdGEpOw0KPiA+IC0Jc3RydWN0IHBj
aWVfcG9ydCAqcHAgPSBzeXNfdG9fcGNpZShtc2ktPmRldi0+YnVzLT5zeXNkYXRhKTsNCj4gPiAr
CXN0cnVjdCBwY2llX3BvcnQgKnBwID0gbXNpLT5kZXYtPmJ1cy0+c3lzZGF0YTsNCj4gPg0KPiA+
ICAJY2xlYXJfaXJxX3JhbmdlKHBwLCBpcnEsIDEsIGRhdGEtPmh3aXJxKTsNCj4gPiAgfQ0KPiA+
IEBAIC0zNTksMjIgKzM1MywxNyBAQCBzdGF0aWMgY29uc3Qgc3RydWN0IGlycV9kb21haW5fb3Bz
DQo+IG1zaV9kb21haW5fb3BzID0gew0KPiA+ICAJLm1hcCA9IGR3X3BjaWVfbXNpX21hcCwNCj4g
PiAgfTsNCj4gPg0KPiA+IC1pbnQgZHdfcGNpZV9ob3N0X2luaXQoc3RydWN0IHBjaWVfcG9ydCAq
cHApDQo+ID4gK2ludCBfX2luaXQgZHdfcGNpZV9ob3N0X2luaXQoc3RydWN0IHBjaWVfcG9ydCAq
cHApDQo+ID4gIHsNCj4gPiAgCXN0cnVjdCBkZXZpY2Vfbm9kZSAqbnAgPSBwcC0+ZGV2LT5vZl9u
b2RlOw0KPiA+ICAJc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldiA9IHRvX3BsYXRmb3JtX2Rl
dmljZShwcC0+ZGV2KTsNCj4gPiAtCXN0cnVjdCBvZl9wY2lfcmFuZ2UgcmFuZ2U7DQo+ID4gLQlz
dHJ1Y3Qgb2ZfcGNpX3JhbmdlX3BhcnNlciBwYXJzZXI7DQo+ID4gKwlzdHJ1Y3QgcGNpX2J1cyAq
YnVzOw0KPiA+ICAJc3RydWN0IHJlc291cmNlICpjZmdfcmVzOw0KPiA+IC0JdTMyIHZhbCwgbmEs
IG5zOw0KPiA+IC0JY29uc3QgX19iZTMyICphZGRycDsNCj4gPiAtCWludCBpLCBpbmRleCwgcmV0
Ow0KPiA+IC0NCj4gPiAtCS8qIEZpbmQgdGhlIGFkZHJlc3MgY2VsbCBzaXplIGFuZCB0aGUgbnVt
YmVyIG9mIGNlbGxzIGluIG9yZGVyIHRvDQo+IGdldA0KPiA+IC0JICogdGhlIHVudHJhbnNsYXRl
ZCBhZGRyZXNzLg0KPiA+IC0JICovDQo+ID4gLQlvZl9wcm9wZXJ0eV9yZWFkX3UzMihucCwgIiNh
ZGRyZXNzLWNlbGxzIiwgJm5hKTsNCj4gPiAtCW5zID0gb2Zfbl9zaXplX2NlbGxzKG5wKTsNCj4g
PiArCUxJU1RfSEVBRChyZXMpOw0KPiA+ICsJdTMyIHZhbDsNCj4gPiArCWludCBpLCByZXQ7DQo+
ID4gKwlzdHJ1Y3QgcmVzb3VyY2VfZW50cnkgKndpbjsNCj4gPiArCXN0YXRpYyBpbnQgcm9vdF9i
dXNfbnIgPSAwOw0KPiA+DQo+ID4gIAljZmdfcmVzID0gcGxhdGZvcm1fZ2V0X3Jlc291cmNlX2J5
bmFtZShwZGV2LCBJT1JFU09VUkNFX01FTSwNCj4gImNvbmZpZyIpOw0KPiA+ICAJaWYgKGNmZ19y
ZXMpIHsNCj4gPiBAQCAtMzgyLDg1ICszNzEsNjAgQEAgaW50IGR3X3BjaWVfaG9zdF9pbml0KHN0
cnVjdCBwY2llX3BvcnQgKnBwKQ0KPiA+ICAJCXBwLT5jZmcxX3NpemUgPSByZXNvdXJjZV9zaXpl
KGNmZ19yZXMpLzI7DQo+ID4gIAkJcHAtPmNmZzBfYmFzZSA9IGNmZ19yZXMtPnN0YXJ0Ow0KPiA+
ICAJCXBwLT5jZmcxX2Jhc2UgPSBjZmdfcmVzLT5zdGFydCArIHBwLT5jZmcwX3NpemU7DQo+ID4g
LQ0KPiA+IC0JCS8qIEZpbmQgdGhlIHVudHJhbnNsYXRlZCBjb25maWd1cmF0aW9uIHNwYWNlIGFk
ZHJlc3MgKi8NCj4gPiAtCQlpbmRleCA9IG9mX3Byb3BlcnR5X21hdGNoX3N0cmluZyhucCwgInJl
Zy1uYW1lcyIsICJjb25maWciKTsNCj4gPiAtCQlhZGRycCA9IG9mX2dldF9hZGRyZXNzKG5wLCBp
bmRleCwgTlVMTCwgTlVMTCk7DQo+ID4gLQkJcHAtPmNmZzBfbW9kX2Jhc2UgPSBvZl9yZWFkX251
bWJlcihhZGRycCwgbnMpOw0KPiA+IC0JCXBwLT5jZmcxX21vZF9iYXNlID0gcHAtPmNmZzBfbW9k
X2Jhc2UgKyBwcC0+Y2ZnMF9zaXplOw0KPiA+ICAJfSBlbHNlIHsNCj4gPiAgCQlkZXZfZXJyKHBw
LT5kZXYsICJtaXNzaW5nICpjb25maWcqIHJlZyBzcGFjZVxuIik7DQo+ID4gIAl9DQo+ID4NCj4g
PiAtCWlmIChvZl9wY2lfcmFuZ2VfcGFyc2VyX2luaXQoJnBhcnNlciwgbnApKSB7DQo+ID4gLQkJ
ZGV2X2VycihwcC0+ZGV2LCAibWlzc2luZyByYW5nZXMgcHJvcGVydHlcbiIpOw0KPiA+IC0JCXJl
dHVybiAtRUlOVkFMOw0KPiA+IC0JfQ0KPiA+ICsJcmV0ID0gb2ZfcGNpX2dldF9ob3N0X2JyaWRn
ZV9yZXNvdXJjZXMobnAsIDAsIDB4ZmYsICZyZXMsICZwcC0NCj4gPmlvX2Jhc2UpOw0KPiA+ICsJ
aWYgKHJldCkNCj4gPiArCQlyZXR1cm4gcmV0Ow0KPiA+DQo+ID4gIAkvKiBHZXQgdGhlIEkvTyBh
bmQgbWVtb3J5IHJhbmdlcyBmcm9tIERUICovDQo+ID4gLQlmb3JfZWFjaF9vZl9wY2lfcmFuZ2Uo
JnBhcnNlciwgJnJhbmdlKSB7DQo+ID4gLQkJdW5zaWduZWQgbG9uZyByZXN0eXBlID0gcmFuZ2Uu
ZmxhZ3MgJiBJT1JFU09VUkNFX1RZUEVfQklUUzsNCj4gPiAtDQo+ID4gLQkJaWYgKHJlc3R5cGUg
PT0gSU9SRVNPVVJDRV9JTykgew0KPiA+IC0JCQlvZl9wY2lfcmFuZ2VfdG9fcmVzb3VyY2UoJnJh
bmdlLCBucCwgJnBwLT5pbyk7DQo+ID4gLQkJCXBwLT5pby5uYW1lID0gIkkvTyI7DQo+ID4gLQkJ
CXBwLT5pby5zdGFydCA9IG1heF90KHJlc291cmNlX3NpemVfdCwNCj4gPiAtCQkJCQkgICAgIFBD
SUJJT1NfTUlOX0lPLA0KPiA+IC0JCQkJCSAgICAgcmFuZ2UucGNpX2FkZHIgKyBnbG9iYWxfaW9f
b2Zmc2V0KTsNCj4gPiAtCQkJcHAtPmlvLmVuZCA9IG1pbl90KHJlc291cmNlX3NpemVfdCwNCj4g
PiAtCQkJCQkgICBJT19TUEFDRV9MSU1JVCwNCj4gPiAtCQkJCQkgICByYW5nZS5wY2lfYWRkciAr
IHJhbmdlLnNpemUNCj4gPiAtCQkJCQkgICArIGdsb2JhbF9pb19vZmZzZXQgLSAxKTsNCj4gPiAt
CQkJcHAtPmlvX3NpemUgPSByZXNvdXJjZV9zaXplKCZwcC0+aW8pOw0KPiA+IC0JCQlwcC0+aW9f
YnVzX2FkZHIgPSByYW5nZS5wY2lfYWRkcjsNCj4gPiAtCQkJcHAtPmlvX2Jhc2UgPSByYW5nZS5j
cHVfYWRkcjsNCj4gPiAtDQo+ID4gLQkJCS8qIEZpbmQgdGhlIHVudHJhbnNsYXRlZCBJTyBzcGFj
ZSBhZGRyZXNzICovDQo+ID4gLQkJCXBwLT5pb19tb2RfYmFzZSA9IHJhbmdlLmNwdV9hZGRyOw0K
PiA+IC0JCX0NCj4gPiAtCQlpZiAocmVzdHlwZSA9PSBJT1JFU09VUkNFX01FTSkgew0KPiA+IC0J
CQlvZl9wY2lfcmFuZ2VfdG9fcmVzb3VyY2UoJnJhbmdlLCBucCwgJnBwLT5tZW0pOw0KPiA+IC0J
CQlwcC0+bWVtLm5hbWUgPSAiTUVNIjsNCj4gPiAtCQkJcHAtPm1lbV9zaXplID0gcmVzb3VyY2Vf
c2l6ZSgmcHAtPm1lbSk7DQo+ID4gLQkJCXBwLT5tZW1fYnVzX2FkZHIgPSByYW5nZS5wY2lfYWRk
cjsNCj4gPiAtDQo+ID4gLQkJCS8qIEZpbmQgdGhlIHVudHJhbnNsYXRlZCBNRU0gc3BhY2UgYWRk
cmVzcyAqLw0KPiA+IC0JCQlwcC0+bWVtX21vZF9iYXNlID0gcmFuZ2UuY3B1X2FkZHI7DQo+ID4g
LQkJfQ0KPiA+IC0JCWlmIChyZXN0eXBlID09IDApIHsNCj4gPiAtCQkJb2ZfcGNpX3JhbmdlX3Rv
X3Jlc291cmNlKCZyYW5nZSwgbnAsICZwcC0+Y2ZnKTsNCj4gPiAtCQkJcHAtPmNmZzBfc2l6ZSA9
IHJlc291cmNlX3NpemUoJnBwLT5jZmcpLzI7DQo+ID4gLQkJCXBwLT5jZmcxX3NpemUgPSByZXNv
dXJjZV9zaXplKCZwcC0+Y2ZnKS8yOw0KPiA+IC0JCQlwcC0+Y2ZnMF9iYXNlID0gcHAtPmNmZy5z
dGFydDsNCj4gPiAtCQkJcHAtPmNmZzFfYmFzZSA9IHBwLT5jZmcuc3RhcnQgKyBwcC0+Y2ZnMF9z
aXplOw0KPiA+IC0NCj4gPiAtCQkJLyogRmluZCB0aGUgdW50cmFuc2xhdGVkIGNvbmZpZ3VyYXRp
b24gc3BhY2UgYWRkcmVzcw0KPiAqLw0KPiA+IC0JCQlwcC0+Y2ZnMF9tb2RfYmFzZSA9IHJhbmdl
LmNwdV9hZGRyOw0KPiA+IC0JCQlwcC0+Y2ZnMV9tb2RfYmFzZSA9IHBwLT5jZmcwX21vZF9iYXNl
ICsNCj4gPiAtCQkJCQkgICAgcHAtPmNmZzBfc2l6ZTsNCj4gPiArCXJlc291cmNlX2xpc3RfZm9y
X2VhY2hfZW50cnkod2luLCAmcmVzKSB7DQo+ID4gKwkJc3dpdGNoIChyZXNvdXJjZV90eXBlKHdp
bi0+cmVzKSkgew0KPiA+ICsJCWNhc2UgSU9SRVNPVVJDRV9JTzoNCj4gPiArCQkJcHAtPmlvID0g
d2luLT5yZXM7DQo+ID4gKwkJCXBwLT5pby0+bmFtZSA9ICJJL08iOw0KPiA+ICsJCQlwcC0+aW9f
c2l6ZSA9IHJlc291cmNlX3NpemUocHAtPmlvKTsNCj4gPiArCQkJcHAtPmlvX2J1c19hZGRyID0g
cHAtPmlvLT5zdGFydCAtIHdpbi0+b2Zmc2V0Ow0KPiA+ICsJCQlyZXQgPSBwY2lfcmVtYXBfaW9z
cGFjZShwcC0+aW8sIHBwLT5pb19iYXNlKTsNCj4gPiArCQkJaWYgKHJldCkgew0KPiA+ICsJCQkJ
ZGV2X3dhcm4ocHAtPmRldiwgImVycm9yICVkOiBmYWlsZWQgdG8gbWFwDQo+IHJlc291cmNlICVw
UlxuIiwNCj4gPiArCQkJCQkgcmV0LCBwcC0+aW8pOw0KPiA+ICsJCQkJY29udGludWU7DQo+ID4g
KwkJCX0NCj4gPiArCQkJYnJlYWs7DQo+ID4gKwkJY2FzZSBJT1JFU09VUkNFX01FTToNCj4gPiAr
CQkJcHAtPm1lbSA9IHdpbi0+cmVzOw0KPiA+ICsJCQlwcC0+bWVtLT5uYW1lID0gIk1FTSI7DQo+
ID4gKwkJCXBwLT5tZW1fc2l6ZSA9IHJlc291cmNlX3NpemUocHAtPm1lbSk7DQo+ID4gKwkJCXBw
LT5tZW1fYnVzX2FkZHIgPSBwcC0+bWVtLT5zdGFydCAtIHdpbi0+b2Zmc2V0Ow0KPiA+ICsJCQli
cmVhazsNCj4gPiArCQljYXNlIDA6DQo+ID4gKwkJCXBwLT5jZmcgPSB3aW4tPnJlczsNCj4gPiAr
CQkJcHAtPmNmZzBfc2l6ZSA9IHJlc291cmNlX3NpemUocHAtPmNmZykvMjsNCj4gPiArCQkJcHAt
PmNmZzFfc2l6ZSA9IHJlc291cmNlX3NpemUocHAtPmNmZykvMjsNCj4gPiArCQkJcHAtPmNmZzBf
YmFzZSA9IHBwLT5jZmctPnN0YXJ0Ow0KPiA+ICsJCQlwcC0+Y2ZnMV9iYXNlID0gcHAtPmNmZy0+
c3RhcnQgKyBwcC0+Y2ZnMF9zaXplOw0KPiA+ICsJCQlicmVhazsNCj4gPiArCQljYXNlIElPUkVT
T1VSQ0VfQlVTOg0KPiA+ICsJCQlwcC0+YnVzbiA9IHdpbi0+cmVzOw0KPiA+ICsJCQlicmVhazsN
Cj4gPiArCQlkZWZhdWx0Og0KPiA+ICsJCQljb250aW51ZTsNCj4gPiAgCQl9DQo+ID4gIAl9DQo+
ID4NCj4gPiAtCXJldCA9IG9mX3BjaV9wYXJzZV9idXNfcmFuZ2UobnAsICZwcC0+YnVzbik7DQo+
ID4gLQlpZiAocmV0IDwgMCkgew0KPiA+IC0JCXBwLT5idXNuLm5hbWUgPSBucC0+bmFtZTsNCj4g
PiAtCQlwcC0+YnVzbi5zdGFydCA9IDA7DQo+ID4gLQkJcHAtPmJ1c24uZW5kID0gMHhmZjsNCj4g
PiAtCQlwcC0+YnVzbi5mbGFncyA9IElPUkVTT1VSQ0VfQlVTOw0KPiA+IC0JCWRldl9kYmcocHAt
PmRldiwgImZhaWxlZCB0byBwYXJzZSBidXMtcmFuZ2UgcHJvcGVydHk6ICVkLA0KPiB1c2luZyBk
ZWZhdWx0ICVwUlxuIiwNCj4gPiAtCQkJcmV0LCAmcHAtPmJ1c24pOw0KPiA+IC0JfQ0KPiA+IC0N
Cj4gPiAgCWlmICghcHAtPmRiaV9iYXNlKSB7DQo+ID4gLQkJcHAtPmRiaV9iYXNlID0gZGV2bV9p
b3JlbWFwKHBwLT5kZXYsIHBwLT5jZmcuc3RhcnQsDQo+ID4gLQkJCQkJcmVzb3VyY2Vfc2l6ZSgm
cHAtPmNmZykpOw0KPiA+ICsJCXBwLT5kYmlfYmFzZSA9IGRldm1faW9yZW1hcChwcC0+ZGV2LCBw
cC0+Y2ZnLT5zdGFydCwNCj4gPiArCQkJCQlyZXNvdXJjZV9zaXplKHBwLT5jZmcpKTsNCj4gPiAg
CQlpZiAoIXBwLT5kYmlfYmFzZSkgew0KPiA+ICAJCQlkZXZfZXJyKHBwLT5kZXYsICJlcnJvciB3
aXRoIGlvcmVtYXBcbiIpOw0KPiA+ICAJCQlyZXR1cm4gLUVOT01FTTsNCj4gPiAgCQl9DQo+ID4g
IAl9DQo+ID4NCj4gPiAtCXBwLT5tZW1fYmFzZSA9IHBwLT5tZW0uc3RhcnQ7DQo+ID4gKwlwcC0+
bWVtX2Jhc2UgPSBwcC0+bWVtLT5zdGFydDsNCj4gPg0KPiA+ICAJaWYgKCFwcC0+dmFfY2ZnMF9i
YXNlKSB7DQo+ID4gIAkJcHAtPnZhX2NmZzBfYmFzZSA9IGRldm1faW9yZW1hcChwcC0+ZGV2LCBw
cC0+Y2ZnMF9iYXNlLA0KPiA+IEBAIC01MDksNyArNDczLDcgQEAgaW50IGR3X3BjaWVfaG9zdF9p
bml0KHN0cnVjdCBwY2llX3BvcnQgKnBwKQ0KPiA+DQo+ID4gIAlpZiAoIXBwLT5vcHMtPnJkX290
aGVyX2NvbmYpDQo+ID4gIAkJZHdfcGNpZV9wcm9nX291dGJvdW5kX2F0dShwcCwgUENJRV9BVFVf
UkVHSU9OX0lOREVYMSwNCj4gPiAtCQkJCQkgIFBDSUVfQVRVX1RZUEVfTUVNLCBwcC0+bWVtX21v
ZF9iYXNlLA0KPiA+ICsJCQkJCSAgUENJRV9BVFVfVFlQRV9NRU0sIHBwLT5tZW1fYmFzZSwNCj4g
PiAgCQkJCQkgIHBwLT5tZW1fYnVzX2FkZHIsIHBwLT5tZW1fc2l6ZSk7DQo+ID4NCj4gPiAgCWR3
X3BjaWVfd3Jfb3duX2NvbmYocHAsIFBDSV9CQVNFX0FERFJFU1NfMCwgNCwgMCk7DQo+ID4gQEAg
LTUyMSwxNSArNDg1LDQwIEBAIGludCBkd19wY2llX2hvc3RfaW5pdChzdHJ1Y3QgcGNpZV9wb3J0
ICpwcCkNCj4gPiAgCXZhbCB8PSBQT1JUX0xPR0lDX1NQRUVEX0NIQU5HRTsNCj4gPiAgCWR3X3Bj
aWVfd3Jfb3duX2NvbmYocHAsIFBDSUVfTElOS19XSURUSF9TUEVFRF9DT05UUk9MLCA0LCB2YWwp
Ow0KPiA+DQo+ID4gLSNpZmRlZiBDT05GSUdfUENJX01TSQ0KPiA+ICAJZHdfcGNpZV9tc2lfY2hp
cC5kZXYgPSBwcC0+ZGV2Ow0KPiA+IC0JZHdfcGNpLm1zaV9jdHJsID0gJmR3X3BjaWVfbXNpX2No
aXA7DQo+ID4gKw0KPiA+ICsJbXV0ZXhfbG9jaygmcm9vdF9idXNfbnJfbXV4KTsNCj4gPiArDQo+
ID4gKwlpZiAocHAtPnJvb3RfYnVzX25yICE9IERXX1JPT1RfTlJfVU5ERUZJTkVEKQ0KPiA+ICsJ
CXJvb3RfYnVzX25yID0gcHAtPnJvb3RfYnVzX25yOw0KPiA+ICsNCj4gPiArCWJ1cyA9IHBjaV9j
cmVhdGVfcm9vdF9idXMocHAtPmRldiwgcm9vdF9idXNfbnIsICZkd19wY2llX29wcywNCj4gPiAr
CQkJICAgICAgcHAsICZyZXMpOw0KPiA+ICsJaWYgKCFidXMpIHsNCj4gPiArCQltdXRleF91bmxv
Y2soJnJvb3RfYnVzX25yX211eCk7DQo+ID4gKwkJcmV0dXJuIC1FTk9NRU07DQo+ID4gKwl9DQo+
ID4gKw0KPiA+ICsJcm9vdF9idXNfbnIgKz0gYnVzLT5idXNuX3Jlcy5lbmQgKyAxOw0KPiA+ICsJ
bXV0ZXhfdW5sb2NrKCZyb290X2J1c19ucl9tdXgpOw0KPiA+ICsNCj4gPiArI2lmZGVmIENPTkZJ
R19HRU5FUklDX01TSV9JUlFfRE9NQUlODQo+ID4gKwlidXMtPm1zaSA9IGNvbnRhaW5lcl9vZigm
cHAtPmlycV9kb21haW4sIHN0cnVjdCBtc2lfY29udHJvbGxlciwNCj4gZG9tYWluKTsNCj4gPiAr
I2Vsc2UNCj4gPiArCWJ1cy0+bXNpID0gJmR3X3BjaWVfbXNpX2NoaXA7DQo+ID4gICNlbmRpZg0K
PiA+DQo+ID4gLQlkd19wY2kubnJfY29udHJvbGxlcnMgPSAxOw0KPiA+IC0JZHdfcGNpLnByaXZh
dGVfZGF0YSA9ICh2b2lkICoqKSZwcDsNCj4gPiArCXBjaV9zY2FuX2NoaWxkX2J1cyhidXMpOw0K
PiA+ICsJaWYgKHBwLT5vcHMtPnNjYW5fYnVzKQ0KPiA+ICsJCXBwLT5vcHMtPnNjYW5fYnVzKHBw
KTsNCj4gPiArDQo+ID4gKyNpZmRlZiBDT05GSUdfQVJNDQo+ID4gKwkvKiBzdXBwb3J0IG9sZCBk
dGJzIHRoYXQgaW5jb3JyZWN0bHkgZGVzY3JpYmUgSVJRcyAqLw0KPiA+ICsJcGNpX2ZpeHVwX2ly
cXMocGNpX2NvbW1vbl9zd2l6emxlLCBvZl9pcnFfcGFyc2VfYW5kX21hcF9wY2kpOw0KPiA+ICsj
ZW5kaWYNCj4gPg0KPiA+IC0JcGNpX2NvbW1vbl9pbml0X2RldihwcC0+ZGV2LCAmZHdfcGNpKTsN
Cj4gPiArCXBjaV9hc3NpZ25fdW5hc3NpZ25lZF9idXNfcmVzb3VyY2VzKGJ1cyk7DQo+ID4gKwlw
Y2lfYnVzX2FkZF9kZXZpY2VzKGJ1cyk7DQo+ID4NCj4gPiAgCXJldHVybiAwOw0KPiA+ICB9DQo+
ID4gQEAgLTU0OCwxMiArNTM3LDEyIEBAIHN0YXRpYyBpbnQgZHdfcGNpZV9yZF9vdGhlcl9jb25m
KHN0cnVjdA0KPiBwY2llX3BvcnQgKnBwLCBzdHJ1Y3QgcGNpX2J1cyAqYnVzLA0KPiA+DQo+ID4g
IAlpZiAoYnVzLT5wYXJlbnQtPm51bWJlciA9PSBwcC0+cm9vdF9idXNfbnIpIHsNCj4gPiAgCQl0
eXBlID0gUENJRV9BVFVfVFlQRV9DRkcwOw0KPiA+IC0JCWNwdV9hZGRyID0gcHAtPmNmZzBfbW9k
X2Jhc2U7DQo+ID4gKwkJY3B1X2FkZHIgPSBwcC0+Y2ZnMF9iYXNlOw0KPiA+ICAJCWNmZ19zaXpl
ID0gcHAtPmNmZzBfc2l6ZTsNCj4gPiAgCQl2YV9jZmdfYmFzZSA9IHBwLT52YV9jZmcwX2Jhc2U7
DQo+ID4gIAl9IGVsc2Ugew0KPiA+ICAJCXR5cGUgPSBQQ0lFX0FUVV9UWVBFX0NGRzE7DQo+ID4g
LQkJY3B1X2FkZHIgPSBwcC0+Y2ZnMV9tb2RfYmFzZTsNCj4gPiArCQljcHVfYWRkciA9IHBwLT5j
ZmcxX2Jhc2U7DQo+ID4gIAkJY2ZnX3NpemUgPSBwcC0+Y2ZnMV9zaXplOw0KPiA+ICAJCXZhX2Nm
Z19iYXNlID0gcHAtPnZhX2NmZzFfYmFzZTsNCj4gPiAgCX0NCj4gPiBAQCAtNTYzLDcgKzU1Miw3
IEBAIHN0YXRpYyBpbnQgZHdfcGNpZV9yZF9vdGhlcl9jb25mKHN0cnVjdCBwY2llX3BvcnQNCj4g
KnBwLCBzdHJ1Y3QgcGNpX2J1cyAqYnVzLA0KPiA+ICAJCQkJICBidXNkZXYsIGNmZ19zaXplKTsN
Cj4gPiAgCXJldCA9IGR3X3BjaWVfY2ZnX3JlYWQodmFfY2ZnX2Jhc2UgKyBhZGRyZXNzLCB3aGVy
ZSwgc2l6ZSwgdmFsKTsNCj4gPiAgCWR3X3BjaWVfcHJvZ19vdXRib3VuZF9hdHUocHAsIFBDSUVf
QVRVX1JFR0lPTl9JTkRFWDAsDQo+ID4gLQkJCQkgIFBDSUVfQVRVX1RZUEVfSU8sIHBwLT5pb19t
b2RfYmFzZSwNCj4gPiArCQkJCSAgUENJRV9BVFVfVFlQRV9JTywgcHAtPmlvX2Jhc2UsDQo+ID4g
IAkJCQkgIHBwLT5pb19idXNfYWRkciwgcHAtPmlvX3NpemUpOw0KPiA+DQo+ID4gIAlyZXR1cm4g
cmV0Ow0KPiA+IEBAIC01ODMsMTIgKzU3MiwxMiBAQCBzdGF0aWMgaW50IGR3X3BjaWVfd3Jfb3Ro
ZXJfY29uZihzdHJ1Y3QNCj4gcGNpZV9wb3J0ICpwcCwgc3RydWN0IHBjaV9idXMgKmJ1cywNCj4g
Pg0KPiA+ICAJaWYgKGJ1cy0+cGFyZW50LT5udW1iZXIgPT0gcHAtPnJvb3RfYnVzX25yKSB7DQo+
ID4gIAkJdHlwZSA9IFBDSUVfQVRVX1RZUEVfQ0ZHMDsNCj4gPiAtCQljcHVfYWRkciA9IHBwLT5j
ZmcwX21vZF9iYXNlOw0KPiA+ICsJCWNwdV9hZGRyID0gcHAtPmNmZzBfYmFzZTsNCj4gPiAgCQlj
Zmdfc2l6ZSA9IHBwLT5jZmcwX3NpemU7DQo+ID4gIAkJdmFfY2ZnX2Jhc2UgPSBwcC0+dmFfY2Zn
MF9iYXNlOw0KPiA+ICAJfSBlbHNlIHsNCj4gPiAgCQl0eXBlID0gUENJRV9BVFVfVFlQRV9DRkcx
Ow0KPiA+IC0JCWNwdV9hZGRyID0gcHAtPmNmZzFfbW9kX2Jhc2U7DQo+ID4gKwkJY3B1X2FkZHIg
PSBwcC0+Y2ZnMV9iYXNlOw0KPiA+ICAJCWNmZ19zaXplID0gcHAtPmNmZzFfc2l6ZTsNCj4gPiAg
CQl2YV9jZmdfYmFzZSA9IHBwLT52YV9jZmcxX2Jhc2U7DQo+ID4gIAl9DQo+ID4gQEAgLTU5OCw3
ICs1ODcsNyBAQCBzdGF0aWMgaW50IGR3X3BjaWVfd3Jfb3RoZXJfY29uZihzdHJ1Y3QgcGNpZV9w
b3J0DQo+ICpwcCwgc3RydWN0IHBjaV9idXMgKmJ1cywNCj4gPiAgCQkJCSAgYnVzZGV2LCBjZmdf
c2l6ZSk7DQo+ID4gIAlyZXQgPSBkd19wY2llX2NmZ193cml0ZSh2YV9jZmdfYmFzZSArIGFkZHJl
c3MsIHdoZXJlLCBzaXplLCB2YWwpOw0KPiA+ICAJZHdfcGNpZV9wcm9nX291dGJvdW5kX2F0dShw
cCwgUENJRV9BVFVfUkVHSU9OX0lOREVYMCwNCj4gPiAtCQkJCSAgUENJRV9BVFVfVFlQRV9JTywg
cHAtPmlvX21vZF9iYXNlLA0KPiA+ICsJCQkJICBQQ0lFX0FUVV9UWVBFX0lPLCBwcC0+aW9fYmFz
ZSwNCj4gPiAgCQkJCSAgcHAtPmlvX2J1c19hZGRyLCBwcC0+aW9fc2l6ZSk7DQo+ID4NCj4gPiAg
CXJldHVybiByZXQ7DQo+ID4gQEAgLTYzMCw3ICs2MTksNyBAQCBzdGF0aWMgaW50IGR3X3BjaWVf
dmFsaWRfY29uZmlnKHN0cnVjdCBwY2llX3BvcnQNCj4gKnBwLA0KPiA+ICBzdGF0aWMgaW50IGR3
X3BjaWVfcmRfY29uZihzdHJ1Y3QgcGNpX2J1cyAqYnVzLCB1MzIgZGV2Zm4sIGludCB3aGVyZSwN
Cj4gPiAgCQkJaW50IHNpemUsIHUzMiAqdmFsKQ0KPiA+ICB7DQo+ID4gLQlzdHJ1Y3QgcGNpZV9w
b3J0ICpwcCA9IHN5c190b19wY2llKGJ1cy0+c3lzZGF0YSk7DQo+ID4gKwlzdHJ1Y3QgcGNpZV9w
b3J0ICpwcCA9IGJ1cy0+c3lzZGF0YTsNCj4gPiAgCWludCByZXQ7DQo+ID4NCj4gPiAgCWlmIChk
d19wY2llX3ZhbGlkX2NvbmZpZyhwcCwgYnVzLCBQQ0lfU0xPVChkZXZmbikpID09IDApIHsNCj4g
PiBAQCAtNjU0LDcgKzY0Myw3IEBAIHN0YXRpYyBpbnQgZHdfcGNpZV9yZF9jb25mKHN0cnVjdCBw
Y2lfYnVzICpidXMsDQo+IHUzMiBkZXZmbiwgaW50IHdoZXJlLA0KPiA+ICBzdGF0aWMgaW50IGR3
X3BjaWVfd3JfY29uZihzdHJ1Y3QgcGNpX2J1cyAqYnVzLCB1MzIgZGV2Zm4sDQo+ID4gIAkJCWlu
dCB3aGVyZSwgaW50IHNpemUsIHUzMiB2YWwpDQo+ID4gIHsNCj4gPiAtCXN0cnVjdCBwY2llX3Bv
cnQgKnBwID0gc3lzX3RvX3BjaWUoYnVzLT5zeXNkYXRhKTsNCj4gPiArCXN0cnVjdCBwY2llX3Bv
cnQgKnBwID0gYnVzLT5zeXNkYXRhOw0KPiA+ICAJaW50IHJldDsNCj4gPg0KPiA+ICAJaWYgKGR3
X3BjaWVfdmFsaWRfY29uZmlnKHBwLCBidXMsIFBDSV9TTE9UKGRldmZuKSkgPT0gMCkNCj4gPiBA
QCAtNjc4LDYyICs2NjcsNiBAQCBzdGF0aWMgc3RydWN0IHBjaV9vcHMgZHdfcGNpZV9vcHMgPSB7
DQo+ID4gIAkud3JpdGUgPSBkd19wY2llX3dyX2NvbmYsDQo+ID4gIH07DQo+ID4NCj4gPiAtc3Rh
dGljIGludCBkd19wY2llX3NldHVwKGludCBuciwgc3RydWN0IHBjaV9zeXNfZGF0YSAqc3lzKQ0K
PiA+IC17DQo+ID4gLQlzdHJ1Y3QgcGNpZV9wb3J0ICpwcDsNCj4gPiAtDQo+ID4gLQlwcCA9IHN5
c190b19wY2llKHN5cyk7DQo+ID4gLQ0KPiA+IC0JaWYgKGdsb2JhbF9pb19vZmZzZXQgPCBTWl8x
TSAmJiBwcC0+aW9fc2l6ZSA+IDApIHsNCj4gPiAtCQlzeXMtPmlvX29mZnNldCA9IGdsb2JhbF9p
b19vZmZzZXQgLSBwcC0+aW9fYnVzX2FkZHI7DQo+ID4gLQkJcGNpX2lvcmVtYXBfaW8oZ2xvYmFs
X2lvX29mZnNldCwgcHAtPmlvX2Jhc2UpOw0KPiA+IC0JCWdsb2JhbF9pb19vZmZzZXQgKz0gU1pf
NjRLOw0KPiA+IC0JCXBjaV9hZGRfcmVzb3VyY2Vfb2Zmc2V0KCZzeXMtPnJlc291cmNlcywgJnBw
LT5pbywNCj4gPiAtCQkJCQlzeXMtPmlvX29mZnNldCk7DQo+ID4gLQl9DQo+ID4gLQ0KPiA+IC0J
c3lzLT5tZW1fb2Zmc2V0ID0gcHAtPm1lbS5zdGFydCAtIHBwLT5tZW1fYnVzX2FkZHI7DQo+ID4g
LQlwY2lfYWRkX3Jlc291cmNlX29mZnNldCgmc3lzLT5yZXNvdXJjZXMsICZwcC0+bWVtLCBzeXMt
DQo+ID5tZW1fb2Zmc2V0KTsNCj4gPiAtCXBjaV9hZGRfcmVzb3VyY2UoJnN5cy0+cmVzb3VyY2Vz
LCAmcHAtPmJ1c24pOw0KPiA+IC0NCj4gPiAtCXJldHVybiAxOw0KPiA+IC19DQo+ID4gLQ0KPiA+
IC1zdGF0aWMgc3RydWN0IHBjaV9idXMgKmR3X3BjaWVfc2Nhbl9idXMoaW50IG5yLCBzdHJ1Y3Qg
cGNpX3N5c19kYXRhDQo+ICpzeXMpDQo+ID4gLXsNCj4gPiAtCXN0cnVjdCBwY2lfYnVzICpidXM7
DQo+ID4gLQlzdHJ1Y3QgcGNpZV9wb3J0ICpwcCA9IHN5c190b19wY2llKHN5cyk7DQo+ID4gLQ0K
PiA+IC0JcHAtPnJvb3RfYnVzX25yID0gc3lzLT5idXNucjsNCj4gPiAtCWJ1cyA9IHBjaV9zY2Fu
X3Jvb3RfYnVzKHBwLT5kZXYsIHN5cy0+YnVzbnIsDQo+ID4gLQkJCQkgICZkd19wY2llX29wcywg
c3lzLCAmc3lzLT5yZXNvdXJjZXMpOw0KPiA+IC0JaWYgKCFidXMpDQo+ID4gLQkJcmV0dXJuIE5V
TEw7DQo+ID4gLQ0KPiA+IC0JaWYgKGJ1cyAmJiBwcC0+b3BzLT5zY2FuX2J1cykNCj4gPiAtCQlw
cC0+b3BzLT5zY2FuX2J1cyhwcCk7DQo+ID4gLQ0KPiA+IC0JcmV0dXJuIGJ1czsNCj4gPiAtfQ0K
PiA+IC0NCj4gPiAtc3RhdGljIGludCBkd19wY2llX21hcF9pcnEoY29uc3Qgc3RydWN0IHBjaV9k
ZXYgKmRldiwgdTggc2xvdCwgdTgNCj4gcGluKQ0KPiA+IC17DQo+ID4gLQlzdHJ1Y3QgcGNpZV9w
b3J0ICpwcCA9IHN5c190b19wY2llKGRldi0+YnVzLT5zeXNkYXRhKTsNCj4gPiAtCWludCBpcnE7
DQo+ID4gLQ0KPiA+IC0JaXJxID0gb2ZfaXJxX3BhcnNlX2FuZF9tYXBfcGNpKGRldiwgc2xvdCwg
cGluKTsNCj4gPiAtCWlmICghaXJxKQ0KPiA+IC0JCWlycSA9IHBwLT5pcnE7DQo+ID4gLQ0KPiA+
IC0JcmV0dXJuIGlycTsNCj4gPiAtfQ0KPiA+IC0NCj4gPiAtc3RhdGljIHN0cnVjdCBod19wY2kg
ZHdfcGNpID0gew0KPiA+IC0JLnNldHVwCQk9IGR3X3BjaWVfc2V0dXAsDQo+ID4gLQkuc2NhbgkJ
PSBkd19wY2llX3NjYW5fYnVzLA0KPiA+IC0JLm1hcF9pcnEJPSBkd19wY2llX21hcF9pcnEsDQo+
ID4gLX07DQo+ID4gLQ0KPiA+ICB2b2lkIGR3X3BjaWVfc2V0dXBfcmMoc3RydWN0IHBjaWVfcG9y
dCAqcHApDQo+ID4gIHsNCj4gPiAgCXUzMiB2YWw7DQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMv
cGNpL2hvc3QvcGNpZS1kZXNpZ253YXJlLmgNCj4gYi9kcml2ZXJzL3BjaS9ob3N0L3BjaWUtZGVz
aWdud2FyZS5oDQo+ID4gaW5kZXggZDBiYmQyNy4uMGMyYTdlYiAxMDA2NDQNCj4gPiAtLS0gYS9k
cml2ZXJzL3BjaS9ob3N0L3BjaWUtZGVzaWdud2FyZS5oDQo+ID4gKysrIGIvZHJpdmVycy9wY2kv
aG9zdC9wY2llLWRlc2lnbndhcmUuaA0KPiA+IEBAIC0yMSwzMSArMjEsMjggQEANCj4gPiAgICov
DQo+ID4gICNkZWZpbmUgTUFYX01TSV9JUlFTCQkJMzINCj4gPiAgI2RlZmluZSBNQVhfTVNJX0NU
UkxTCQkJKE1BWF9NU0lfSVJRUyAvIDMyKQ0KPiA+ICsjZGVmaW5lIERXX1JPT1RfTlJfVU5ERUZJ
TkVECS0xDQo+ID4NCj4gPiAgc3RydWN0IHBjaWVfcG9ydCB7DQo+ID4gIAlzdHJ1Y3QgZGV2aWNl
CQkqZGV2Ow0KPiA+ICAJdTgJCQlyb290X2J1c19ucjsNCj4gPiAgCXZvaWQgX19pb21lbQkJKmRi
aV9iYXNlOw0KPiA+ICAJdTY0CQkJY2ZnMF9iYXNlOw0KPiA+IC0JdTY0CQkJY2ZnMF9tb2RfYmFz
ZTsNCj4gPiAgCXZvaWQgX19pb21lbQkJKnZhX2NmZzBfYmFzZTsNCj4gPiAgCXUzMgkJCWNmZzBf
c2l6ZTsNCj4gPiAgCXU2NAkJCWNmZzFfYmFzZTsNCj4gPiAtCXU2NAkJCWNmZzFfbW9kX2Jhc2U7
DQo+ID4gIAl2b2lkIF9faW9tZW0JCSp2YV9jZmcxX2Jhc2U7DQo+ID4gIAl1MzIJCQljZmcxX3Np
emU7DQo+ID4gLQl1NjQJCQlpb19iYXNlOw0KPiA+IC0JdTY0CQkJaW9fbW9kX2Jhc2U7DQo+ID4g
KwlyZXNvdXJjZV9zaXplX3QJCWlvX2Jhc2U7DQo+ID4gIAlwaHlzX2FkZHJfdAkJaW9fYnVzX2Fk
ZHI7DQo+ID4gIAl1MzIJCQlpb19zaXplOw0KPiA+ICAJdTY0CQkJbWVtX2Jhc2U7DQo+ID4gLQl1
NjQJCQltZW1fbW9kX2Jhc2U7DQo+ID4gIAlwaHlzX2FkZHJfdAkJbWVtX2J1c19hZGRyOw0KPiA+
ICAJdTMyCQkJbWVtX3NpemU7DQo+ID4gLQlzdHJ1Y3QgcmVzb3VyY2UJCWNmZzsNCj4gPiAtCXN0
cnVjdCByZXNvdXJjZQkJaW87DQo+ID4gLQlzdHJ1Y3QgcmVzb3VyY2UJCW1lbTsNCj4gPiAtCXN0
cnVjdCByZXNvdXJjZQkJYnVzbjsNCj4gPiArCXN0cnVjdCByZXNvdXJjZQkJKmNmZzsNCj4gPiAr
CXN0cnVjdCByZXNvdXJjZQkJKmlvOw0KPiA+ICsJc3RydWN0IHJlc291cmNlCQkqbWVtOw0KPiA+
ICsJc3RydWN0IHJlc291cmNlCQkqYnVzbjsNCj4gPiAgCWludAkJCWlycTsNCj4gPiAgCXUzMgkJ
CWxhbmVzOw0KPiA+ICAJc3RydWN0IHBjaWVfaG9zdF9vcHMJKm9wczsNCj4gPiBkaWZmIC0tZ2l0
IGEvZHJpdmVycy9wY2kvaG9zdC9wY2llLXNwZWFyMTN4eC5jDQo+IGIvZHJpdmVycy9wY2kvaG9z
dC9wY2llLXNwZWFyMTN4eC5jDQo+ID4gaW5kZXggYzQ5ZmJkYy4uYjJjNTliOSAxMDA2NDQNCj4g
PiAtLS0gYS9kcml2ZXJzL3BjaS9ob3N0L3BjaWUtc3BlYXIxM3h4LmMNCj4gPiArKysgYi9kcml2
ZXJzL3BjaS9ob3N0L3BjaWUtc3BlYXIxM3h4LmMNCj4gPiBAQCAtMjg2LDcgKzI4Niw3IEBAIHN0
YXRpYyBpbnQgc3BlYXIxM3h4X2FkZF9wY2llX3BvcnQoc3RydWN0DQo+IHBjaWVfcG9ydCAqcHAs
DQo+ID4gIAkJcmV0dXJuIHJldDsNCj4gPiAgCX0NCj4gPg0KPiA+IC0JcHAtPnJvb3RfYnVzX25y
ID0gLTE7DQo+ID4gKwlwcC0+cm9vdF9idXNfbnIgPSBEV19ST09UX05SX1VOREVGSU5FRDsNCj4g
PiAgCXBwLT5vcHMgPSAmc3BlYXIxM3h4X3BjaWVfaG9zdF9vcHM7DQo+ID4NCj4gPiAgCXJldCA9
IGR3X3BjaWVfaG9zdF9pbml0KHBwKTsNCj4gPiAtLQ0KPiA+IDEuOS4xDQo+ID4NCj4gPg0KPiA+
ID4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gPiA+IEZyb206IEx1Y2FzIFN0YWNoIFtt
YWlsdG86bC5zdGFjaEBwZW5ndXRyb25peC5kZV0NCj4gPiA+IFNlbnQ6IFdlZG5lc2RheSwgQXVn
dXN0IDE5LCAyMDE1IDE6NTQgUE0NCj4gPiA+IFRvOiBXYW5nemhvdSAoQikNCj4gPiA+IENjOiBC
am9ybiBIZWxnYWFzOyBqaW5nb29oYW4xQGdtYWlsLmNvbTsgUHJhdHl1c2ggQW5hbmQ7IEFybmQN
Cj4gQmVyZ21hbm47DQo+ID4gPiBsaW51eEBhcm0ubGludXgub3JnLnVrOyB0aG9tYXMucGV0YXp6
b25pQGZyZWUtZWxlY3Ryb25zLmNvbTsNCj4gR2FicmllbGUNCj4gPiA+IFBhb2xvbmk7IGxvcmVu
em8ucGllcmFsaXNpQGFybS5jb207IGphbWVzLm1vcnNlQGFybS5jb207DQo+ID4gPiBMaXZpdS5E
dWRhdUBhcm0uY29tOyBqYXNvbkBsYWtlZGFlbW9uLm5ldDsgcm9iaEBrZXJuZWwub3JnOyBsaW51
eC0NCj4gPiA+IHBjaUB2Z2VyLmtlcm5lbC5vcmc7IGxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5m
cmFkZWFkLm9yZzsNCj4gPiA+IGRldmljZXRyZWVAdmdlci5rZXJuZWwub3JnOyBZdWFuemhpY2hh
bmc7IFpodWRhY2FpOyB6aGFuZ2p1a3VvOw0KPiA+ID4gcWl1emhlbmZhOyBsaXVkb25nZG9uZyAo
Qyk7IHFpdWppYW5nOyB4dXdlaSAoTyk7IExpZ3Vvemh1IChLZW5uZXRoKQ0KPiA+ID4gU3ViamVj
dDogUmU6IFtQQVRDSCB2NyAzLzZdIFBDSTogZGVzaWdud2FyZTogQWRkIEFSTTY0IHN1cHBvcnQN
Cj4gPiA+DQo+ID4gPiBBbSBNb250YWcsIGRlbiAxNy4wOC4yMDE1LCAxOTo1NSArMDgwMCBzY2hy
aWViIFpob3UgV2FuZzoNCj4gPiA+ID4gVGhpcyBwYXRjaCB0cmllcyB0byB1bmlmeSBBUk0zMiBh
bmQgQVJNNjQgUENJZSBpbiBkZXNpZ253YXJlDQo+IGRyaXZlci4NCj4gPiA+IERlbGV0ZQ0KPiA+
ID4gPiBmdW5jdGlvbiBkd19wY2llX3NldHVwLCBkd19wY2llX3NjYW5fYnVzLCBkd19wY2llX21h
cF9pcnEgYW5kDQo+IHN0cnVjdA0KPiA+ID4gaHdfcGNpLA0KPiA+ID4gPiBtb3ZlIHJlbGF0ZWQg
b3BlcmF0aW9ucyB0byBkd19wY2llX2hvc3RfaW5pdC4NCj4gPiA+ID4NCj4gPiA+ID4gSW4gcGFz
dCwgd2UgdXNlOg0KPiA+ID4gPiBwY2lfY29tbW9uX2luaXRfZGV2DQo+ID4gPiA+IAktPiBwY2li
aW9zX2luaXRfaHcNCj4gPiA+ID4gCQktPiBody0+c2NhbiAoZHdfcGNpZV9zY2FuX2J1cykNCj4g
PiA+ID4gdG8gcGFzcyAwIHRvIHJvb3RfYnVzX25yIGluIHN0cnVjdCBwY2llX3BvcnQuIFRoaXMg
cGF0Y2ggc2V0IHBwLQ0KPiA+ID4gPnJvb3RfYnVzX25yID0gMA0KPiA+ID4gPiBpbiBlYWNoIFBD
SWUgaG9zdCBkcml2ZXIgd2hpY2ggaXMgYmFzZWQgb24gcGNpZS1kZXNpZ253YXJlLg0KPiA+ID4g
Pg0KPiA+ID4gVGhpcyBpcyBpbmNvcnJlY3QgYXQgbGVhc3QgaWYgdGhlcmUgYXJlIDIgaW5zdGFu
Y2VzIG9mIERXIFBDSWUgaG9zdA0KPiBpbg0KPiA+ID4gdGhlIHNhbWUgU29DIHdpdGhvdXQgdXNp
bmcgUENJIGRvbWFpbnMuIEluIHRoYXQgdGhlIGNhc2UgdGhlIGJ1cw0KPiByYW5nZQ0KPiA+ID4g
ZGV0ZXJtaW5lcyB0aGUgcmFuZ2Ugb2YgdmFsaWQgYnVzIG51bWJlcnMgcGVyIGluc3RhbmNlIGFu
ZCB0aGUNCj4gZmlyc3QNCj4gPiA+IG51bWJlciBpcyB0aGUgcm9vdCBidXMuIFBsZWFzZSBsb29r
IGF0IHRoZSAiYnVzLXJhbmdlIiBEVCBwcm9wZXJ0eQ0KPiBpbg0KPiA+ID4gdGhlIERXIFBDSWUg
YmluZGluZ3MuDQo+ID4gPg0KPiA+ID4gQWxzbyB3ZSBzaG91bGQgZmluYWxseSByZW1vdmUgdGhp
cyByb290LWJ1cyBzZXR1cCBmcm9tIHRoZSBnbHVlDQo+IGRyaXZlcnMNCj4gPiA+IGFsdG9nZXRo
ZXIuIEl0J3Mgc29tZXRoaW5nIHRoYXQgZW50aXJlbHkgYmVsb25ncyBpbnRvIHRoZSBEVyBjb3Jl
DQo+IGNvZGUuDQo+ID4gPg0KPiA+ID4gUmVnYXJkcywNCj4gPiA+IEx1Y2FzDQo+ID4gPg0KPiA+
ID4gPiBUaGlzIHBhdGNoIGFsc28gdHJ5IHRvIHVzZSBvZl9wY2lfZ2V0X2hvc3RfYnJpZGdlX3Jl
c291cmNlcyBmb3INCj4gQVJNMzINCj4gPiA+IGFuZCBBUk02NA0KPiA+ID4gPiBhY2NvcmRpbmcg
dG8gdGhlIHN1Z2dlc3Rpb24gZm9yIEdhYnJpZWxlWzFdDQo+ID4gPiA+DQo+ID4gPiA+IEZpbmFs
bHkgdGhpcyBwYXRjaCByZXZlcnRzIGNvbW1pdCBmNGM1NWM1YTNmN2YgIlBDSTogZGVzaWdud2Fy
ZToNCj4gPiA+IFByb2dyYW0gQVRVDQo+ID4gPiA+IHdpdGggdW50cmFuc2xhdGVkIGFkZHJlc3Mi
IGJhc2VkIG9uIDEvNiBpbiB0aGlzIHNlcmllcy4gd2UgZGVsZXRlDQo+ID4gPiAqX21vZF9iYXNl
IGluDQo+ID4gPiA+IHBjaWUtZGVzaWdud2FyZS4gVGhpcyB3YXMgZGlzY3Vzc2VkIGluIFsyXQ0K
PiA+ID4gPg0KPiA+ID4gPiBJIGhhdmUgY29tcGlsZWQgdGhlIGRyaXZlciB3aXRoIG11bHRpX3Y3
X2RlZmNvbmZpZy4gSG93ZXZlciwgSQ0KPiBkb24ndA0KPiA+ID4gaGF2ZQ0KPiA+ID4gPiBBUk0z
MiBQQ0llIHJlbGF0ZWQgYm9hcmQgdG8gZG8gdGVzdC4gSXQgd2lsbCBiZSBhcHByZWNpYXRlZCBp
Zg0KPiA+ID4gc29tZW9uZSBjb3VsZA0KPiA+ID4gPiBoZWxwIHRvIHRlc3QgaXQuDQo+ID4gPiA+
DQo+ID4gPiA+IFNpZ25lZC1vZmYtYnk6IFpob3UgV2FuZyA8d2FuZ3pob3UxQGhpc2lsaWNvbi5j
b20+DQo+ID4gPiA+IFNpZ25lZC1vZmYtYnk6IEdhYnJpZWxlIFBhb2xvbmkgPGdhYnJpZWxlLnBh
b2xvbmlAaHVhd2VpLmNvbT4NCj4gPiA+ID4gU2lnbmVkLW9mZi1ieTogQXJuZCBCZXJnbWFubiA8
YXJuZEBhcm5kYi5kZT4NCj4gPiA+ID4gVGVzdGVkLUJ5OiBKYW1lcyBNb3JzZSA8amFtZXMubW9y
c2VAYXJtLmNvbT4NCj4gPiA+ID4NCj4gPiA+ID4gWzFdIGh0dHA6Ly93d3cuc3Bpbmljcy5uZXQv
bGlzdHMvbGludXgtcGNpL21zZzQyMTk0Lmh0bWwNCj4gPiA+ID4gWzJdIGh0dHA6Ly93d3cuc3Bp
bmljcy5uZXQvbGlzdHMvYXJtLWtlcm5lbC9tc2c0MzY3NzkuaHRtbA0KPiA+ID4gPiAtLS0NCj4g
PiA+ID4gIGRyaXZlcnMvcGNpL2hvc3QvcGNpLWRyYTd4eC5jICAgICAgfCAgMTUgKy0tDQo+ID4g
PiA+ICBkcml2ZXJzL3BjaS9ob3N0L3BjaS1leHlub3MuYyAgICAgIHwgICAyICstDQo+ID4gPiA+
ICBkcml2ZXJzL3BjaS9ob3N0L3BjaS1pbXg2LmMgICAgICAgIHwgICAyICstDQo+ID4gPiA+ICBk
cml2ZXJzL3BjaS9ob3N0L3BjaS1rZXlzdG9uZS1kdy5jIHwgICAyICstDQo+ID4gPiA+ICBkcml2
ZXJzL3BjaS9ob3N0L3BjaS1rZXlzdG9uZS5jICAgIHwgICAyICstDQo+ID4gPiA+ICBkcml2ZXJz
L3BjaS9ob3N0L3BjaS1sYXllcnNjYXBlLmMgIHwgICAyICstDQo+ID4gPiA+ICBkcml2ZXJzL3Bj
aS9ob3N0L3BjaWUtZGVzaWdud2FyZS5jIHwgMjI5ICsrKysrKysrKysrKy0tLS0tLS0tLS0tDQo+
IC0tLS0NCj4gPiA+IC0tLS0tLS0tLS0NCj4gPiA+ID4gIGRyaXZlcnMvcGNpL2hvc3QvcGNpZS1k
ZXNpZ253YXJlLmggfCAgMTQgKy0tDQo+ID4gPiA+ICBkcml2ZXJzL3BjaS9ob3N0L3BjaWUtc3Bl
YXIxM3h4LmMgIHwgICAyICstDQo+ID4gPiA+ICA5IGZpbGVzIGNoYW5nZWQsIDk1IGluc2VydGlv
bnMoKyksIDE3NSBkZWxldGlvbnMoLSkNCj4gPiA+ID4NCj4gPiA+ID4gZGlmZiAtLWdpdCBhL2Ry
aXZlcnMvcGNpL2hvc3QvcGNpLWRyYTd4eC5jDQo+IGIvZHJpdmVycy9wY2kvaG9zdC9wY2ktDQo+
ID4gPiBkcmE3eHguYw0KPiA+ID4gPiBpbmRleCAxOGFlN2ZmLi4xMjY4YzY5IDEwMDY0NA0KPiA+
ID4gPiAtLS0gYS9kcml2ZXJzL3BjaS9ob3N0L3BjaS1kcmE3eHguYw0KPiA+ID4gPiArKysgYi9k
cml2ZXJzL3BjaS9ob3N0L3BjaS1kcmE3eHguYw0KPiA+ID4gPiBAQCAtMTQxLDE1ICsxNDEsMTUg
QEAgc3RhdGljIHZvaWQgZHJhN3h4X3BjaWVfaG9zdF9pbml0KHN0cnVjdA0KPiA+ID4gcGNpZV9w
b3J0ICpwcCkNCj4gPiA+ID4gIHsNCj4gPiA+ID4gIAlkd19wY2llX3NldHVwX3JjKHBwKTsNCj4g
PiA+ID4NCj4gPiA+ID4gLQlpZiAocHAtPmlvX21vZF9iYXNlKQ0KPiA+ID4gPiAtCQlwcC0+aW9f
bW9kX2Jhc2UgJj0gQ1BVX1RPX0JVU19BRERSOw0KPiA+ID4gPiArCWlmIChwcC0+aW9fYmFzZSkN
Cj4gPiA+ID4gKwkJcHAtPmlvX2Jhc2UgJj0gQ1BVX1RPX0JVU19BRERSOw0KPiA+ID4gPg0KPiA+
ID4gPiAtCWlmIChwcC0+bWVtX21vZF9iYXNlKQ0KPiA+ID4gPiAtCQlwcC0+bWVtX21vZF9iYXNl
ICY9IENQVV9UT19CVVNfQUREUjsNCj4gPiA+ID4gKwlpZiAocHAtPm1lbV9iYXNlKQ0KPiA+ID4g
PiArCQlwcC0+bWVtX2Jhc2UgJj0gQ1BVX1RPX0JVU19BRERSOw0KPiA+ID4gPg0KPiA+ID4gPiAt
CWlmIChwcC0+Y2ZnMF9tb2RfYmFzZSkgew0KPiA+ID4gPiAtCQlwcC0+Y2ZnMF9tb2RfYmFzZSAm
PSBDUFVfVE9fQlVTX0FERFI7DQo+ID4gPiA+IC0JCXBwLT5jZmcxX21vZF9iYXNlICY9IENQVV9U
T19CVVNfQUREUjsNCj4gPiA+ID4gKwlpZiAocHAtPmNmZzBfYmFzZSkgew0KPiA+ID4gPiArCQlw
cC0+Y2ZnMF9iYXNlICY9IENQVV9UT19CVVNfQUREUjsNCj4gPiA+ID4gKwkJcHAtPmNmZzFfYmFz
ZSAmPSBDUFVfVE9fQlVTX0FERFI7DQo+ID4gPiA+ICAJfQ0KPiA+ID4gPg0KPiA+ID4gPiAgCWRy
YTd4eF9wY2llX2VzdGFibGlzaF9saW5rKHBwKTsNCj4gPiA+ID4gQEAgLTI4OCw2ICsyODgsNyBA
QCBzdGF0aWMgaW50IF9faW5pdCBkcmE3eHhfYWRkX3BjaWVfcG9ydChzdHJ1Y3QNCj4gPiA+IGRy
YTd4eF9wY2llICpkcmE3eHgsDQo+ID4gPiA+DQo+ID4gPiA+ICAJcHAgPSAmZHJhN3h4LT5wcDsN
Cj4gPiA+ID4gIAlwcC0+ZGV2ID0gZGV2Ow0KPiA+ID4gPiArCXBwLT5yb290X2J1c19uciA9IDA7
DQo+ID4gPiA+ICAJcHAtPm9wcyA9ICZkcmE3eHhfcGNpZV9ob3N0X29wczsNCj4gPiA+ID4NCj4g
PiA+ID4gIAlwcC0+aXJxID0gcGxhdGZvcm1fZ2V0X2lycShwZGV2LCAxKTsNCj4gPiA+ID4gZGlm
ZiAtLWdpdCBhL2RyaXZlcnMvcGNpL2hvc3QvcGNpLWV4eW5vcy5jDQo+IGIvZHJpdmVycy9wY2kv
aG9zdC9wY2ktDQo+ID4gPiBleHlub3MuYw0KPiA+ID4gPiBpbmRleCBmOWY0NjhkLi45NzcxYmIw
IDEwMDY0NA0KPiA+ID4gPiAtLS0gYS9kcml2ZXJzL3BjaS9ob3N0L3BjaS1leHlub3MuYw0KPiA+
ID4gPiArKysgYi9kcml2ZXJzL3BjaS9ob3N0L3BjaS1leHlub3MuYw0KPiA+ID4gPiBAQCAtNTMw
LDcgKzUzMCw3IEBAIHN0YXRpYyBpbnQgX19pbml0IGV4eW5vc19hZGRfcGNpZV9wb3J0KHN0cnVj
dA0KPiA+ID4gcGNpZV9wb3J0ICpwcCwNCj4gPiA+ID4gIAkJfQ0KPiA+ID4gPiAgCX0NCj4gPiA+
ID4NCj4gPiA+ID4gLQlwcC0+cm9vdF9idXNfbnIgPSAtMTsNCj4gPiA+ID4gKwlwcC0+cm9vdF9i
dXNfbnIgPSAwOw0KPiA+ID4gPiAgCXBwLT5vcHMgPSAmZXh5bm9zX3BjaWVfaG9zdF9vcHM7DQo+
ID4gPiA+DQo+ID4gPiA+ICAJcmV0ID0gZHdfcGNpZV9ob3N0X2luaXQocHApOw0KPiA+ID4gPiBk
aWZmIC0tZ2l0IGEvZHJpdmVycy9wY2kvaG9zdC9wY2ktaW14Ni5jIGIvZHJpdmVycy9wY2kvaG9z
dC9wY2ktDQo+ID4gPiBpbXg2LmMNCj4gPiA+ID4gaW5kZXggMjMzYTE5Ni4uYmVjMjU2YyAxMDA2
NDQNCj4gPiA+ID4gLS0tIGEvZHJpdmVycy9wY2kvaG9zdC9wY2ktaW14Ni5jDQo+ID4gPiA+ICsr
KyBiL2RyaXZlcnMvcGNpL2hvc3QvcGNpLWlteDYuYw0KPiA+ID4gPiBAQCAtNTUxLDcgKzU1MSw3
IEBAIHN0YXRpYyBpbnQgX19pbml0IGlteDZfYWRkX3BjaWVfcG9ydChzdHJ1Y3QNCj4gPiA+IHBj
aWVfcG9ydCAqcHAsDQo+ID4gPiA+ICAJCX0NCj4gPiA+ID4gIAl9DQo+ID4gPiA+DQo+ID4gPiA+
IC0JcHAtPnJvb3RfYnVzX25yID0gLTE7DQo+ID4gPiA+ICsJcHAtPnJvb3RfYnVzX25yID0gMDsN
Cj4gPiA+ID4gIAlwcC0+b3BzID0gJmlteDZfcGNpZV9ob3N0X29wczsNCj4gPiA+ID4NCj4gPiA+
ID4gIAlyZXQgPSBkd19wY2llX2hvc3RfaW5pdChwcCk7DQo+ID4gPiA+IGRpZmYgLS1naXQgYS9k
cml2ZXJzL3BjaS9ob3N0L3BjaS1rZXlzdG9uZS1kdy5jDQo+ID4gPiBiL2RyaXZlcnMvcGNpL2hv
c3QvcGNpLWtleXN0b25lLWR3LmMNCj4gPiA+ID4gaW5kZXggZjM0ODkyZS4uYjFlNDEzNSAxMDA2
NDQNCj4gPiA+ID4gLS0tIGEvZHJpdmVycy9wY2kvaG9zdC9wY2kta2V5c3RvbmUtZHcuYw0KPiA+
ID4gPiArKysgYi9kcml2ZXJzL3BjaS9ob3N0L3BjaS1rZXlzdG9uZS1kdy5jDQo+ID4gPiA+IEBA
IC0zMjcsNyArMzI3LDcgQEAgc3RhdGljIHZvaWQga3NfZHdfcGNpZV9jbGVhcl9kYmlfbW9kZSh2
b2lkDQo+ID4gPiBfX2lvbWVtICpyZWdfdmlydCkNCj4gPiA+ID4gIHZvaWQga3NfZHdfcGNpZV9z
ZXR1cF9yY19hcHBfcmVncyhzdHJ1Y3Qga2V5c3RvbmVfcGNpZSAqa3NfcGNpZSkNCj4gPiA+ID4g
IHsNCj4gPiA+ID4gIAlzdHJ1Y3QgcGNpZV9wb3J0ICpwcCA9ICZrc19wY2llLT5wcDsNCj4gPiA+
ID4gLQl1MzIgc3RhcnQgPSBwcC0+bWVtLnN0YXJ0LCBlbmQgPSBwcC0+bWVtLmVuZDsNCj4gPiA+
ID4gKwl1MzIgc3RhcnQgPSBwcC0+bWVtLT5zdGFydCwgZW5kID0gcHAtPm1lbS0+ZW5kOw0KPiA+
ID4gPiAgCWludCBpLCB0cl9zaXplOw0KPiA+ID4gPg0KPiA+ID4gPiAgCS8qIERpc2FibGUgQkFS
cyBmb3IgaW5ib3VuZCBhY2Nlc3MgKi8NCj4gPiA+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvcGNp
L2hvc3QvcGNpLWtleXN0b25lLmMNCj4gYi9kcml2ZXJzL3BjaS9ob3N0L3BjaS0NCj4gPiA+IGtl
eXN0b25lLmMNCj4gPiA+ID4gaW5kZXggNzM0ZGE1OC4uODExMzgzMiAxMDA2NDQNCj4gPiA+ID4g
LS0tIGEvZHJpdmVycy9wY2kvaG9zdC9wY2kta2V5c3RvbmUuYw0KPiA+ID4gPiArKysgYi9kcml2
ZXJzL3BjaS9ob3N0L3BjaS1rZXlzdG9uZS5jDQo+ID4gPiA+IEBAIC0zMDksNyArMzA5LDcgQEAg
c3RhdGljIGludCBfX2luaXQga3NfYWRkX3BjaWVfcG9ydChzdHJ1Y3QNCj4gPiA+IGtleXN0b25l
X3BjaWUgKmtzX3BjaWUsDQo+ID4gPiA+ICAJCQlyZXR1cm4gcmV0Ow0KPiA+ID4gPiAgCX0NCj4g
PiA+ID4NCj4gPiA+ID4gLQlwcC0+cm9vdF9idXNfbnIgPSAtMTsNCj4gPiA+ID4gKwlwcC0+cm9v
dF9idXNfbnIgPSAwOw0KPiA+ID4gPiAgCXBwLT5vcHMgPSAma2V5c3RvbmVfcGNpZV9ob3N0X29w
czsNCj4gPiA+ID4gIAlyZXQgPSBrc19kd19wY2llX2hvc3RfaW5pdChrc19wY2llLCBrc19wY2ll
LT5tc2lfaW50Y19ucCk7DQo+ID4gPiA+ICAJaWYgKHJldCkgew0KPiA+ID4gPiBkaWZmIC0tZ2l0
IGEvZHJpdmVycy9wY2kvaG9zdC9wY2ktbGF5ZXJzY2FwZS5jDQo+ID4gPiBiL2RyaXZlcnMvcGNp
L2hvc3QvcGNpLWxheWVyc2NhcGUuYw0KPiA+ID4gPiBpbmRleCBiMjMyOGVhMS4uNzlmZjA4YyAx
MDA2NDQNCj4gPiA+ID4gLS0tIGEvZHJpdmVycy9wY2kvaG9zdC9wY2ktbGF5ZXJzY2FwZS5jDQo+
ID4gPiA+ICsrKyBiL2RyaXZlcnMvcGNpL2hvc3QvcGNpLWxheWVyc2NhcGUuYw0KPiA+ID4gPiBA
QCAtMTA2LDcgKzEwNiw3IEBAIHN0YXRpYyBpbnQgbHNfYWRkX3BjaWVfcG9ydChzdHJ1Y3QgbHNf
cGNpZQ0KPiAqcGNpZSkNCj4gPiA+ID4gIAlwcCA9ICZwY2llLT5wcDsNCj4gPiA+ID4gIAlwcC0+
ZGV2ID0gcGNpZS0+ZGV2Ow0KPiA+ID4gPiAgCXBwLT5kYmlfYmFzZSA9IHBjaWUtPmRiaTsNCj4g
PiA+ID4gLQlwcC0+cm9vdF9idXNfbnIgPSAtMTsNCj4gPiA+ID4gKwlwcC0+cm9vdF9idXNfbnIg
PSAwOw0KPiA+ID4gPiAgCXBwLT5vcHMgPSAmbHNfcGNpZV9ob3N0X29wczsNCj4gPiA+ID4NCj4g
PiA+ID4gIAlyZXQgPSBkd19wY2llX2hvc3RfaW5pdChwcCk7DQo+ID4gPiA+IGRpZmYgLS1naXQg
YS9kcml2ZXJzL3BjaS9ob3N0L3BjaWUtZGVzaWdud2FyZS5jDQo+ID4gPiBiL2RyaXZlcnMvcGNp
L2hvc3QvcGNpZS1kZXNpZ253YXJlLmMNCj4gPiA+ID4gaW5kZXggYzVkNDA3Yy4uZTcxYTg4ZSAx
MDA2NDQNCj4gPiA+ID4gLS0tIGEvZHJpdmVycy9wY2kvaG9zdC9wY2llLWRlc2lnbndhcmUuYw0K
PiA+ID4gPiArKysgYi9kcml2ZXJzL3BjaS9ob3N0L3BjaWUtZGVzaWdud2FyZS5jDQo+ID4gPiA+
IEBAIC0xMSw2ICsxMSw3IEBADQo+ID4gPiA+ICAgKiBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29m
dHdhcmUgRm91bmRhdGlvbi4NCj4gPiA+ID4gICAqLw0KPiA+ID4gPg0KPiA+ID4gPiArI2luY2x1
ZGUgPGxpbnV4L2hhcmRpcnEuaD4NCj4gPiA+ID4gICNpbmNsdWRlIDxsaW51eC9pcnEuaD4NCj4g
PiA+ID4gICNpbmNsdWRlIDxsaW51eC9pcnFkb21haW4uaD4NCj4gPiA+ID4gICNpbmNsdWRlIDxs
aW51eC9rZXJuZWwuaD4NCj4gPiA+ID4gQEAgLTY5LDE2ICs3MCw3IEBADQo+ID4gPiA+ICAjZGVm
aW5lIFBDSUVfQVRVX0ZVTkMoeCkJCSgoKHgpICYgMHg3KSA8PCAxNikNCj4gPiA+ID4gICNkZWZp
bmUgUENJRV9BVFVfVVBQRVJfVEFSR0VUCQkweDkxQw0KPiA+ID4gPg0KPiA+ID4gPiAtc3RhdGlj
IHN0cnVjdCBod19wY2kgZHdfcGNpOw0KPiA+ID4gPiAtDQo+ID4gPiA+IC1zdGF0aWMgdW5zaWdu
ZWQgbG9uZyBnbG9iYWxfaW9fb2Zmc2V0Ow0KPiA+ID4gPiAtDQo+ID4gPiA+IC1zdGF0aWMgaW5s
aW5lIHN0cnVjdCBwY2llX3BvcnQgKnN5c190b19wY2llKHN0cnVjdCBwY2lfc3lzX2RhdGENCj4g
KnN5cykNCj4gPiA+ID4gLXsNCj4gPiA+ID4gLQlCVUdfT04oIXN5cy0+cHJpdmF0ZV9kYXRhKTsN
Cj4gPiA+ID4gLQ0KPiA+ID4gPiAtCXJldHVybiBzeXMtPnByaXZhdGVfZGF0YTsNCj4gPiA+ID4g
LX0NCj4gPiA+ID4gK3N0YXRpYyBzdHJ1Y3QgcGNpX29wcyBkd19wY2llX29wczsNCj4gPiA+ID4N
Cj4gPiA+ID4gIGludCBkd19wY2llX2NmZ19yZWFkKHZvaWQgX19pb21lbSAqYWRkciwgaW50IHdo
ZXJlLCBpbnQgc2l6ZSwNCj4gdTMyDQo+ID4gPiAqdmFsKQ0KPiA+ID4gPiAgew0KPiA+ID4gPiBA
QCAtMjU1LDcgKzI0Nyw3IEBAIHN0YXRpYyB2b2lkIGR3X3BjaWVfbXNpX3NldF9pcnEoc3RydWN0
DQo+IHBjaWVfcG9ydA0KPiA+ID4gKnBwLCBpbnQgaXJxKQ0KPiA+ID4gPiAgc3RhdGljIGludCBh
c3NpZ25faXJxKGludCBub19pcnFzLCBzdHJ1Y3QgbXNpX2Rlc2MgKmRlc2MsIGludA0KPiAqcG9z
KQ0KPiA+ID4gPiAgew0KPiA+ID4gPiAgCWludCBpcnEsIHBvczAsIGk7DQo+ID4gPiA+IC0Jc3Ry
dWN0IHBjaWVfcG9ydCAqcHAgPSBzeXNfdG9fcGNpZShkZXNjLT5kZXYtPmJ1cy0+c3lzZGF0YSk7
DQo+ID4gPiA+ICsJc3RydWN0IHBjaWVfcG9ydCAqcHAgPSBkZXNjLT5kZXYtPmJ1cy0+c3lzZGF0
YTsNCj4gPiA+ID4NCj4gPiA+ID4gIAlwb3MwID0gYml0bWFwX2ZpbmRfZnJlZV9yZWdpb24ocHAt
Pm1zaV9pcnFfaW5fdXNlLA0KPiBNQVhfTVNJX0lSUVMsDQo+ID4gPiA+ICAJCQkJICAgICAgIG9y
ZGVyX2Jhc2VfMihub19pcnFzKSk7DQo+ID4gPiA+IEBAIC0yOTgsNyArMjkwLDcgQEAgc3RhdGlj
IGludCBkd19tc2lfc2V0dXBfaXJxKHN0cnVjdA0KPiBtc2lfY29udHJvbGxlcg0KPiA+ID4gKmNo
aXAsIHN0cnVjdCBwY2lfZGV2ICpwZGV2LA0KPiA+ID4gPiAgew0KPiA+ID4gPiAgCWludCBpcnEs
IHBvczsNCj4gPiA+ID4gIAlzdHJ1Y3QgbXNpX21zZyBtc2c7DQo+ID4gPiA+IC0Jc3RydWN0IHBj
aWVfcG9ydCAqcHAgPSBzeXNfdG9fcGNpZShwZGV2LT5idXMtPnN5c2RhdGEpOw0KPiA+ID4gPiAr
CXN0cnVjdCBwY2llX3BvcnQgKnBwID0gcGRldi0+YnVzLT5zeXNkYXRhOw0KPiA+ID4gPg0KPiA+
ID4gPiAgCWlmIChkZXNjLT5tc2lfYXR0cmliLmlzX21zaXgpDQo+ID4gPiA+ICAJCXJldHVybiAt
RUlOVkFMOw0KPiA+ID4gPiBAQCAtMzI3LDcgKzMxOSw3IEBAIHN0YXRpYyB2b2lkIGR3X21zaV90
ZWFyZG93bl9pcnEoc3RydWN0DQo+ID4gPiBtc2lfY29udHJvbGxlciAqY2hpcCwgdW5zaWduZWQg
aW50IGlycSkNCj4gPiA+ID4gIHsNCj4gPiA+ID4gIAlzdHJ1Y3QgaXJxX2RhdGEgKmRhdGEgPSBp
cnFfZ2V0X2lycV9kYXRhKGlycSk7DQo+ID4gPiA+ICAJc3RydWN0IG1zaV9kZXNjICptc2kgPSBp
cnFfZGF0YV9nZXRfbXNpKGRhdGEpOw0KPiA+ID4gPiAtCXN0cnVjdCBwY2llX3BvcnQgKnBwID0g
c3lzX3RvX3BjaWUobXNpLT5kZXYtPmJ1cy0+c3lzZGF0YSk7DQo+ID4gPiA+ICsJc3RydWN0IHBj
aWVfcG9ydCAqcHAgPSBtc2ktPmRldi0+YnVzLT5zeXNkYXRhOw0KPiA+ID4gPg0KPiA+ID4gPiAg
CWNsZWFyX2lycV9yYW5nZShwcCwgaXJxLCAxLCBkYXRhLT5od2lycSk7DQo+ID4gPiA+ICB9DQo+
ID4gPiA+IEBAIC0zNjMsMTQgKzM1NSwxMiBAQCBpbnQgZHdfcGNpZV9ob3N0X2luaXQoc3RydWN0
IHBjaWVfcG9ydCAqcHApDQo+ID4gPiA+ICB7DQo+ID4gPiA+ICAJc3RydWN0IGRldmljZV9ub2Rl
ICpucCA9IHBwLT5kZXYtPm9mX25vZGU7DQo+ID4gPiA+ICAJc3RydWN0IHBsYXRmb3JtX2Rldmlj
ZSAqcGRldiA9IHRvX3BsYXRmb3JtX2RldmljZShwcC0+ZGV2KTsNCj4gPiA+ID4gLQlzdHJ1Y3Qg
b2ZfcGNpX3JhbmdlIHJhbmdlOw0KPiA+ID4gPiAtCXN0cnVjdCBvZl9wY2lfcmFuZ2VfcGFyc2Vy
IHBhcnNlcjsNCj4gPiA+ID4gKwlzdHJ1Y3QgcGNpX2J1cyAqYnVzOw0KPiA+ID4gPiAgCXN0cnVj
dCByZXNvdXJjZSAqY2ZnX3JlczsNCj4gPiA+ID4gLQl1MzIgdmFsLCBuczsNCj4gPiA+ID4gLQlj
b25zdCBfX2JlMzIgKmFkZHJwOw0KPiA+ID4gPiAtCWludCBpLCBpbmRleCwgcmV0Ow0KPiA+ID4g
PiAtDQo+ID4gPiA+IC0JbnMgPSBvZl9uX3NpemVfY2VsbHMobnApOw0KPiA+ID4gPiArCUxJU1Rf
SEVBRChyZXMpOw0KPiA+ID4gPiArCXUzMiB2YWw7DQo+ID4gPiA+ICsJaW50IGksIHJldDsNCj4g
PiA+ID4gKwlzdHJ1Y3QgcmVzb3VyY2VfZW50cnkgKndpbjsNCj4gPiA+ID4NCj4gPiA+ID4gIAlj
ZmdfcmVzID0gcGxhdGZvcm1fZ2V0X3Jlc291cmNlX2J5bmFtZShwZGV2LCBJT1JFU09VUkNFX01F
TSwNCj4gPiA+ICJjb25maWciKTsNCj4gPiA+ID4gIAlpZiAoY2ZnX3Jlcykgew0KPiA+ID4gPiBA
QCAtMzc4LDg1ICszNjgsNjAgQEAgaW50IGR3X3BjaWVfaG9zdF9pbml0KHN0cnVjdCBwY2llX3Bv
cnQgKnBwKQ0KPiA+ID4gPiAgCQlwcC0+Y2ZnMV9zaXplID0gcmVzb3VyY2Vfc2l6ZShjZmdfcmVz
KS8yOw0KPiA+ID4gPiAgCQlwcC0+Y2ZnMF9iYXNlID0gY2ZnX3Jlcy0+c3RhcnQ7DQo+ID4gPiA+
ICAJCXBwLT5jZmcxX2Jhc2UgPSBjZmdfcmVzLT5zdGFydCArIHBwLT5jZmcwX3NpemU7DQo+ID4g
PiA+IC0NCj4gPiA+ID4gLQkJLyogRmluZCB0aGUgdW50cmFuc2xhdGVkIGNvbmZpZ3VyYXRpb24g
c3BhY2UgYWRkcmVzcw0KPiAqLw0KPiA+ID4gPiAtCQlpbmRleCA9IG9mX3Byb3BlcnR5X21hdGNo
X3N0cmluZyhucCwgInJlZy1uYW1lcyIsDQo+ICJjb25maWciKTsNCj4gPiA+ID4gLQkJYWRkcnAg
PSBvZl9nZXRfYWRkcmVzcyhucCwgaW5kZXgsIE5VTEwsIE5VTEwpOw0KPiA+ID4gPiAtCQlwcC0+
Y2ZnMF9tb2RfYmFzZSA9IG9mX3JlYWRfbnVtYmVyKGFkZHJwLCBucyk7DQo+ID4gPiA+IC0JCXBw
LT5jZmcxX21vZF9iYXNlID0gcHAtPmNmZzBfbW9kX2Jhc2UgKyBwcC0+Y2ZnMF9zaXplOw0KPiA+
ID4gPiAgCX0gZWxzZSB7DQo+ID4gPiA+ICAJCWRldl9lcnIocHAtPmRldiwgIm1pc3NpbmcgKmNv
bmZpZyogcmVnIHNwYWNlXG4iKTsNCj4gPiA+ID4gIAl9DQo+ID4gPiA+DQo+ID4gPiA+IC0JaWYg
KG9mX3BjaV9yYW5nZV9wYXJzZXJfaW5pdCgmcGFyc2VyLCBucCkpIHsNCj4gPiA+ID4gLQkJZGV2
X2VycihwcC0+ZGV2LCAibWlzc2luZyByYW5nZXMgcHJvcGVydHlcbiIpOw0KPiA+ID4gPiAtCQly
ZXR1cm4gLUVJTlZBTDsNCj4gPiA+ID4gLQl9DQo+ID4gPiA+ICsJcmV0ID0gb2ZfcGNpX2dldF9o
b3N0X2JyaWRnZV9yZXNvdXJjZXMobnAsIDAsIDB4ZmYsICZyZXMsDQo+ICZwcC0NCj4gPiA+ID5p
b19iYXNlKTsNCj4gPiA+ID4gKwlpZiAocmV0KQ0KPiA+ID4gPiArCQlyZXR1cm4gcmV0Ow0KPiA+
ID4gPg0KPiA+ID4gPiAgCS8qIEdldCB0aGUgSS9PIGFuZCBtZW1vcnkgcmFuZ2VzIGZyb20gRFQg
Ki8NCj4gPiA+ID4gLQlmb3JfZWFjaF9vZl9wY2lfcmFuZ2UoJnBhcnNlciwgJnJhbmdlKSB7DQo+
ID4gPiA+IC0JCXVuc2lnbmVkIGxvbmcgcmVzdHlwZSA9IHJhbmdlLmZsYWdzICYNCj4gSU9SRVNP
VVJDRV9UWVBFX0JJVFM7DQo+ID4gPiA+IC0NCj4gPiA+ID4gLQkJaWYgKHJlc3R5cGUgPT0gSU9S
RVNPVVJDRV9JTykgew0KPiA+ID4gPiAtCQkJb2ZfcGNpX3JhbmdlX3RvX3Jlc291cmNlKCZyYW5n
ZSwgbnAsICZwcC0+aW8pOw0KPiA+ID4gPiAtCQkJcHAtPmlvLm5hbWUgPSAiSS9PIjsNCj4gPiA+
ID4gLQkJCXBwLT5pby5zdGFydCA9IG1heF90KHJlc291cmNlX3NpemVfdCwNCj4gPiA+ID4gLQkJ
CQkJICAgICBQQ0lCSU9TX01JTl9JTywNCj4gPiA+ID4gLQkJCQkJICAgICByYW5nZS5wY2lfYWRk
ciArDQo+IGdsb2JhbF9pb19vZmZzZXQpOw0KPiA+ID4gPiAtCQkJcHAtPmlvLmVuZCA9IG1pbl90
KHJlc291cmNlX3NpemVfdCwNCj4gPiA+ID4gLQkJCQkJICAgSU9fU1BBQ0VfTElNSVQsDQo+ID4g
PiA+IC0JCQkJCSAgIHJhbmdlLnBjaV9hZGRyICsgcmFuZ2Uuc2l6ZQ0KPiA+ID4gPiAtCQkJCQkg
ICArIGdsb2JhbF9pb19vZmZzZXQgLSAxKTsNCj4gPiA+ID4gLQkJCXBwLT5pb19zaXplID0gcmVz
b3VyY2Vfc2l6ZSgmcHAtPmlvKTsNCj4gPiA+ID4gLQkJCXBwLT5pb19idXNfYWRkciA9IHJhbmdl
LnBjaV9hZGRyOw0KPiA+ID4gPiAtCQkJcHAtPmlvX2Jhc2UgPSByYW5nZS5jcHVfYWRkcjsNCj4g
PiA+ID4gLQ0KPiA+ID4gPiAtCQkJLyogRmluZCB0aGUgdW50cmFuc2xhdGVkIElPIHNwYWNlIGFk
ZHJlc3MgKi8NCj4gPiA+ID4gLQkJCXBwLT5pb19tb2RfYmFzZSA9IHJhbmdlLmNwdV9hZGRyOw0K
PiA+ID4gPiAtCQl9DQo+ID4gPiA+IC0JCWlmIChyZXN0eXBlID09IElPUkVTT1VSQ0VfTUVNKSB7
DQo+ID4gPiA+IC0JCQlvZl9wY2lfcmFuZ2VfdG9fcmVzb3VyY2UoJnJhbmdlLCBucCwgJnBwLT5t
ZW0pOw0KPiA+ID4gPiAtCQkJcHAtPm1lbS5uYW1lID0gIk1FTSI7DQo+ID4gPiA+IC0JCQlwcC0+
bWVtX3NpemUgPSByZXNvdXJjZV9zaXplKCZwcC0+bWVtKTsNCj4gPiA+ID4gLQkJCXBwLT5tZW1f
YnVzX2FkZHIgPSByYW5nZS5wY2lfYWRkcjsNCj4gPiA+ID4gLQ0KPiA+ID4gPiAtCQkJLyogRmlu
ZCB0aGUgdW50cmFuc2xhdGVkIE1FTSBzcGFjZSBhZGRyZXNzICovDQo+ID4gPiA+IC0JCQlwcC0+
bWVtX21vZF9iYXNlID0gcmFuZ2UuY3B1X2FkZHI7DQo+ID4gPiA+IC0JCX0NCj4gPiA+ID4gLQkJ
aWYgKHJlc3R5cGUgPT0gMCkgew0KPiA+ID4gPiAtCQkJb2ZfcGNpX3JhbmdlX3RvX3Jlc291cmNl
KCZyYW5nZSwgbnAsICZwcC0+Y2ZnKTsNCj4gPiA+ID4gLQkJCXBwLT5jZmcwX3NpemUgPSByZXNv
dXJjZV9zaXplKCZwcC0+Y2ZnKS8yOw0KPiA+ID4gPiAtCQkJcHAtPmNmZzFfc2l6ZSA9IHJlc291
cmNlX3NpemUoJnBwLT5jZmcpLzI7DQo+ID4gPiA+IC0JCQlwcC0+Y2ZnMF9iYXNlID0gcHAtPmNm
Zy5zdGFydDsNCj4gPiA+ID4gLQkJCXBwLT5jZmcxX2Jhc2UgPSBwcC0+Y2ZnLnN0YXJ0ICsgcHAt
PmNmZzBfc2l6ZTsNCj4gPiA+ID4gLQ0KPiA+ID4gPiAtCQkJLyogRmluZCB0aGUgdW50cmFuc2xh
dGVkIGNvbmZpZ3VyYXRpb24gc3BhY2UNCj4gYWRkcmVzcw0KPiA+ID4gKi8NCj4gPiA+ID4gLQkJ
CXBwLT5jZmcwX21vZF9iYXNlID0gcmFuZ2UuY3B1X2FkZHI7DQo+ID4gPiA+IC0JCQlwcC0+Y2Zn
MV9tb2RfYmFzZSA9IHBwLT5jZmcwX21vZF9iYXNlICsNCj4gPiA+ID4gLQkJCQkJICAgIHBwLT5j
ZmcwX3NpemU7DQo+ID4gPiA+ICsJcmVzb3VyY2VfbGlzdF9mb3JfZWFjaF9lbnRyeSh3aW4sICZy
ZXMpIHsNCj4gPiA+ID4gKwkJc3dpdGNoIChyZXNvdXJjZV90eXBlKHdpbi0+cmVzKSkgew0KPiA+
ID4gPiArCQljYXNlIElPUkVTT1VSQ0VfSU86DQo+ID4gPiA+ICsJCQlwcC0+aW8gPSB3aW4tPnJl
czsNCj4gPiA+ID4gKwkJCXBwLT5pby0+bmFtZSA9ICJJL08iOw0KPiA+ID4gPiArCQkJcHAtPmlv
X3NpemUgPSByZXNvdXJjZV9zaXplKHBwLT5pbyk7DQo+ID4gPiA+ICsJCQlwcC0+aW9fYnVzX2Fk
ZHIgPSBwcC0+aW8tPnN0YXJ0IC0gd2luLT5vZmZzZXQ7DQo+ID4gPiA+ICsJCQlyZXQgPSBwY2lf
cmVtYXBfaW9zcGFjZShwcC0+aW8sIHBwLT5pb19iYXNlKTsNCj4gPiA+ID4gKwkJCWlmIChyZXQp
IHsNCj4gPiA+ID4gKwkJCQlkZXZfd2FybihwcC0+ZGV2LCAiZXJyb3IgJWQ6IGZhaWxlZCB0bw0K
PiBtYXANCj4gPiA+IHJlc291cmNlICVwUlxuIiwNCj4gPiA+ID4gKwkJCQkJIHJldCwgcHAtPmlv
KTsNCj4gPiA+ID4gKwkJCQljb250aW51ZTsNCj4gPiA+ID4gKwkJCX0NCj4gPiA+ID4gKwkJCWJy
ZWFrOw0KPiA+ID4gPiArCQljYXNlIElPUkVTT1VSQ0VfTUVNOg0KPiA+ID4gPiArCQkJcHAtPm1l
bSA9IHdpbi0+cmVzOw0KPiA+ID4gPiArCQkJcHAtPm1lbS0+bmFtZSA9ICJNRU0iOw0KPiA+ID4g
PiArCQkJcHAtPm1lbV9zaXplID0gcmVzb3VyY2Vfc2l6ZShwcC0+bWVtKTsNCj4gPiA+ID4gKwkJ
CXBwLT5tZW1fYnVzX2FkZHIgPSBwcC0+bWVtLT5zdGFydCAtIHdpbi0+b2Zmc2V0Ow0KPiA+ID4g
PiArCQkJYnJlYWs7DQo+ID4gPiA+ICsJCWNhc2UgMDoNCj4gPiA+ID4gKwkJCXBwLT5jZmcgPSB3
aW4tPnJlczsNCj4gPiA+ID4gKwkJCXBwLT5jZmcwX3NpemUgPSByZXNvdXJjZV9zaXplKHBwLT5j
ZmcpLzI7DQo+ID4gPiA+ICsJCQlwcC0+Y2ZnMV9zaXplID0gcmVzb3VyY2Vfc2l6ZShwcC0+Y2Zn
KS8yOw0KPiA+ID4gPiArCQkJcHAtPmNmZzBfYmFzZSA9IHBwLT5jZmctPnN0YXJ0Ow0KPiA+ID4g
PiArCQkJcHAtPmNmZzFfYmFzZSA9IHBwLT5jZmctPnN0YXJ0ICsgcHAtPmNmZzBfc2l6ZTsNCj4g
PiA+ID4gKwkJCWJyZWFrOw0KPiA+ID4gPiArCQljYXNlIElPUkVTT1VSQ0VfQlVTOg0KPiA+ID4g
PiArCQkJcHAtPmJ1c24gPSB3aW4tPnJlczsNCj4gPiA+ID4gKwkJCWJyZWFrOw0KPiA+ID4gPiAr
CQlkZWZhdWx0Og0KPiA+ID4gPiArCQkJY29udGludWU7DQo+ID4gPiA+ICAJCX0NCj4gPiA+ID4g
IAl9DQo+ID4gPiA+DQo+ID4gPiA+IC0JcmV0ID0gb2ZfcGNpX3BhcnNlX2J1c19yYW5nZShucCwg
JnBwLT5idXNuKTsNCj4gPiA+ID4gLQlpZiAocmV0IDwgMCkgew0KPiA+ID4gPiAtCQlwcC0+YnVz
bi5uYW1lID0gbnAtPm5hbWU7DQo+ID4gPiA+IC0JCXBwLT5idXNuLnN0YXJ0ID0gMDsNCj4gPiA+
ID4gLQkJcHAtPmJ1c24uZW5kID0gMHhmZjsNCj4gPiA+ID4gLQkJcHAtPmJ1c24uZmxhZ3MgPSBJ
T1JFU09VUkNFX0JVUzsNCj4gPiA+ID4gLQkJZGV2X2RiZyhwcC0+ZGV2LCAiZmFpbGVkIHRvIHBh
cnNlIGJ1cy1yYW5nZQ0KPiBwcm9wZXJ0eTogJWQsDQo+ID4gPiB1c2luZyBkZWZhdWx0ICVwUlxu
IiwNCj4gPiA+ID4gLQkJCXJldCwgJnBwLT5idXNuKTsNCj4gPiA+ID4gLQl9DQo+ID4gPiA+IC0N
Cj4gPiA+ID4gIAlpZiAoIXBwLT5kYmlfYmFzZSkgew0KPiA+ID4gPiAtCQlwcC0+ZGJpX2Jhc2Ug
PSBkZXZtX2lvcmVtYXAocHAtPmRldiwgcHAtPmNmZy5zdGFydCwNCj4gPiA+ID4gLQkJCQkJcmVz
b3VyY2Vfc2l6ZSgmcHAtPmNmZykpOw0KPiA+ID4gPiArCQlwcC0+ZGJpX2Jhc2UgPSBkZXZtX2lv
cmVtYXAocHAtPmRldiwgcHAtPmNmZy0+c3RhcnQsDQo+ID4gPiA+ICsJCQkJCXJlc291cmNlX3Np
emUocHAtPmNmZykpOw0KPiA+ID4gPiAgCQlpZiAoIXBwLT5kYmlfYmFzZSkgew0KPiA+ID4gPiAg
CQkJZGV2X2VycihwcC0+ZGV2LCAiZXJyb3Igd2l0aCBpb3JlbWFwXG4iKTsNCj4gPiA+ID4gIAkJ
CXJldHVybiAtRU5PTUVNOw0KPiA+ID4gPiAgCQl9DQo+ID4gPiA+ICAJfQ0KPiA+ID4gPg0KPiA+
ID4gPiAtCXBwLT5tZW1fYmFzZSA9IHBwLT5tZW0uc3RhcnQ7DQo+ID4gPiA+ICsJcHAtPm1lbV9i
YXNlID0gcHAtPm1lbS0+c3RhcnQ7DQo+ID4gPiA+DQo+ID4gPiA+ICAJaWYgKCFwcC0+dmFfY2Zn
MF9iYXNlKSB7DQo+ID4gPiA+ICAJCXBwLT52YV9jZmcwX2Jhc2UgPSBkZXZtX2lvcmVtYXAocHAt
PmRldiwgcHAtDQo+ID5jZmcwX2Jhc2UsDQo+ID4gPiA+IEBAIC01MDUsNyArNDcwLDcgQEAgaW50
IGR3X3BjaWVfaG9zdF9pbml0KHN0cnVjdCBwY2llX3BvcnQgKnBwKQ0KPiA+ID4gPg0KPiA+ID4g
PiAgCWlmICghcHAtPm9wcy0+cmRfb3RoZXJfY29uZikNCj4gPiA+ID4gIAkJZHdfcGNpZV9wcm9n
X291dGJvdW5kX2F0dShwcCwgUENJRV9BVFVfUkVHSU9OX0lOREVYMSwNCj4gPiA+ID4gLQkJCQkJ
ICBQQ0lFX0FUVV9UWVBFX01FTSwgcHAtDQo+ID5tZW1fbW9kX2Jhc2UsDQo+ID4gPiA+ICsJCQkJ
CSAgUENJRV9BVFVfVFlQRV9NRU0sIHBwLT5tZW1fYmFzZSwNCj4gPiA+ID4gIAkJCQkJICBwcC0+
bWVtX2J1c19hZGRyLCBwcC0+bWVtX3NpemUpOw0KPiA+ID4gPg0KPiA+ID4gPiAgCWR3X3BjaWVf
d3Jfb3duX2NvbmYocHAsIFBDSV9CQVNFX0FERFJFU1NfMCwgNCwgMCk7DQo+ID4gPiA+IEBAIC01
MTcsMTUgKzQ4MiwyOSBAQCBpbnQgZHdfcGNpZV9ob3N0X2luaXQoc3RydWN0IHBjaWVfcG9ydCAq
cHApDQo+ID4gPiA+ICAJdmFsIHw9IFBPUlRfTE9HSUNfU1BFRURfQ0hBTkdFOw0KPiA+ID4gPiAg
CWR3X3BjaWVfd3Jfb3duX2NvbmYocHAsIFBDSUVfTElOS19XSURUSF9TUEVFRF9DT05UUk9MLCA0
LA0KPiB2YWwpOw0KPiA+ID4gPg0KPiA+ID4gPiAtI2lmZGVmIENPTkZJR19QQ0lfTVNJDQo+ID4g
PiA+ICsJYnVzID0gcGNpX2NyZWF0ZV9yb290X2J1cyhwcC0+ZGV2LCBwcC0+cm9vdF9idXNfbnIs
DQo+ICZkd19wY2llX29wcywNCj4gPiA+ID4gKwkJCQkgIHBwLCAmcmVzKTsNCj4gPiA+ID4gKwlp
ZiAoIWJ1cykNCj4gPiA+ID4gKwkJcmV0dXJuIC1FTk9NRU07DQo+ID4gPiA+ICsNCj4gPiA+ID4g
KyNpZmRlZiBDT05GSUdfR0VORVJJQ19NU0lfSVJRX0RPTUFJTg0KPiA+ID4gPiArCWJ1cy0+bXNp
ID0gY29udGFpbmVyX29mKCZwcC0+aXJxX2RvbWFpbiwgc3RydWN0DQo+IG1zaV9jb250cm9sbGVy
LA0KPiA+ID4gZG9tYWluKTsNCj4gPiA+ID4gKyNlbHNlDQo+ID4gPiA+ICAJZHdfcGNpZV9tc2lf
Y2hpcC5kZXYgPSBwcC0+ZGV2Ow0KPiA+ID4gPiAtCWR3X3BjaS5tc2lfY3RybCA9ICZkd19wY2ll
X21zaV9jaGlwOw0KPiA+ID4gPiArCWJ1cy0+bXNpID0gJmR3X3BjaWVfbXNpX2NoaXA7DQo+ID4g
PiA+ICAjZW5kaWYNCj4gPiA+ID4NCj4gPiA+ID4gLQlkd19wY2kubnJfY29udHJvbGxlcnMgPSAx
Ow0KPiA+ID4gPiAtCWR3X3BjaS5wcml2YXRlX2RhdGEgPSAodm9pZCAqKikmcHA7DQo+ID4gPiA+
ICsJcGNpX3NjYW5fY2hpbGRfYnVzKGJ1cyk7DQo+ID4gPiA+ICsJaWYgKHBwLT5vcHMtPnNjYW5f
YnVzKQ0KPiA+ID4gPiArCQlwcC0+b3BzLT5zY2FuX2J1cyhwcCk7DQo+ID4gPiA+ICsNCj4gPiA+
ID4gKyNpZmRlZiBDT05GSUdfQVJNDQo+ID4gPiA+ICsJLyogc3VwcG9ydCBvbGQgZHRicyB0aGF0
IGluY29ycmVjdGx5IGRlc2NyaWJlIElSUXMgKi8NCj4gPiA+ID4gKwlwY2lfZml4dXBfaXJxcyhw
Y2lfY29tbW9uX3N3aXp6bGUsDQo+IG9mX2lycV9wYXJzZV9hbmRfbWFwX3BjaSk7DQo+ID4gPiA+
ICsjZW5kaWYNCj4gPiA+ID4NCj4gPiA+ID4gLQlwY2lfY29tbW9uX2luaXRfZGV2KHBwLT5kZXYs
ICZkd19wY2kpOw0KPiA+ID4gPiArCXBjaV9hc3NpZ25fdW5hc3NpZ25lZF9idXNfcmVzb3VyY2Vz
KGJ1cyk7DQo+ID4gPiA+ICsJcGNpX2J1c19hZGRfZGV2aWNlcyhidXMpOw0KPiA+ID4gPg0KPiA+
ID4gPiAgCXJldHVybiAwOw0KPiA+ID4gPiAgfQ0KPiA+ID4gPiBAQCAtNTQ0LDEyICs1MjMsMTIg
QEAgc3RhdGljIGludCBkd19wY2llX3JkX290aGVyX2NvbmYoc3RydWN0DQo+ID4gPiBwY2llX3Bv
cnQgKnBwLCBzdHJ1Y3QgcGNpX2J1cyAqYnVzLA0KPiA+ID4gPg0KPiA+ID4gPiAgCWlmIChidXMt
PnBhcmVudC0+bnVtYmVyID09IHBwLT5yb290X2J1c19ucikgew0KPiA+ID4gPiAgCQl0eXBlID0g
UENJRV9BVFVfVFlQRV9DRkcwOw0KPiA+ID4gPiAtCQljcHVfYWRkciA9IHBwLT5jZmcwX21vZF9i
YXNlOw0KPiA+ID4gPiArCQljcHVfYWRkciA9IHBwLT5jZmcwX2Jhc2U7DQo+ID4gPiA+ICAJCWNm
Z19zaXplID0gcHAtPmNmZzBfc2l6ZTsNCj4gPiA+ID4gIAkJdmFfY2ZnX2Jhc2UgPSBwcC0+dmFf
Y2ZnMF9iYXNlOw0KPiA+ID4gPiAgCX0gZWxzZSB7DQo+ID4gPiA+ICAJCXR5cGUgPSBQQ0lFX0FU
VV9UWVBFX0NGRzE7DQo+ID4gPiA+IC0JCWNwdV9hZGRyID0gcHAtPmNmZzFfbW9kX2Jhc2U7DQo+
ID4gPiA+ICsJCWNwdV9hZGRyID0gcHAtPmNmZzFfYmFzZTsNCj4gPiA+ID4gIAkJY2ZnX3NpemUg
PSBwcC0+Y2ZnMV9zaXplOw0KPiA+ID4gPiAgCQl2YV9jZmdfYmFzZSA9IHBwLT52YV9jZmcxX2Jh
c2U7DQo+ID4gPiA+ICAJfQ0KPiA+ID4gPiBAQCAtNTU5LDcgKzUzOCw3IEBAIHN0YXRpYyBpbnQg
ZHdfcGNpZV9yZF9vdGhlcl9jb25mKHN0cnVjdA0KPiBwY2llX3BvcnQNCj4gPiA+ICpwcCwgc3Ry
dWN0IHBjaV9idXMgKmJ1cywNCj4gPiA+ID4gIAkJCQkgIGJ1c2RldiwgY2ZnX3NpemUpOw0KPiA+
ID4gPiAgCXJldCA9IGR3X3BjaWVfY2ZnX3JlYWQodmFfY2ZnX2Jhc2UgKyBhZGRyZXNzLCB3aGVy
ZSwgc2l6ZSwNCj4gdmFsKTsNCj4gPiA+ID4gIAlkd19wY2llX3Byb2dfb3V0Ym91bmRfYXR1KHBw
LCBQQ0lFX0FUVV9SRUdJT05fSU5ERVgwLA0KPiA+ID4gPiAtCQkJCSAgUENJRV9BVFVfVFlQRV9J
TywgcHAtPmlvX21vZF9iYXNlLA0KPiA+ID4gPiArCQkJCSAgUENJRV9BVFVfVFlQRV9JTywgcHAt
PmlvX2Jhc2UsDQo+ID4gPiA+ICAJCQkJICBwcC0+aW9fYnVzX2FkZHIsIHBwLT5pb19zaXplKTsN
Cj4gPiA+ID4NCj4gPiA+ID4gIAlyZXR1cm4gcmV0Ow0KPiA+ID4gPiBAQCAtNTc5LDEyICs1NTgs
MTIgQEAgc3RhdGljIGludCBkd19wY2llX3dyX290aGVyX2NvbmYoc3RydWN0DQo+ID4gPiBwY2ll
X3BvcnQgKnBwLCBzdHJ1Y3QgcGNpX2J1cyAqYnVzLA0KPiA+ID4gPg0KPiA+ID4gPiAgCWlmIChi
dXMtPnBhcmVudC0+bnVtYmVyID09IHBwLT5yb290X2J1c19ucikgew0KPiA+ID4gPiAgCQl0eXBl
ID0gUENJRV9BVFVfVFlQRV9DRkcwOw0KPiA+ID4gPiAtCQljcHVfYWRkciA9IHBwLT5jZmcwX21v
ZF9iYXNlOw0KPiA+ID4gPiArCQljcHVfYWRkciA9IHBwLT5jZmcwX2Jhc2U7DQo+ID4gPiA+ICAJ
CWNmZ19zaXplID0gcHAtPmNmZzBfc2l6ZTsNCj4gPiA+ID4gIAkJdmFfY2ZnX2Jhc2UgPSBwcC0+
dmFfY2ZnMF9iYXNlOw0KPiA+ID4gPiAgCX0gZWxzZSB7DQo+ID4gPiA+ICAJCXR5cGUgPSBQQ0lF
X0FUVV9UWVBFX0NGRzE7DQo+ID4gPiA+IC0JCWNwdV9hZGRyID0gcHAtPmNmZzFfbW9kX2Jhc2U7
DQo+ID4gPiA+ICsJCWNwdV9hZGRyID0gcHAtPmNmZzFfYmFzZTsNCj4gPiA+ID4gIAkJY2ZnX3Np
emUgPSBwcC0+Y2ZnMV9zaXplOw0KPiA+ID4gPiAgCQl2YV9jZmdfYmFzZSA9IHBwLT52YV9jZmcx
X2Jhc2U7DQo+ID4gPiA+ICAJfQ0KPiA+ID4gPiBAQCAtNTk0LDcgKzU3Myw3IEBAIHN0YXRpYyBp
bnQgZHdfcGNpZV93cl9vdGhlcl9jb25mKHN0cnVjdA0KPiBwY2llX3BvcnQNCj4gPiA+ICpwcCwg
c3RydWN0IHBjaV9idXMgKmJ1cywNCj4gPiA+ID4gIAkJCQkgIGJ1c2RldiwgY2ZnX3NpemUpOw0K
PiA+ID4gPiAgCXJldCA9IGR3X3BjaWVfY2ZnX3dyaXRlKHZhX2NmZ19iYXNlICsgYWRkcmVzcywg
d2hlcmUsIHNpemUsDQo+IHZhbCk7DQo+ID4gPiA+ICAJZHdfcGNpZV9wcm9nX291dGJvdW5kX2F0
dShwcCwgUENJRV9BVFVfUkVHSU9OX0lOREVYMCwNCj4gPiA+ID4gLQkJCQkgIFBDSUVfQVRVX1RZ
UEVfSU8sIHBwLT5pb19tb2RfYmFzZSwNCj4gPiA+ID4gKwkJCQkgIFBDSUVfQVRVX1RZUEVfSU8s
IHBwLT5pb19iYXNlLA0KPiA+ID4gPiAgCQkJCSAgcHAtPmlvX2J1c19hZGRyLCBwcC0+aW9fc2l6
ZSk7DQo+ID4gPiA+DQo+ID4gPiA+ICAJcmV0dXJuIHJldDsNCj4gPiA+ID4gQEAgLTYyNiw3ICs2
MDUsNyBAQCBzdGF0aWMgaW50IGR3X3BjaWVfdmFsaWRfY29uZmlnKHN0cnVjdA0KPiBwY2llX3Bv
cnQNCj4gPiA+ICpwcCwNCj4gPiA+ID4gIHN0YXRpYyBpbnQgZHdfcGNpZV9yZF9jb25mKHN0cnVj
dCBwY2lfYnVzICpidXMsIHUzMiBkZXZmbiwgaW50DQo+IHdoZXJlLA0KPiA+ID4gPiAgCQkJaW50
IHNpemUsIHUzMiAqdmFsKQ0KPiA+ID4gPiAgew0KPiA+ID4gPiAtCXN0cnVjdCBwY2llX3BvcnQg
KnBwID0gc3lzX3RvX3BjaWUoYnVzLT5zeXNkYXRhKTsNCj4gPiA+ID4gKwlzdHJ1Y3QgcGNpZV9w
b3J0ICpwcCA9IGJ1cy0+c3lzZGF0YTsNCj4gPiA+ID4gIAlpbnQgcmV0Ow0KPiA+ID4gPg0KPiA+
ID4gPiAgCWlmIChkd19wY2llX3ZhbGlkX2NvbmZpZyhwcCwgYnVzLCBQQ0lfU0xPVChkZXZmbikp
ID09IDApIHsNCj4gPiA+ID4gQEAgLTY1MCw3ICs2MjksNyBAQCBzdGF0aWMgaW50IGR3X3BjaWVf
cmRfY29uZihzdHJ1Y3QgcGNpX2J1cw0KPiAqYnVzLA0KPiA+ID4gdTMyIGRldmZuLCBpbnQgd2hl
cmUsDQo+ID4gPiA+ICBzdGF0aWMgaW50IGR3X3BjaWVfd3JfY29uZihzdHJ1Y3QgcGNpX2J1cyAq
YnVzLCB1MzIgZGV2Zm4sDQo+ID4gPiA+ICAJCQlpbnQgd2hlcmUsIGludCBzaXplLCB1MzIgdmFs
KQ0KPiA+ID4gPiAgew0KPiA+ID4gPiAtCXN0cnVjdCBwY2llX3BvcnQgKnBwID0gc3lzX3RvX3Bj
aWUoYnVzLT5zeXNkYXRhKTsNCj4gPiA+ID4gKwlzdHJ1Y3QgcGNpZV9wb3J0ICpwcCA9IGJ1cy0+
c3lzZGF0YTsNCj4gPiA+ID4gIAlpbnQgcmV0Ow0KPiA+ID4gPg0KPiA+ID4gPiAgCWlmIChkd19w
Y2llX3ZhbGlkX2NvbmZpZyhwcCwgYnVzLCBQQ0lfU0xPVChkZXZmbikpID09IDApDQo+ID4gPiA+
IEBAIC02NzQsNjIgKzY1Myw2IEBAIHN0YXRpYyBzdHJ1Y3QgcGNpX29wcyBkd19wY2llX29wcyA9
IHsNCj4gPiA+ID4gIAkud3JpdGUgPSBkd19wY2llX3dyX2NvbmYsDQo+ID4gPiA+ICB9Ow0KPiA+
ID4gPg0KPiA+ID4gPiAtc3RhdGljIGludCBkd19wY2llX3NldHVwKGludCBuciwgc3RydWN0IHBj
aV9zeXNfZGF0YSAqc3lzKQ0KPiA+ID4gPiAtew0KPiA+ID4gPiAtCXN0cnVjdCBwY2llX3BvcnQg
KnBwOw0KPiA+ID4gPiAtDQo+ID4gPiA+IC0JcHAgPSBzeXNfdG9fcGNpZShzeXMpOw0KPiA+ID4g
PiAtDQo+ID4gPiA+IC0JaWYgKGdsb2JhbF9pb19vZmZzZXQgPCBTWl8xTSAmJiBwcC0+aW9fc2l6
ZSA+IDApIHsNCj4gPiA+ID4gLQkJc3lzLT5pb19vZmZzZXQgPSBnbG9iYWxfaW9fb2Zmc2V0IC0g
cHAtPmlvX2J1c19hZGRyOw0KPiA+ID4gPiAtCQlwY2lfaW9yZW1hcF9pbyhnbG9iYWxfaW9fb2Zm
c2V0LCBwcC0+aW9fYmFzZSk7DQo+ID4gPiA+IC0JCWdsb2JhbF9pb19vZmZzZXQgKz0gU1pfNjRL
Ow0KPiA+ID4gPiAtCQlwY2lfYWRkX3Jlc291cmNlX29mZnNldCgmc3lzLT5yZXNvdXJjZXMsICZw
cC0+aW8sDQo+ID4gPiA+IC0JCQkJCXN5cy0+aW9fb2Zmc2V0KTsNCj4gPiA+ID4gLQl9DQo+ID4g
PiA+IC0NCj4gPiA+ID4gLQlzeXMtPm1lbV9vZmZzZXQgPSBwcC0+bWVtLnN0YXJ0IC0gcHAtPm1l
bV9idXNfYWRkcjsNCj4gPiA+ID4gLQlwY2lfYWRkX3Jlc291cmNlX29mZnNldCgmc3lzLT5yZXNv
dXJjZXMsICZwcC0+bWVtLCBzeXMtDQo+ID4gPiA+bWVtX29mZnNldCk7DQo+ID4gPiA+IC0JcGNp
X2FkZF9yZXNvdXJjZSgmc3lzLT5yZXNvdXJjZXMsICZwcC0+YnVzbik7DQo+ID4gPiA+IC0NCj4g
PiA+ID4gLQlyZXR1cm4gMTsNCj4gPiA+ID4gLX0NCj4gPiA+ID4gLQ0KPiA+ID4gPiAtc3RhdGlj
IHN0cnVjdCBwY2lfYnVzICpkd19wY2llX3NjYW5fYnVzKGludCBuciwgc3RydWN0DQo+IHBjaV9z
eXNfZGF0YQ0KPiA+ID4gKnN5cykNCj4gPiA+ID4gLXsNCj4gPiA+ID4gLQlzdHJ1Y3QgcGNpX2J1
cyAqYnVzOw0KPiA+ID4gPiAtCXN0cnVjdCBwY2llX3BvcnQgKnBwID0gc3lzX3RvX3BjaWUoc3lz
KTsNCj4gPiA+ID4gLQ0KPiA+ID4gPiAtCXBwLT5yb290X2J1c19uciA9IHN5cy0+YnVzbnI7DQo+
ID4gPiA+IC0JYnVzID0gcGNpX3NjYW5fcm9vdF9idXMocHAtPmRldiwgc3lzLT5idXNuciwNCj4g
PiA+ID4gLQkJCQkgICZkd19wY2llX29wcywgc3lzLCAmc3lzLT5yZXNvdXJjZXMpOw0KPiA+ID4g
PiAtCWlmICghYnVzKQ0KPiA+ID4gPiAtCQlyZXR1cm4gTlVMTDsNCj4gPiA+ID4gLQ0KPiA+ID4g
PiAtCWlmIChidXMgJiYgcHAtPm9wcy0+c2Nhbl9idXMpDQo+ID4gPiA+IC0JCXBwLT5vcHMtPnNj
YW5fYnVzKHBwKTsNCj4gPiA+ID4gLQ0KPiA+ID4gPiAtCXJldHVybiBidXM7DQo+ID4gPiA+IC19
DQo+ID4gPiA+IC0NCj4gPiA+ID4gLXN0YXRpYyBpbnQgZHdfcGNpZV9tYXBfaXJxKGNvbnN0IHN0
cnVjdCBwY2lfZGV2ICpkZXYsIHU4IHNsb3QsDQo+IHU4DQo+ID4gPiBwaW4pDQo+ID4gPiA+IC17
DQo+ID4gPiA+IC0Jc3RydWN0IHBjaWVfcG9ydCAqcHAgPSBzeXNfdG9fcGNpZShkZXYtPmJ1cy0+
c3lzZGF0YSk7DQo+ID4gPiA+IC0JaW50IGlycTsNCj4gPiA+ID4gLQ0KPiA+ID4gPiAtCWlycSA9
IG9mX2lycV9wYXJzZV9hbmRfbWFwX3BjaShkZXYsIHNsb3QsIHBpbik7DQo+ID4gPiA+IC0JaWYg
KCFpcnEpDQo+ID4gPiA+IC0JCWlycSA9IHBwLT5pcnE7DQo+ID4gPiA+IC0NCj4gPiA+ID4gLQly
ZXR1cm4gaXJxOw0KPiA+ID4gPiAtfQ0KPiA+ID4gPiAtDQo+ID4gPiA+IC1zdGF0aWMgc3RydWN0
IGh3X3BjaSBkd19wY2kgPSB7DQo+ID4gPiA+IC0JLnNldHVwCQk9IGR3X3BjaWVfc2V0dXAsDQo+
ID4gPiA+IC0JLnNjYW4JCT0gZHdfcGNpZV9zY2FuX2J1cywNCj4gPiA+ID4gLQkubWFwX2lycQk9
IGR3X3BjaWVfbWFwX2lycSwNCj4gPiA+ID4gLX07DQo+ID4gPiA+IC0NCj4gPiA+ID4gIHZvaWQg
ZHdfcGNpZV9zZXR1cF9yYyhzdHJ1Y3QgcGNpZV9wb3J0ICpwcCkNCj4gPiA+ID4gIHsNCj4gPiA+
ID4gIAl1MzIgdmFsOw0KPiA+ID4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9wY2kvaG9zdC9wY2ll
LWRlc2lnbndhcmUuaA0KPiA+ID4gYi9kcml2ZXJzL3BjaS9ob3N0L3BjaWUtZGVzaWdud2FyZS5o
DQo+ID4gPiA+IGluZGV4IGQwYmJkMjcuLjI2NGM5NjkgMTAwNjQ0DQo+ID4gPiA+IC0tLSBhL2Ry
aXZlcnMvcGNpL2hvc3QvcGNpZS1kZXNpZ253YXJlLmgNCj4gPiA+ID4gKysrIGIvZHJpdmVycy9w
Y2kvaG9zdC9wY2llLWRlc2lnbndhcmUuaA0KPiA+ID4gPiBAQCAtMjcsMjUgKzI3LDIxIEBAIHN0
cnVjdCBwY2llX3BvcnQgew0KPiA+ID4gPiAgCXU4CQkJcm9vdF9idXNfbnI7DQo+ID4gPiA+ICAJ
dm9pZCBfX2lvbWVtCQkqZGJpX2Jhc2U7DQo+ID4gPiA+ICAJdTY0CQkJY2ZnMF9iYXNlOw0KPiA+
ID4gPiAtCXU2NAkJCWNmZzBfbW9kX2Jhc2U7DQo+ID4gPiA+ICAJdm9pZCBfX2lvbWVtCQkqdmFf
Y2ZnMF9iYXNlOw0KPiA+ID4gPiAgCXUzMgkJCWNmZzBfc2l6ZTsNCj4gPiA+ID4gIAl1NjQJCQlj
ZmcxX2Jhc2U7DQo+ID4gPiA+IC0JdTY0CQkJY2ZnMV9tb2RfYmFzZTsNCj4gPiA+ID4gIAl2b2lk
IF9faW9tZW0JCSp2YV9jZmcxX2Jhc2U7DQo+ID4gPiA+ICAJdTMyCQkJY2ZnMV9zaXplOw0KPiA+
ID4gPiAtCXU2NAkJCWlvX2Jhc2U7DQo+ID4gPiA+IC0JdTY0CQkJaW9fbW9kX2Jhc2U7DQo+ID4g
PiA+ICsJcmVzb3VyY2Vfc2l6ZV90CQlpb19iYXNlOw0KPiA+ID4gPiAgCXBoeXNfYWRkcl90CQlp
b19idXNfYWRkcjsNCj4gPiA+ID4gIAl1MzIJCQlpb19zaXplOw0KPiA+ID4gPiAgCXU2NAkJCW1l
bV9iYXNlOw0KPiA+ID4gPiAtCXU2NAkJCW1lbV9tb2RfYmFzZTsNCj4gPiA+ID4gIAlwaHlzX2Fk
ZHJfdAkJbWVtX2J1c19hZGRyOw0KPiA+ID4gPiAgCXUzMgkJCW1lbV9zaXplOw0KPiA+ID4gPiAt
CXN0cnVjdCByZXNvdXJjZQkJY2ZnOw0KPiA+ID4gPiAtCXN0cnVjdCByZXNvdXJjZQkJaW87DQo+
ID4gPiA+IC0Jc3RydWN0IHJlc291cmNlCQltZW07DQo+ID4gPiA+IC0Jc3RydWN0IHJlc291cmNl
CQlidXNuOw0KPiA+ID4gPiArCXN0cnVjdCByZXNvdXJjZQkJKmNmZzsNCj4gPiA+ID4gKwlzdHJ1
Y3QgcmVzb3VyY2UJCSppbzsNCj4gPiA+ID4gKwlzdHJ1Y3QgcmVzb3VyY2UJCSptZW07DQo+ID4g
PiA+ICsJc3RydWN0IHJlc291cmNlCQkqYnVzbjsNCj4gPiA+ID4gIAlpbnQJCQlpcnE7DQo+ID4g
PiA+ICAJdTMyCQkJbGFuZXM7DQo+ID4gPiA+ICAJc3RydWN0IHBjaWVfaG9zdF9vcHMJKm9wczsN
Cj4gPiA+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvcGNpL2hvc3QvcGNpZS1zcGVhcjEzeHguYw0K
PiA+ID4gYi9kcml2ZXJzL3BjaS9ob3N0L3BjaWUtc3BlYXIxM3h4LmMNCj4gPiA+ID4gaW5kZXgg
YzQ5ZmJkYy4uMDNlYjIwNCAxMDA2NDQNCj4gPiA+ID4gLS0tIGEvZHJpdmVycy9wY2kvaG9zdC9w
Y2llLXNwZWFyMTN4eC5jDQo+ID4gPiA+ICsrKyBiL2RyaXZlcnMvcGNpL2hvc3QvcGNpZS1zcGVh
cjEzeHguYw0KPiA+ID4gPiBAQCAtMjg2LDcgKzI4Niw3IEBAIHN0YXRpYyBpbnQgc3BlYXIxM3h4
X2FkZF9wY2llX3BvcnQoc3RydWN0DQo+ID4gPiBwY2llX3BvcnQgKnBwLA0KPiA+ID4gPiAgCQly
ZXR1cm4gcmV0Ow0KPiA+ID4gPiAgCX0NCj4gPiA+ID4NCj4gPiA+ID4gLQlwcC0+cm9vdF9idXNf
bnIgPSAtMTsNCj4gPiA+ID4gKwlwcC0+cm9vdF9idXNfbnIgPSAwOw0KPiA+ID4gPiAgCXBwLT5v
cHMgPSAmc3BlYXIxM3h4X3BjaWVfaG9zdF9vcHM7DQo+ID4gPiA+DQo+ID4gPiA+ICAJcmV0ID0g
ZHdfcGNpZV9ob3N0X2luaXQocHApOw0KPiA+ID4NCj4gPiA+IC0tDQo+ID4gPiBQZW5ndXRyb25p
eCBlLksuICAgICAgICAgICAgIHwgTHVjYXMgU3RhY2ggICAgICAgICAgICAgICAgIHwNCj4gPiA+
IEluZHVzdHJpYWwgTGludXggU29sdXRpb25zICAgfCBodHRwOi8vd3d3LnBlbmd1dHJvbml4LmRl
LyAgfA0KPiA+DQo+IA0KPiAtLQ0KPiBQZW5ndXRyb25peCBlLksuICAgICAgICAgICAgIHwgTHVj
YXMgU3RhY2ggICAgICAgICAgICAgICAgIHwNCj4gSW5kdXN0cmlhbCBMaW51eCBTb2x1dGlvbnMg
ICB8IGh0dHA6Ly93d3cucGVuZ3V0cm9uaXguZGUvICB8DQoNCg==

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

* [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-19 16:34           ` Gabriele Paoloni
  0 siblings, 0 replies; 53+ messages in thread
From: Gabriele Paoloni @ 2015-08-19 16:34 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Lucas

First of all many thanks for the quick reply, really appreciated

> -----Original Message-----
> From: Lucas Stach [mailto:l.stach at pengutronix.de]
> Sent: Wednesday, August 19, 2015 4:37 PM
> To: Gabriele Paoloni
> Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1 at gmail.com; Pratyush Anand;
> Arnd Bergmann; linux at arm.linux.org.uk; thomas.petazzoni at free-
> electrons.com; lorenzo.pieralisi at arm.com; james.morse at arm.com;
> Liviu.Dudau at arm.com; jason at lakedaemon.net; robh at kernel.org; linux-
> pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> 
> Hi Gab,
> 
> Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele Paoloni:
> > Hi Lucas
> >
> > I have rewritten the patch to take into account multiple controllers.
> >
> > As you can see now there is a static var in dw_pcie_host_init() that
> tracks
> > the bus numbers used.
> 
> This is wrong. The DT specifies the valid bus number range. You can not
> just assign the next free bus number to the root bus.

I think this is what is being done in
http://lxr.free-electrons.com/source/arch/arm/kernel/bios32.c#L495
and currently designware assigns the root bus number in
http://lxr.free-electrons.com/source/drivers/pci/host/pcie-designware.c#L730


In general I agree with you but if you look at all the current drivers 
based on designware none of them define the "bus-range" dtb property.
Therefore doing as you say would break the current driver when we have
multiple controllers...am I right?

If that is the case in order to fix this in the way you say I would need
to assign "bus-range" for all the PCIe drivers with multiple controllers:
in this case I would split the default range evenly (that is, if we have 
two controllers I would define "bus-range"  0-127 and 128-255)

If you think this solution is ok I can go for it. My only doubt was about
touching other vendors DTBs....


> 
> It is perfectly valid to have a bus range of 0x00-0x10 assigned to one
> instance and 0x50-0xff to the next instance. Additional with PCIe
> hotplug you may not use the full range of the bus numbers on one
> instance at the first scan, but only later populate more buses when
> more
> bridges are added to the tree.
> 
> > Drivers that do not specify the bus range in the DTB set pp-
> >root_bus_nr = DW_ROOT_NR_UNDEFINED.
> > Designware will check if the flag is set and will use the automatic
> bus range
> > assignment.
> 
> No, please lets get rid of this assignment altogether. The glue drivers
> have no business in assigning the bus range. Please remove the
> pp->root_bus_nr assignment from all the glue drivers.
> 
> "bus range" is a generic DW PCIe property, so just parse the root bus
> number from the DT, it is handled the same way for all the DW based
> PCIe
> drivers. The bindings specifies that if the bus range property is
> missing the range is 0x00-0xff, so you can default to 0 as the root bus
> number in that case.
> 
> Also I would think this conversion warrants a patch on its own and
> should not be mixed in the ARM64 support patch.
> 
> Regards,
> Lucas
> 
> > Instead if the driver assigns pp->root_bus_nr according to the dtb,
> designwware
> > will use the value passed in by the driver.
> > Below the relevant section:
> >
> >
> > +	static int root_bus_nr = 0;
> > ...
> > +	mutex_lock(&root_bus_nr_mux);
> > +
> > +	if (pp->root_bus_nr != DW_ROOT_NR_UNDEFINED)
> > +		root_bus_nr = pp->root_bus_nr;
> > +
> > +	bus = pci_create_root_bus(pp->dev, root_bus_nr, &dw_pcie_ops,
> > +			      pp, &res);
> > +	if (!bus) {
> > +		mutex_unlock(&root_bus_nr_mux);
> > +		return -ENOMEM;
> > +	}
> > +
> > +	root_bus_nr += bus->busn_res.end + 1;
> > +	mutex_unlock(&root_bus_nr_mux);
> >
> > Please let me know what you think...
> >
> > Many Thanks
> >
> > Gab
> > ----------
> >
> > From: gabriele paoloni <gabriele.paoloni@huawei.com>
> >
> > This patch tries to unify ARM32 and ARM64 PCIe in designware driver.
> Delete
> > function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct
> hw_pci,
> > move related operations to dw_pcie_host_init.
> > Also set pp->root_bus_nr = DW_ROOT_NR_UNDEFINED in all the drivers
> that
> > are based on designware to flag that the drivers do not read the bus
> > ranges from DT.
> > This patch also adds handling of multiple PCI domains in designware.
> > if the PCI host bridge driver does not specify a root bus number, in
> case
> > of multiple domains, designware will automatillay set the next domain
> root
> > bus number to the last bus number used in the last domain + 1.
> >
> > This patch also try to use of_pci_get_host_bridge_resources for ARM32
> and
> > ARM64 according to the suggestion for Gabriele[1]
> >
> > This patch is based on Gabriele's patch about of_pci_range fix[2]
> >
> > Finally this patch reverts commit f4c55c5a3f7f "PCI: designware:
> > Program ATU with untranslated address". This was discussed in [3]
> >
> > I have compiled the driver with multi_v7_defconfig. However, I don't
> have
> > ARM32 PCIe related board to do test. It will be appreciated if
> someone could
> > help to test it.
> >
> > Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> >
> > [1] http://www.spinics.net/lists/linux-pci/msg42194.html
> > [2] https://patchwork.ozlabs.org/patch/495018/
> > [3] http://www.spinics.net/lists/arm-kernel/msg436779.html
> > ---
> >  drivers/pci/host/pci-dra7xx.c      |  15 +--
> >  drivers/pci/host/pci-exynos.c      |   2 +-
> >  drivers/pci/host/pci-imx6.c        |   2 +-
> >  drivers/pci/host/pci-keystone-dw.c |   2 +-
> >  drivers/pci/host/pci-keystone.c    |   2 +-
> >  drivers/pci/host/pci-layerscape.c  |   2 +-
> >  drivers/pci/host/pcie-designware.c | 247 ++++++++++++++-------------
> ----------
> >  drivers/pci/host/pcie-designware.h |  15 +--
> >  drivers/pci/host/pcie-spear13xx.c  |   2 +-
> >  9 files changed, 110 insertions(+), 179 deletions(-)
> >
> > diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-
> dra7xx.c
> > index 5678b57..8d598fb 100644
> > --- a/drivers/pci/host/pci-dra7xx.c
> > +++ b/drivers/pci/host/pci-dra7xx.c
> > @@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct
> pcie_port *pp)
> >  {
> >  	dw_pcie_setup_rc(pp);
> >
> > -	if (pp->io_mod_base)
> > -		pp->io_mod_base &= CPU_TO_BUS_ADDR;
> > +	if (pp->io_base)
> > +		pp->io_base &= CPU_TO_BUS_ADDR;
> >
> > -	if (pp->mem_mod_base)
> > -		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
> > +	if (pp->mem_base)
> > +		pp->mem_base &= CPU_TO_BUS_ADDR;
> >
> > -	if (pp->cfg0_mod_base) {
> > -		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
> > -		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
> > +	if (pp->cfg0_base) {
> > +		pp->cfg0_base &= CPU_TO_BUS_ADDR;
> > +		pp->cfg1_base &= CPU_TO_BUS_ADDR;
> >  	}
> >
> >  	dra7xx_pcie_establish_link(pp);
> > @@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct
> dra7xx_pcie *dra7xx,
> >
> >  	pp = &dra7xx->pp;
> >  	pp->dev = dev;
> > +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
> >  	pp->ops = &dra7xx_pcie_host_ops;
> >
> >  	pp->irq = platform_get_irq(pdev, 1);
> > diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-
> exynos.c
> > index f9f468d..ed03a8f 100644
> > --- a/drivers/pci/host/pci-exynos.c
> > +++ b/drivers/pci/host/pci-exynos.c
> > @@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct
> pcie_port *pp,
> >  		}
> >  	}
> >
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
> >  	pp->ops = &exynos_pcie_host_ops;
> >
> >  	ret = dw_pcie_host_init(pp);
> > diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-
> imx6.c
> > index 233a196..0efac85 100644
> > --- a/drivers/pci/host/pci-imx6.c
> > +++ b/drivers/pci/host/pci-imx6.c
> > @@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct
> pcie_port *pp,
> >  		}
> >  	}
> >
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
> >  	pp->ops = &imx6_pcie_host_ops;
> >
> >  	ret = dw_pcie_host_init(pp);
> > diff --git a/drivers/pci/host/pci-keystone-dw.c
> b/drivers/pci/host/pci-keystone-dw.c
> > index f34892e..b1e4135 100644
> > --- a/drivers/pci/host/pci-keystone-dw.c
> > +++ b/drivers/pci/host/pci-keystone-dw.c
> > @@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void
> __iomem *reg_virt)
> >  void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
> >  {
> >  	struct pcie_port *pp = &ks_pcie->pp;
> > -	u32 start = pp->mem.start, end = pp->mem.end;
> > +	u32 start = pp->mem->start, end = pp->mem->end;
> >  	int i, tr_size;
> >
> >  	/* Disable BARs for inbound access */
> > diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-
> keystone.c
> > index 734da58..b522956 100644
> > --- a/drivers/pci/host/pci-keystone.c
> > +++ b/drivers/pci/host/pci-keystone.c
> > @@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct
> keystone_pcie *ks_pcie,
> >  			return ret;
> >  	}
> >
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
> >  	pp->ops = &keystone_pcie_host_ops;
> >  	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
> >  	if (ret) {
> > diff --git a/drivers/pci/host/pci-layerscape.c
> b/drivers/pci/host/pci-layerscape.c
> > index b2328ea1..dd92ffa 100644
> > --- a/drivers/pci/host/pci-layerscape.c
> > +++ b/drivers/pci/host/pci-layerscape.c
> > @@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
> >  	pp = &pcie->pp;
> >  	pp->dev = pcie->dev;
> >  	pp->dbi_base = pcie->dbi;
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
> >  	pp->ops = &ls_pcie_host_ops;
> >
> >  	ret = dw_pcie_host_init(pp);
> > diff --git a/drivers/pci/host/pcie-designware.c
> b/drivers/pci/host/pcie-designware.c
> > index 5307b35..bd2606b 100644
> > --- a/drivers/pci/host/pcie-designware.c
> > +++ b/drivers/pci/host/pcie-designware.c
> > @@ -11,6 +11,7 @@
> >   * published by the Free Software Foundation.
> >   */
> >
> > +#include <linux/hardirq.h>
> >  #include <linux/irq.h>
> >  #include <linux/irqdomain.h>
> >  #include <linux/kernel.h>
> > @@ -69,16 +70,9 @@
> >  #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
> >  #define PCIE_ATU_UPPER_TARGET		0x91C
> >
> > -static struct hw_pci dw_pci;
> > +static struct pci_ops dw_pcie_ops;
> >
> > -static unsigned long global_io_offset;
> > -
> > -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
> > -{
> > -	BUG_ON(!sys->private_data);
> > -
> > -	return sys->private_data;
> > -}
> > +DEFINE_MUTEX(root_bus_nr_mux);
> >
> >  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32
> *val)
> >  {
> > @@ -255,7 +249,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port
> *pp, int irq)
> >  static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
> >  {
> >  	int irq, pos0, i;
> > -	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
> > +	struct pcie_port *pp = desc->dev->bus->sysdata;
> >
> >  	pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
> >  				       order_base_2(no_irqs));
> > @@ -298,7 +292,7 @@ static int dw_msi_setup_irq(struct msi_controller
> *chip, struct pci_dev *pdev,
> >  {
> >  	int irq, pos;
> >  	struct msi_msg msg;
> > -	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
> > +	struct pcie_port *pp = pdev->bus->sysdata;
> >
> >  	if (desc->msi_attrib.is_msix)
> >  		return -EINVAL;
> > @@ -327,7 +321,7 @@ static void dw_msi_teardown_irq(struct
> msi_controller *chip, unsigned int irq)
> >  {
> >  	struct irq_data *data = irq_get_irq_data(irq);
> >  	struct msi_desc *msi = irq_data_get_msi(data);
> > -	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
> > +	struct pcie_port *pp = msi->dev->bus->sysdata;
> >
> >  	clear_irq_range(pp, irq, 1, data->hwirq);
> >  }
> > @@ -359,22 +353,17 @@ static const struct irq_domain_ops
> msi_domain_ops = {
> >  	.map = dw_pcie_msi_map,
> >  };
> >
> > -int dw_pcie_host_init(struct pcie_port *pp)
> > +int __init dw_pcie_host_init(struct pcie_port *pp)
> >  {
> >  	struct device_node *np = pp->dev->of_node;
> >  	struct platform_device *pdev = to_platform_device(pp->dev);
> > -	struct of_pci_range range;
> > -	struct of_pci_range_parser parser;
> > +	struct pci_bus *bus;
> >  	struct resource *cfg_res;
> > -	u32 val, na, ns;
> > -	const __be32 *addrp;
> > -	int i, index, ret;
> > -
> > -	/* Find the address cell size and the number of cells in order to
> get
> > -	 * the untranslated address.
> > -	 */
> > -	of_property_read_u32(np, "#address-cells", &na);
> > -	ns = of_n_size_cells(np);
> > +	LIST_HEAD(res);
> > +	u32 val;
> > +	int i, ret;
> > +	struct resource_entry *win;
> > +	static int root_bus_nr = 0;
> >
> >  	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> "config");
> >  	if (cfg_res) {
> > @@ -382,85 +371,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
> >  		pp->cfg1_size = resource_size(cfg_res)/2;
> >  		pp->cfg0_base = cfg_res->start;
> >  		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
> > -
> > -		/* Find the untranslated configuration space address */
> > -		index = of_property_match_string(np, "reg-names", "config");
> > -		addrp = of_get_address(np, index, NULL, NULL);
> > -		pp->cfg0_mod_base = of_read_number(addrp, ns);
> > -		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
> >  	} else {
> >  		dev_err(pp->dev, "missing *config* reg space\n");
> >  	}
> >
> > -	if (of_pci_range_parser_init(&parser, np)) {
> > -		dev_err(pp->dev, "missing ranges property\n");
> > -		return -EINVAL;
> > -	}
> > +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp-
> >io_base);
> > +	if (ret)
> > +		return ret;
> >
> >  	/* Get the I/O and memory ranges from DT */
> > -	for_each_of_pci_range(&parser, &range) {
> > -		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
> > -
> > -		if (restype == IORESOURCE_IO) {
> > -			of_pci_range_to_resource(&range, np, &pp->io);
> > -			pp->io.name = "I/O";
> > -			pp->io.start = max_t(resource_size_t,
> > -					     PCIBIOS_MIN_IO,
> > -					     range.pci_addr + global_io_offset);
> > -			pp->io.end = min_t(resource_size_t,
> > -					   IO_SPACE_LIMIT,
> > -					   range.pci_addr + range.size
> > -					   + global_io_offset - 1);
> > -			pp->io_size = resource_size(&pp->io);
> > -			pp->io_bus_addr = range.pci_addr;
> > -			pp->io_base = range.cpu_addr;
> > -
> > -			/* Find the untranslated IO space address */
> > -			pp->io_mod_base = range.cpu_addr;
> > -		}
> > -		if (restype == IORESOURCE_MEM) {
> > -			of_pci_range_to_resource(&range, np, &pp->mem);
> > -			pp->mem.name = "MEM";
> > -			pp->mem_size = resource_size(&pp->mem);
> > -			pp->mem_bus_addr = range.pci_addr;
> > -
> > -			/* Find the untranslated MEM space address */
> > -			pp->mem_mod_base = range.cpu_addr;
> > -		}
> > -		if (restype == 0) {
> > -			of_pci_range_to_resource(&range, np, &pp->cfg);
> > -			pp->cfg0_size = resource_size(&pp->cfg)/2;
> > -			pp->cfg1_size = resource_size(&pp->cfg)/2;
> > -			pp->cfg0_base = pp->cfg.start;
> > -			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
> > -
> > -			/* Find the untranslated configuration space address
> */
> > -			pp->cfg0_mod_base = range.cpu_addr;
> > -			pp->cfg1_mod_base = pp->cfg0_mod_base +
> > -					    pp->cfg0_size;
> > +	resource_list_for_each_entry(win, &res) {
> > +		switch (resource_type(win->res)) {
> > +		case IORESOURCE_IO:
> > +			pp->io = win->res;
> > +			pp->io->name = "I/O";
> > +			pp->io_size = resource_size(pp->io);
> > +			pp->io_bus_addr = pp->io->start - win->offset;
> > +			ret = pci_remap_iospace(pp->io, pp->io_base);
> > +			if (ret) {
> > +				dev_warn(pp->dev, "error %d: failed to map
> resource %pR\n",
> > +					 ret, pp->io);
> > +				continue;
> > +			}
> > +			break;
> > +		case IORESOURCE_MEM:
> > +			pp->mem = win->res;
> > +			pp->mem->name = "MEM";
> > +			pp->mem_size = resource_size(pp->mem);
> > +			pp->mem_bus_addr = pp->mem->start - win->offset;
> > +			break;
> > +		case 0:
> > +			pp->cfg = win->res;
> > +			pp->cfg0_size = resource_size(pp->cfg)/2;
> > +			pp->cfg1_size = resource_size(pp->cfg)/2;
> > +			pp->cfg0_base = pp->cfg->start;
> > +			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
> > +			break;
> > +		case IORESOURCE_BUS:
> > +			pp->busn = win->res;
> > +			break;
> > +		default:
> > +			continue;
> >  		}
> >  	}
> >
> > -	ret = of_pci_parse_bus_range(np, &pp->busn);
> > -	if (ret < 0) {
> > -		pp->busn.name = np->name;
> > -		pp->busn.start = 0;
> > -		pp->busn.end = 0xff;
> > -		pp->busn.flags = IORESOURCE_BUS;
> > -		dev_dbg(pp->dev, "failed to parse bus-range property: %d,
> using default %pR\n",
> > -			ret, &pp->busn);
> > -	}
> > -
> >  	if (!pp->dbi_base) {
> > -		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
> > -					resource_size(&pp->cfg));
> > +		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
> > +					resource_size(pp->cfg));
> >  		if (!pp->dbi_base) {
> >  			dev_err(pp->dev, "error with ioremap\n");
> >  			return -ENOMEM;
> >  		}
> >  	}
> >
> > -	pp->mem_base = pp->mem.start;
> > +	pp->mem_base = pp->mem->start;
> >
> >  	if (!pp->va_cfg0_base) {
> >  		pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
> > @@ -509,7 +473,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
> >
> >  	if (!pp->ops->rd_other_conf)
> >  		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
> > -					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
> > +					  PCIE_ATU_TYPE_MEM, pp->mem_base,
> >  					  pp->mem_bus_addr, pp->mem_size);
> >
> >  	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
> > @@ -521,15 +485,40 @@ int dw_pcie_host_init(struct pcie_port *pp)
> >  	val |= PORT_LOGIC_SPEED_CHANGE;
> >  	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
> >
> > -#ifdef CONFIG_PCI_MSI
> >  	dw_pcie_msi_chip.dev = pp->dev;
> > -	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> > +
> > +	mutex_lock(&root_bus_nr_mux);
> > +
> > +	if (pp->root_bus_nr != DW_ROOT_NR_UNDEFINED)
> > +		root_bus_nr = pp->root_bus_nr;
> > +
> > +	bus = pci_create_root_bus(pp->dev, root_bus_nr, &dw_pcie_ops,
> > +			      pp, &res);
> > +	if (!bus) {
> > +		mutex_unlock(&root_bus_nr_mux);
> > +		return -ENOMEM;
> > +	}
> > +
> > +	root_bus_nr += bus->busn_res.end + 1;
> > +	mutex_unlock(&root_bus_nr_mux);
> > +
> > +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> > +	bus->msi = container_of(&pp->irq_domain, struct msi_controller,
> domain);
> > +#else
> > +	bus->msi = &dw_pcie_msi_chip;
> >  #endif
> >
> > -	dw_pci.nr_controllers = 1;
> > -	dw_pci.private_data = (void **)&pp;
> > +	pci_scan_child_bus(bus);
> > +	if (pp->ops->scan_bus)
> > +		pp->ops->scan_bus(pp);
> > +
> > +#ifdef CONFIG_ARM
> > +	/* support old dtbs that incorrectly describe IRQs */
> > +	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
> > +#endif
> >
> > -	pci_common_init_dev(pp->dev, &dw_pci);
> > +	pci_assign_unassigned_bus_resources(bus);
> > +	pci_bus_add_devices(bus);
> >
> >  	return 0;
> >  }
> > @@ -548,12 +537,12 @@ static int dw_pcie_rd_other_conf(struct
> pcie_port *pp, struct pci_bus *bus,
> >
> >  	if (bus->parent->number == pp->root_bus_nr) {
> >  		type = PCIE_ATU_TYPE_CFG0;
> > -		cpu_addr = pp->cfg0_mod_base;
> > +		cpu_addr = pp->cfg0_base;
> >  		cfg_size = pp->cfg0_size;
> >  		va_cfg_base = pp->va_cfg0_base;
> >  	} else {
> >  		type = PCIE_ATU_TYPE_CFG1;
> > -		cpu_addr = pp->cfg1_mod_base;
> > +		cpu_addr = pp->cfg1_base;
> >  		cfg_size = pp->cfg1_size;
> >  		va_cfg_base = pp->va_cfg1_base;
> >  	}
> > @@ -563,7 +552,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port
> *pp, struct pci_bus *bus,
> >  				  busdev, cfg_size);
> >  	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val);
> >  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> > -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> > +				  PCIE_ATU_TYPE_IO, pp->io_base,
> >  				  pp->io_bus_addr, pp->io_size);
> >
> >  	return ret;
> > @@ -583,12 +572,12 @@ static int dw_pcie_wr_other_conf(struct
> pcie_port *pp, struct pci_bus *bus,
> >
> >  	if (bus->parent->number == pp->root_bus_nr) {
> >  		type = PCIE_ATU_TYPE_CFG0;
> > -		cpu_addr = pp->cfg0_mod_base;
> > +		cpu_addr = pp->cfg0_base;
> >  		cfg_size = pp->cfg0_size;
> >  		va_cfg_base = pp->va_cfg0_base;
> >  	} else {
> >  		type = PCIE_ATU_TYPE_CFG1;
> > -		cpu_addr = pp->cfg1_mod_base;
> > +		cpu_addr = pp->cfg1_base;
> >  		cfg_size = pp->cfg1_size;
> >  		va_cfg_base = pp->va_cfg1_base;
> >  	}
> > @@ -598,7 +587,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port
> *pp, struct pci_bus *bus,
> >  				  busdev, cfg_size);
> >  	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val);
> >  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> > -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> > +				  PCIE_ATU_TYPE_IO, pp->io_base,
> >  				  pp->io_bus_addr, pp->io_size);
> >
> >  	return ret;
> > @@ -630,7 +619,7 @@ static int dw_pcie_valid_config(struct pcie_port
> *pp,
> >  static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> >  			int size, u32 *val)
> >  {
> > -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> > +	struct pcie_port *pp = bus->sysdata;
> >  	int ret;
> >
> >  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
> > @@ -654,7 +643,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus,
> u32 devfn, int where,
> >  static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
> >  			int where, int size, u32 val)
> >  {
> > -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> > +	struct pcie_port *pp = bus->sysdata;
> >  	int ret;
> >
> >  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
> > @@ -678,62 +667,6 @@ static struct pci_ops dw_pcie_ops = {
> >  	.write = dw_pcie_wr_conf,
> >  };
> >
> > -static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
> > -{
> > -	struct pcie_port *pp;
> > -
> > -	pp = sys_to_pcie(sys);
> > -
> > -	if (global_io_offset < SZ_1M && pp->io_size > 0) {
> > -		sys->io_offset = global_io_offset - pp->io_bus_addr;
> > -		pci_ioremap_io(global_io_offset, pp->io_base);
> > -		global_io_offset += SZ_64K;
> > -		pci_add_resource_offset(&sys->resources, &pp->io,
> > -					sys->io_offset);
> > -	}
> > -
> > -	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
> > -	pci_add_resource_offset(&sys->resources, &pp->mem, sys-
> >mem_offset);
> > -	pci_add_resource(&sys->resources, &pp->busn);
> > -
> > -	return 1;
> > -}
> > -
> > -static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data
> *sys)
> > -{
> > -	struct pci_bus *bus;
> > -	struct pcie_port *pp = sys_to_pcie(sys);
> > -
> > -	pp->root_bus_nr = sys->busnr;
> > -	bus = pci_scan_root_bus(pp->dev, sys->busnr,
> > -				  &dw_pcie_ops, sys, &sys->resources);
> > -	if (!bus)
> > -		return NULL;
> > -
> > -	if (bus && pp->ops->scan_bus)
> > -		pp->ops->scan_bus(pp);
> > -
> > -	return bus;
> > -}
> > -
> > -static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8
> pin)
> > -{
> > -	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
> > -	int irq;
> > -
> > -	irq = of_irq_parse_and_map_pci(dev, slot, pin);
> > -	if (!irq)
> > -		irq = pp->irq;
> > -
> > -	return irq;
> > -}
> > -
> > -static struct hw_pci dw_pci = {
> > -	.setup		= dw_pcie_setup,
> > -	.scan		= dw_pcie_scan_bus,
> > -	.map_irq	= dw_pcie_map_irq,
> > -};
> > -
> >  void dw_pcie_setup_rc(struct pcie_port *pp)
> >  {
> >  	u32 val;
> > diff --git a/drivers/pci/host/pcie-designware.h
> b/drivers/pci/host/pcie-designware.h
> > index d0bbd27..0c2a7eb 100644
> > --- a/drivers/pci/host/pcie-designware.h
> > +++ b/drivers/pci/host/pcie-designware.h
> > @@ -21,31 +21,28 @@
> >   */
> >  #define MAX_MSI_IRQS			32
> >  #define MAX_MSI_CTRLS			(MAX_MSI_IRQS / 32)
> > +#define DW_ROOT_NR_UNDEFINED	-1
> >
> >  struct pcie_port {
> >  	struct device		*dev;
> >  	u8			root_bus_nr;
> >  	void __iomem		*dbi_base;
> >  	u64			cfg0_base;
> > -	u64			cfg0_mod_base;
> >  	void __iomem		*va_cfg0_base;
> >  	u32			cfg0_size;
> >  	u64			cfg1_base;
> > -	u64			cfg1_mod_base;
> >  	void __iomem		*va_cfg1_base;
> >  	u32			cfg1_size;
> > -	u64			io_base;
> > -	u64			io_mod_base;
> > +	resource_size_t		io_base;
> >  	phys_addr_t		io_bus_addr;
> >  	u32			io_size;
> >  	u64			mem_base;
> > -	u64			mem_mod_base;
> >  	phys_addr_t		mem_bus_addr;
> >  	u32			mem_size;
> > -	struct resource		cfg;
> > -	struct resource		io;
> > -	struct resource		mem;
> > -	struct resource		busn;
> > +	struct resource		*cfg;
> > +	struct resource		*io;
> > +	struct resource		*mem;
> > +	struct resource		*busn;
> >  	int			irq;
> >  	u32			lanes;
> >  	struct pcie_host_ops	*ops;
> > diff --git a/drivers/pci/host/pcie-spear13xx.c
> b/drivers/pci/host/pcie-spear13xx.c
> > index c49fbdc..b2c59b9 100644
> > --- a/drivers/pci/host/pcie-spear13xx.c
> > +++ b/drivers/pci/host/pcie-spear13xx.c
> > @@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct
> pcie_port *pp,
> >  		return ret;
> >  	}
> >
> > -	pp->root_bus_nr = -1;
> > +	pp->root_bus_nr = DW_ROOT_NR_UNDEFINED;
> >  	pp->ops = &spear13xx_pcie_host_ops;
> >
> >  	ret = dw_pcie_host_init(pp);
> > --
> > 1.9.1
> >
> >
> > > -----Original Message-----
> > > From: Lucas Stach [mailto:l.stach at pengutronix.de]
> > > Sent: Wednesday, August 19, 2015 1:54 PM
> > > To: Wangzhou (B)
> > > Cc: Bjorn Helgaas; jingoohan1 at gmail.com; Pratyush Anand; Arnd
> Bergmann;
> > > linux at arm.linux.org.uk; thomas.petazzoni at free-electrons.com;
> Gabriele
> > > Paoloni; lorenzo.pieralisi at arm.com; james.morse at arm.com;
> > > Liviu.Dudau at arm.com; jason at lakedaemon.net; robh at kernel.org; linux-
> > > pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> > > devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> > > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > >
> > > Am Montag, den 17.08.2015, 19:55 +0800 schrieb Zhou Wang:
> > > > This patch tries to unify ARM32 and ARM64 PCIe in designware
> driver.
> > > Delete
> > > > function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and
> struct
> > > hw_pci,
> > > > move related operations to dw_pcie_host_init.
> > > >
> > > > In past, we use:
> > > > pci_common_init_dev
> > > > 	-> pcibios_init_hw
> > > > 		-> hw->scan (dw_pcie_scan_bus)
> > > > to pass 0 to root_bus_nr in struct pcie_port. This patch set pp-
> > > >root_bus_nr = 0
> > > > in each PCIe host driver which is based on pcie-designware.
> > > >
> > > This is incorrect at least if there are 2 instances of DW PCIe host
> in
> > > the same SoC without using PCI domains. In that the case the bus
> range
> > > determines the range of valid bus numbers per instance and the
> first
> > > number is the root bus. Please look at the "bus-range" DT property
> in
> > > the DW PCIe bindings.
> > >
> > > Also we should finally remove this root-bus setup from the glue
> drivers
> > > altogether. It's something that entirely belongs into the DW core
> code.
> > >
> > > Regards,
> > > Lucas
> > >
> > > > This patch also try to use of_pci_get_host_bridge_resources for
> ARM32
> > > and ARM64
> > > > according to the suggestion for Gabriele[1]
> > > >
> > > > Finally this patch reverts commit f4c55c5a3f7f "PCI: designware:
> > > Program ATU
> > > > with untranslated address" based on 1/6 in this series. we delete
> > > *_mod_base in
> > > > pcie-designware. This was discussed in [2]
> > > >
> > > > I have compiled the driver with multi_v7_defconfig. However, I
> don't
> > > have
> > > > ARM32 PCIe related board to do test. It will be appreciated if
> > > someone could
> > > > help to test it.
> > > >
> > > > Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> > > > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > > > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> > > > Tested-By: James Morse <james.morse@arm.com>
> > > >
> > > > [1] http://www.spinics.net/lists/linux-pci/msg42194.html
> > > > [2] http://www.spinics.net/lists/arm-kernel/msg436779.html
> > > > ---
> > > >  drivers/pci/host/pci-dra7xx.c      |  15 +--
> > > >  drivers/pci/host/pci-exynos.c      |   2 +-
> > > >  drivers/pci/host/pci-imx6.c        |   2 +-
> > > >  drivers/pci/host/pci-keystone-dw.c |   2 +-
> > > >  drivers/pci/host/pci-keystone.c    |   2 +-
> > > >  drivers/pci/host/pci-layerscape.c  |   2 +-
> > > >  drivers/pci/host/pcie-designware.c | 229 ++++++++++++-----------
> ----
> > > ----------
> > > >  drivers/pci/host/pcie-designware.h |  14 +--
> > > >  drivers/pci/host/pcie-spear13xx.c  |   2 +-
> > > >  9 files changed, 95 insertions(+), 175 deletions(-)
> > > >
> > > > diff --git a/drivers/pci/host/pci-dra7xx.c
> b/drivers/pci/host/pci-
> > > dra7xx.c
> > > > index 18ae7ff..1268c69 100644
> > > > --- a/drivers/pci/host/pci-dra7xx.c
> > > > +++ b/drivers/pci/host/pci-dra7xx.c
> > > > @@ -141,15 +141,15 @@ static void dra7xx_pcie_host_init(struct
> > > pcie_port *pp)
> > > >  {
> > > >  	dw_pcie_setup_rc(pp);
> > > >
> > > > -	if (pp->io_mod_base)
> > > > -		pp->io_mod_base &= CPU_TO_BUS_ADDR;
> > > > +	if (pp->io_base)
> > > > +		pp->io_base &= CPU_TO_BUS_ADDR;
> > > >
> > > > -	if (pp->mem_mod_base)
> > > > -		pp->mem_mod_base &= CPU_TO_BUS_ADDR;
> > > > +	if (pp->mem_base)
> > > > +		pp->mem_base &= CPU_TO_BUS_ADDR;
> > > >
> > > > -	if (pp->cfg0_mod_base) {
> > > > -		pp->cfg0_mod_base &= CPU_TO_BUS_ADDR;
> > > > -		pp->cfg1_mod_base &= CPU_TO_BUS_ADDR;
> > > > +	if (pp->cfg0_base) {
> > > > +		pp->cfg0_base &= CPU_TO_BUS_ADDR;
> > > > +		pp->cfg1_base &= CPU_TO_BUS_ADDR;
> > > >  	}
> > > >
> > > >  	dra7xx_pcie_establish_link(pp);
> > > > @@ -288,6 +288,7 @@ static int __init dra7xx_add_pcie_port(struct
> > > dra7xx_pcie *dra7xx,
> > > >
> > > >  	pp = &dra7xx->pp;
> > > >  	pp->dev = dev;
> > > > +	pp->root_bus_nr = 0;
> > > >  	pp->ops = &dra7xx_pcie_host_ops;
> > > >
> > > >  	pp->irq = platform_get_irq(pdev, 1);
> > > > diff --git a/drivers/pci/host/pci-exynos.c
> b/drivers/pci/host/pci-
> > > exynos.c
> > > > index f9f468d..9771bb0 100644
> > > > --- a/drivers/pci/host/pci-exynos.c
> > > > +++ b/drivers/pci/host/pci-exynos.c
> > > > @@ -530,7 +530,7 @@ static int __init exynos_add_pcie_port(struct
> > > pcie_port *pp,
> > > >  		}
> > > >  	}
> > > >
> > > > -	pp->root_bus_nr = -1;
> > > > +	pp->root_bus_nr = 0;
> > > >  	pp->ops = &exynos_pcie_host_ops;
> > > >
> > > >  	ret = dw_pcie_host_init(pp);
> > > > diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-
> > > imx6.c
> > > > index 233a196..bec256c 100644
> > > > --- a/drivers/pci/host/pci-imx6.c
> > > > +++ b/drivers/pci/host/pci-imx6.c
> > > > @@ -551,7 +551,7 @@ static int __init imx6_add_pcie_port(struct
> > > pcie_port *pp,
> > > >  		}
> > > >  	}
> > > >
> > > > -	pp->root_bus_nr = -1;
> > > > +	pp->root_bus_nr = 0;
> > > >  	pp->ops = &imx6_pcie_host_ops;
> > > >
> > > >  	ret = dw_pcie_host_init(pp);
> > > > diff --git a/drivers/pci/host/pci-keystone-dw.c
> > > b/drivers/pci/host/pci-keystone-dw.c
> > > > index f34892e..b1e4135 100644
> > > > --- a/drivers/pci/host/pci-keystone-dw.c
> > > > +++ b/drivers/pci/host/pci-keystone-dw.c
> > > > @@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void
> > > __iomem *reg_virt)
> > > >  void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
> > > >  {
> > > >  	struct pcie_port *pp = &ks_pcie->pp;
> > > > -	u32 start = pp->mem.start, end = pp->mem.end;
> > > > +	u32 start = pp->mem->start, end = pp->mem->end;
> > > >  	int i, tr_size;
> > > >
> > > >  	/* Disable BARs for inbound access */
> > > > diff --git a/drivers/pci/host/pci-keystone.c
> b/drivers/pci/host/pci-
> > > keystone.c
> > > > index 734da58..8113832 100644
> > > > --- a/drivers/pci/host/pci-keystone.c
> > > > +++ b/drivers/pci/host/pci-keystone.c
> > > > @@ -309,7 +309,7 @@ static int __init ks_add_pcie_port(struct
> > > keystone_pcie *ks_pcie,
> > > >  			return ret;
> > > >  	}
> > > >
> > > > -	pp->root_bus_nr = -1;
> > > > +	pp->root_bus_nr = 0;
> > > >  	pp->ops = &keystone_pcie_host_ops;
> > > >  	ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
> > > >  	if (ret) {
> > > > diff --git a/drivers/pci/host/pci-layerscape.c
> > > b/drivers/pci/host/pci-layerscape.c
> > > > index b2328ea1..79ff08c 100644
> > > > --- a/drivers/pci/host/pci-layerscape.c
> > > > +++ b/drivers/pci/host/pci-layerscape.c
> > > > @@ -106,7 +106,7 @@ static int ls_add_pcie_port(struct ls_pcie
> *pcie)
> > > >  	pp = &pcie->pp;
> > > >  	pp->dev = pcie->dev;
> > > >  	pp->dbi_base = pcie->dbi;
> > > > -	pp->root_bus_nr = -1;
> > > > +	pp->root_bus_nr = 0;
> > > >  	pp->ops = &ls_pcie_host_ops;
> > > >
> > > >  	ret = dw_pcie_host_init(pp);
> > > > diff --git a/drivers/pci/host/pcie-designware.c
> > > b/drivers/pci/host/pcie-designware.c
> > > > index c5d407c..e71a88e 100644
> > > > --- a/drivers/pci/host/pcie-designware.c
> > > > +++ b/drivers/pci/host/pcie-designware.c
> > > > @@ -11,6 +11,7 @@
> > > >   * published by the Free Software Foundation.
> > > >   */
> > > >
> > > > +#include <linux/hardirq.h>
> > > >  #include <linux/irq.h>
> > > >  #include <linux/irqdomain.h>
> > > >  #include <linux/kernel.h>
> > > > @@ -69,16 +70,7 @@
> > > >  #define PCIE_ATU_FUNC(x)		(((x) & 0x7) << 16)
> > > >  #define PCIE_ATU_UPPER_TARGET		0x91C
> > > >
> > > > -static struct hw_pci dw_pci;
> > > > -
> > > > -static unsigned long global_io_offset;
> > > > -
> > > > -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data
> *sys)
> > > > -{
> > > > -	BUG_ON(!sys->private_data);
> > > > -
> > > > -	return sys->private_data;
> > > > -}
> > > > +static struct pci_ops dw_pcie_ops;
> > > >
> > > >  int dw_pcie_cfg_read(void __iomem *addr, int where, int size,
> u32
> > > *val)
> > > >  {
> > > > @@ -255,7 +247,7 @@ static void dw_pcie_msi_set_irq(struct
> pcie_port
> > > *pp, int irq)
> > > >  static int assign_irq(int no_irqs, struct msi_desc *desc, int
> *pos)
> > > >  {
> > > >  	int irq, pos0, i;
> > > > -	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
> > > > +	struct pcie_port *pp = desc->dev->bus->sysdata;
> > > >
> > > >  	pos0 = bitmap_find_free_region(pp->msi_irq_in_use,
> MAX_MSI_IRQS,
> > > >  				       order_base_2(no_irqs));
> > > > @@ -298,7 +290,7 @@ static int dw_msi_setup_irq(struct
> msi_controller
> > > *chip, struct pci_dev *pdev,
> > > >  {
> > > >  	int irq, pos;
> > > >  	struct msi_msg msg;
> > > > -	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
> > > > +	struct pcie_port *pp = pdev->bus->sysdata;
> > > >
> > > >  	if (desc->msi_attrib.is_msix)
> > > >  		return -EINVAL;
> > > > @@ -327,7 +319,7 @@ static void dw_msi_teardown_irq(struct
> > > msi_controller *chip, unsigned int irq)
> > > >  {
> > > >  	struct irq_data *data = irq_get_irq_data(irq);
> > > >  	struct msi_desc *msi = irq_data_get_msi(data);
> > > > -	struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
> > > > +	struct pcie_port *pp = msi->dev->bus->sysdata;
> > > >
> > > >  	clear_irq_range(pp, irq, 1, data->hwirq);
> > > >  }
> > > > @@ -363,14 +355,12 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > > >  {
> > > >  	struct device_node *np = pp->dev->of_node;
> > > >  	struct platform_device *pdev = to_platform_device(pp->dev);
> > > > -	struct of_pci_range range;
> > > > -	struct of_pci_range_parser parser;
> > > > +	struct pci_bus *bus;
> > > >  	struct resource *cfg_res;
> > > > -	u32 val, ns;
> > > > -	const __be32 *addrp;
> > > > -	int i, index, ret;
> > > > -
> > > > -	ns = of_n_size_cells(np);
> > > > +	LIST_HEAD(res);
> > > > +	u32 val;
> > > > +	int i, ret;
> > > > +	struct resource_entry *win;
> > > >
> > > >  	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> > > "config");
> > > >  	if (cfg_res) {
> > > > @@ -378,85 +368,60 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > > >  		pp->cfg1_size = resource_size(cfg_res)/2;
> > > >  		pp->cfg0_base = cfg_res->start;
> > > >  		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
> > > > -
> > > > -		/* Find the untranslated configuration space address
> */
> > > > -		index = of_property_match_string(np, "reg-names",
> "config");
> > > > -		addrp = of_get_address(np, index, NULL, NULL);
> > > > -		pp->cfg0_mod_base = of_read_number(addrp, ns);
> > > > -		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
> > > >  	} else {
> > > >  		dev_err(pp->dev, "missing *config* reg space\n");
> > > >  	}
> > > >
> > > > -	if (of_pci_range_parser_init(&parser, np)) {
> > > > -		dev_err(pp->dev, "missing ranges property\n");
> > > > -		return -EINVAL;
> > > > -	}
> > > > +	ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res,
> &pp-
> > > >io_base);
> > > > +	if (ret)
> > > > +		return ret;
> > > >
> > > >  	/* Get the I/O and memory ranges from DT */
> > > > -	for_each_of_pci_range(&parser, &range) {
> > > > -		unsigned long restype = range.flags &
> IORESOURCE_TYPE_BITS;
> > > > -
> > > > -		if (restype == IORESOURCE_IO) {
> > > > -			of_pci_range_to_resource(&range, np, &pp->io);
> > > > -			pp->io.name = "I/O";
> > > > -			pp->io.start = max_t(resource_size_t,
> > > > -					     PCIBIOS_MIN_IO,
> > > > -					     range.pci_addr +
> global_io_offset);
> > > > -			pp->io.end = min_t(resource_size_t,
> > > > -					   IO_SPACE_LIMIT,
> > > > -					   range.pci_addr + range.size
> > > > -					   + global_io_offset - 1);
> > > > -			pp->io_size = resource_size(&pp->io);
> > > > -			pp->io_bus_addr = range.pci_addr;
> > > > -			pp->io_base = range.cpu_addr;
> > > > -
> > > > -			/* Find the untranslated IO space address */
> > > > -			pp->io_mod_base = range.cpu_addr;
> > > > -		}
> > > > -		if (restype == IORESOURCE_MEM) {
> > > > -			of_pci_range_to_resource(&range, np, &pp->mem);
> > > > -			pp->mem.name = "MEM";
> > > > -			pp->mem_size = resource_size(&pp->mem);
> > > > -			pp->mem_bus_addr = range.pci_addr;
> > > > -
> > > > -			/* Find the untranslated MEM space address */
> > > > -			pp->mem_mod_base = range.cpu_addr;
> > > > -		}
> > > > -		if (restype == 0) {
> > > > -			of_pci_range_to_resource(&range, np, &pp->cfg);
> > > > -			pp->cfg0_size = resource_size(&pp->cfg)/2;
> > > > -			pp->cfg1_size = resource_size(&pp->cfg)/2;
> > > > -			pp->cfg0_base = pp->cfg.start;
> > > > -			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
> > > > -
> > > > -			/* Find the untranslated configuration space
> address
> > > */
> > > > -			pp->cfg0_mod_base = range.cpu_addr;
> > > > -			pp->cfg1_mod_base = pp->cfg0_mod_base +
> > > > -					    pp->cfg0_size;
> > > > +	resource_list_for_each_entry(win, &res) {
> > > > +		switch (resource_type(win->res)) {
> > > > +		case IORESOURCE_IO:
> > > > +			pp->io = win->res;
> > > > +			pp->io->name = "I/O";
> > > > +			pp->io_size = resource_size(pp->io);
> > > > +			pp->io_bus_addr = pp->io->start - win->offset;
> > > > +			ret = pci_remap_iospace(pp->io, pp->io_base);
> > > > +			if (ret) {
> > > > +				dev_warn(pp->dev, "error %d: failed to
> map
> > > resource %pR\n",
> > > > +					 ret, pp->io);
> > > > +				continue;
> > > > +			}
> > > > +			break;
> > > > +		case IORESOURCE_MEM:
> > > > +			pp->mem = win->res;
> > > > +			pp->mem->name = "MEM";
> > > > +			pp->mem_size = resource_size(pp->mem);
> > > > +			pp->mem_bus_addr = pp->mem->start - win->offset;
> > > > +			break;
> > > > +		case 0:
> > > > +			pp->cfg = win->res;
> > > > +			pp->cfg0_size = resource_size(pp->cfg)/2;
> > > > +			pp->cfg1_size = resource_size(pp->cfg)/2;
> > > > +			pp->cfg0_base = pp->cfg->start;
> > > > +			pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
> > > > +			break;
> > > > +		case IORESOURCE_BUS:
> > > > +			pp->busn = win->res;
> > > > +			break;
> > > > +		default:
> > > > +			continue;
> > > >  		}
> > > >  	}
> > > >
> > > > -	ret = of_pci_parse_bus_range(np, &pp->busn);
> > > > -	if (ret < 0) {
> > > > -		pp->busn.name = np->name;
> > > > -		pp->busn.start = 0;
> > > > -		pp->busn.end = 0xff;
> > > > -		pp->busn.flags = IORESOURCE_BUS;
> > > > -		dev_dbg(pp->dev, "failed to parse bus-range
> property: %d,
> > > using default %pR\n",
> > > > -			ret, &pp->busn);
> > > > -	}
> > > > -
> > > >  	if (!pp->dbi_base) {
> > > > -		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
> > > > -					resource_size(&pp->cfg));
> > > > +		pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
> > > > +					resource_size(pp->cfg));
> > > >  		if (!pp->dbi_base) {
> > > >  			dev_err(pp->dev, "error with ioremap\n");
> > > >  			return -ENOMEM;
> > > >  		}
> > > >  	}
> > > >
> > > > -	pp->mem_base = pp->mem.start;
> > > > +	pp->mem_base = pp->mem->start;
> > > >
> > > >  	if (!pp->va_cfg0_base) {
> > > >  		pp->va_cfg0_base = devm_ioremap(pp->dev, pp-
> >cfg0_base,
> > > > @@ -505,7 +470,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > > >
> > > >  	if (!pp->ops->rd_other_conf)
> > > >  		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
> > > > -					  PCIE_ATU_TYPE_MEM, pp-
> >mem_mod_base,
> > > > +					  PCIE_ATU_TYPE_MEM, pp->mem_base,
> > > >  					  pp->mem_bus_addr, pp->mem_size);
> > > >
> > > >  	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
> > > > @@ -517,15 +482,29 @@ int dw_pcie_host_init(struct pcie_port *pp)
> > > >  	val |= PORT_LOGIC_SPEED_CHANGE;
> > > >  	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,
> val);
> > > >
> > > > -#ifdef CONFIG_PCI_MSI
> > > > +	bus = pci_create_root_bus(pp->dev, pp->root_bus_nr,
> &dw_pcie_ops,
> > > > +				  pp, &res);
> > > > +	if (!bus)
> > > > +		return -ENOMEM;
> > > > +
> > > > +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> > > > +	bus->msi = container_of(&pp->irq_domain, struct
> msi_controller,
> > > domain);
> > > > +#else
> > > >  	dw_pcie_msi_chip.dev = pp->dev;
> > > > -	dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> > > > +	bus->msi = &dw_pcie_msi_chip;
> > > >  #endif
> > > >
> > > > -	dw_pci.nr_controllers = 1;
> > > > -	dw_pci.private_data = (void **)&pp;
> > > > +	pci_scan_child_bus(bus);
> > > > +	if (pp->ops->scan_bus)
> > > > +		pp->ops->scan_bus(pp);
> > > > +
> > > > +#ifdef CONFIG_ARM
> > > > +	/* support old dtbs that incorrectly describe IRQs */
> > > > +	pci_fixup_irqs(pci_common_swizzle,
> of_irq_parse_and_map_pci);
> > > > +#endif
> > > >
> > > > -	pci_common_init_dev(pp->dev, &dw_pci);
> > > > +	pci_assign_unassigned_bus_resources(bus);
> > > > +	pci_bus_add_devices(bus);
> > > >
> > > >  	return 0;
> > > >  }
> > > > @@ -544,12 +523,12 @@ static int dw_pcie_rd_other_conf(struct
> > > pcie_port *pp, struct pci_bus *bus,
> > > >
> > > >  	if (bus->parent->number == pp->root_bus_nr) {
> > > >  		type = PCIE_ATU_TYPE_CFG0;
> > > > -		cpu_addr = pp->cfg0_mod_base;
> > > > +		cpu_addr = pp->cfg0_base;
> > > >  		cfg_size = pp->cfg0_size;
> > > >  		va_cfg_base = pp->va_cfg0_base;
> > > >  	} else {
> > > >  		type = PCIE_ATU_TYPE_CFG1;
> > > > -		cpu_addr = pp->cfg1_mod_base;
> > > > +		cpu_addr = pp->cfg1_base;
> > > >  		cfg_size = pp->cfg1_size;
> > > >  		va_cfg_base = pp->va_cfg1_base;
> > > >  	}
> > > > @@ -559,7 +538,7 @@ static int dw_pcie_rd_other_conf(struct
> pcie_port
> > > *pp, struct pci_bus *bus,
> > > >  				  busdev, cfg_size);
> > > >  	ret = dw_pcie_cfg_read(va_cfg_base + address, where, size,
> val);
> > > >  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> > > > -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> > > > +				  PCIE_ATU_TYPE_IO, pp->io_base,
> > > >  				  pp->io_bus_addr, pp->io_size);
> > > >
> > > >  	return ret;
> > > > @@ -579,12 +558,12 @@ static int dw_pcie_wr_other_conf(struct
> > > pcie_port *pp, struct pci_bus *bus,
> > > >
> > > >  	if (bus->parent->number == pp->root_bus_nr) {
> > > >  		type = PCIE_ATU_TYPE_CFG0;
> > > > -		cpu_addr = pp->cfg0_mod_base;
> > > > +		cpu_addr = pp->cfg0_base;
> > > >  		cfg_size = pp->cfg0_size;
> > > >  		va_cfg_base = pp->va_cfg0_base;
> > > >  	} else {
> > > >  		type = PCIE_ATU_TYPE_CFG1;
> > > > -		cpu_addr = pp->cfg1_mod_base;
> > > > +		cpu_addr = pp->cfg1_base;
> > > >  		cfg_size = pp->cfg1_size;
> > > >  		va_cfg_base = pp->va_cfg1_base;
> > > >  	}
> > > > @@ -594,7 +573,7 @@ static int dw_pcie_wr_other_conf(struct
> pcie_port
> > > *pp, struct pci_bus *bus,
> > > >  				  busdev, cfg_size);
> > > >  	ret = dw_pcie_cfg_write(va_cfg_base + address, where, size,
> val);
> > > >  	dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> > > > -				  PCIE_ATU_TYPE_IO, pp->io_mod_base,
> > > > +				  PCIE_ATU_TYPE_IO, pp->io_base,
> > > >  				  pp->io_bus_addr, pp->io_size);
> > > >
> > > >  	return ret;
> > > > @@ -626,7 +605,7 @@ static int dw_pcie_valid_config(struct
> pcie_port
> > > *pp,
> > > >  static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int
> where,
> > > >  			int size, u32 *val)
> > > >  {
> > > > -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> > > > +	struct pcie_port *pp = bus->sysdata;
> > > >  	int ret;
> > > >
> > > >  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
> > > > @@ -650,7 +629,7 @@ static int dw_pcie_rd_conf(struct pci_bus
> *bus,
> > > u32 devfn, int where,
> > > >  static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
> > > >  			int where, int size, u32 val)
> > > >  {
> > > > -	struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> > > > +	struct pcie_port *pp = bus->sysdata;
> > > >  	int ret;
> > > >
> > > >  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
> > > > @@ -674,62 +653,6 @@ static struct pci_ops dw_pcie_ops = {
> > > >  	.write = dw_pcie_wr_conf,
> > > >  };
> > > >
> > > > -static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
> > > > -{
> > > > -	struct pcie_port *pp;
> > > > -
> > > > -	pp = sys_to_pcie(sys);
> > > > -
> > > > -	if (global_io_offset < SZ_1M && pp->io_size > 0) {
> > > > -		sys->io_offset = global_io_offset - pp->io_bus_addr;
> > > > -		pci_ioremap_io(global_io_offset, pp->io_base);
> > > > -		global_io_offset += SZ_64K;
> > > > -		pci_add_resource_offset(&sys->resources, &pp->io,
> > > > -					sys->io_offset);
> > > > -	}
> > > > -
> > > > -	sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
> > > > -	pci_add_resource_offset(&sys->resources, &pp->mem, sys-
> > > >mem_offset);
> > > > -	pci_add_resource(&sys->resources, &pp->busn);
> > > > -
> > > > -	return 1;
> > > > -}
> > > > -
> > > > -static struct pci_bus *dw_pcie_scan_bus(int nr, struct
> pci_sys_data
> > > *sys)
> > > > -{
> > > > -	struct pci_bus *bus;
> > > > -	struct pcie_port *pp = sys_to_pcie(sys);
> > > > -
> > > > -	pp->root_bus_nr = sys->busnr;
> > > > -	bus = pci_scan_root_bus(pp->dev, sys->busnr,
> > > > -				  &dw_pcie_ops, sys, &sys->resources);
> > > > -	if (!bus)
> > > > -		return NULL;
> > > > -
> > > > -	if (bus && pp->ops->scan_bus)
> > > > -		pp->ops->scan_bus(pp);
> > > > -
> > > > -	return bus;
> > > > -}
> > > > -
> > > > -static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot,
> u8
> > > pin)
> > > > -{
> > > > -	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
> > > > -	int irq;
> > > > -
> > > > -	irq = of_irq_parse_and_map_pci(dev, slot, pin);
> > > > -	if (!irq)
> > > > -		irq = pp->irq;
> > > > -
> > > > -	return irq;
> > > > -}
> > > > -
> > > > -static struct hw_pci dw_pci = {
> > > > -	.setup		= dw_pcie_setup,
> > > > -	.scan		= dw_pcie_scan_bus,
> > > > -	.map_irq	= dw_pcie_map_irq,
> > > > -};
> > > > -
> > > >  void dw_pcie_setup_rc(struct pcie_port *pp)
> > > >  {
> > > >  	u32 val;
> > > > diff --git a/drivers/pci/host/pcie-designware.h
> > > b/drivers/pci/host/pcie-designware.h
> > > > index d0bbd27..264c969 100644
> > > > --- a/drivers/pci/host/pcie-designware.h
> > > > +++ b/drivers/pci/host/pcie-designware.h
> > > > @@ -27,25 +27,21 @@ struct pcie_port {
> > > >  	u8			root_bus_nr;
> > > >  	void __iomem		*dbi_base;
> > > >  	u64			cfg0_base;
> > > > -	u64			cfg0_mod_base;
> > > >  	void __iomem		*va_cfg0_base;
> > > >  	u32			cfg0_size;
> > > >  	u64			cfg1_base;
> > > > -	u64			cfg1_mod_base;
> > > >  	void __iomem		*va_cfg1_base;
> > > >  	u32			cfg1_size;
> > > > -	u64			io_base;
> > > > -	u64			io_mod_base;
> > > > +	resource_size_t		io_base;
> > > >  	phys_addr_t		io_bus_addr;
> > > >  	u32			io_size;
> > > >  	u64			mem_base;
> > > > -	u64			mem_mod_base;
> > > >  	phys_addr_t		mem_bus_addr;
> > > >  	u32			mem_size;
> > > > -	struct resource		cfg;
> > > > -	struct resource		io;
> > > > -	struct resource		mem;
> > > > -	struct resource		busn;
> > > > +	struct resource		*cfg;
> > > > +	struct resource		*io;
> > > > +	struct resource		*mem;
> > > > +	struct resource		*busn;
> > > >  	int			irq;
> > > >  	u32			lanes;
> > > >  	struct pcie_host_ops	*ops;
> > > > diff --git a/drivers/pci/host/pcie-spear13xx.c
> > > b/drivers/pci/host/pcie-spear13xx.c
> > > > index c49fbdc..03eb204 100644
> > > > --- a/drivers/pci/host/pcie-spear13xx.c
> > > > +++ b/drivers/pci/host/pcie-spear13xx.c
> > > > @@ -286,7 +286,7 @@ static int spear13xx_add_pcie_port(struct
> > > pcie_port *pp,
> > > >  		return ret;
> > > >  	}
> > > >
> > > > -	pp->root_bus_nr = -1;
> > > > +	pp->root_bus_nr = 0;
> > > >  	pp->ops = &spear13xx_pcie_host_ops;
> > > >
> > > >  	ret = dw_pcie_host_init(pp);
> > >
> > > --
> > > Pengutronix e.K.             | Lucas Stach                 |
> > > Industrial Linux Solutions   | http://www.pengutronix.de/  |
> >
> 
> --
> Pengutronix e.K.             | Lucas Stach                 |
> Industrial Linux Solutions   | http://www.pengutronix.de/  |

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

* Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
  2015-08-19 16:34           ` Gabriele Paoloni
  (?)
@ 2015-08-20  8:27             ` Lucas Stach
  -1 siblings, 0 replies; 53+ messages in thread
From: Lucas Stach @ 2015-08-20  8:27 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Wangzhou (B),
	Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, lorenzo.pieralisi, james.morse, Liviu.Dudau,
	jason, robh, linux-pci, linux-arm-kernel, devicetree,
	Yuanzhichang, Zhudacai, zhangjukuo, qiuzhe

Hi Gab,

Am Mittwoch, den 19.08.2015, 16:34 +0000 schrieb Gabriele Paoloni:
> Hi Lucas
> 
> First of all many thanks for the quick reply, really appreciated
> 
> > -----Original Message-----
> > From: Lucas Stach [mailto:l.stach@pengutronix.de]
> > Sent: Wednesday, August 19, 2015 4:37 PM
> > To: Gabriele Paoloni
> > Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com; Pratyush Anand;
> > Arnd Bergmann; linux@arm.linux.org.uk; thomas.petazzoni@free-
> > electrons.com; lorenzo.pieralisi@arm.com; james.morse@arm.com;
> > Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org; linux-
> > pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> > devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > 
> > Hi Gab,
> > 
> > Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele Paoloni:
> > > Hi Lucas
> > >
> > > I have rewritten the patch to take into account multiple controllers.
> > >
> > > As you can see now there is a static var in dw_pcie_host_init() that
> > tracks
> > > the bus numbers used.
> > 
> > This is wrong. The DT specifies the valid bus number range. You can not
> > just assign the next free bus number to the root bus.
> 
> I think this is what is being done in
> http://lxr.free-electrons.com/source/arch/arm/kernel/bios32.c#L495
> and currently designware assigns the root bus number in
> http://lxr.free-electrons.com/source/drivers/pci/host/pcie-designware.c#L730
> 
You found the right spot. It works a bit different than I remember, but
is less broken than your current code. :)

It actually assigns the next instance a root bus number behind the
current instances bus range. Please note the difference to your code
which assigns the next free bus number, which may still lay within the
current instances bus range.

> 
> In general I agree with you but if you look at all the current drivers 
> based on designware none of them define the "bus-range" dtb property.
> Therefore doing as you say would break the current driver when we have
> multiple controllers...am I right?
> 
The current _code_ works fine for multiple controllers. It's just that
you must define the bus range property in the DTB if you want to enable
multiple instances of one controller and support a kernel without PCI
domains support. As all current implementations have only a single
instance of the controller per SoC, or depend on PCI domain support,
it's totally fine for them to not define the bus ranges property, as
it's an optional property and it is well defined how things behave if it
is absent. We absolutely need to keep that specified behavior.

> If that is the case in order to fix this in the way you say I would need
> to assign "bus-range" for all the PCIe drivers with multiple controllers:
> in this case I would split the default range evenly (that is, if we have 
> two controllers I would define "bus-range"  0-127 and 128-255)
> 
> If you think this solution is ok I can go for it. My only doubt was about
> touching other vendors DTBs....
> 
You don't need to touch any of the current DTBs, as they are fine with
the default bus range behavior. You need to keep the specified behavior
of the bus range property with the new code.

Regards,
Lucas
> 
> > 
> > It is perfectly valid to have a bus range of 0x00-0x10 assigned to one
> > instance and 0x50-0xff to the next instance. Additional with PCIe
> > hotplug you may not use the full range of the bus numbers on one
> > instance at the first scan, but only later populate more buses when
> > more
> > bridges are added to the tree.
> > 
> > > Drivers that do not specify the bus range in the DTB set pp-
> > >root_bus_nr = DW_ROOT_NR_UNDEFINED.
> > > Designware will check if the flag is set and will use the automatic
> > bus range
> > > assignment.
> > 
> > No, please lets get rid of this assignment altogether. The glue drivers
> > have no business in assigning the bus range. Please remove the
> > pp->root_bus_nr assignment from all the glue drivers.
> > 
> > "bus range" is a generic DW PCIe property, so just parse the root bus
> > number from the DT, it is handled the same way for all the DW based
> > PCIe
> > drivers. The bindings specifies that if the bus range property is
> > missing the range is 0x00-0xff, so you can default to 0 as the root bus
> > number in that case.
> > 
> > Also I would think this conversion warrants a patch on its own and
> > should not be mixed in the ARM64 support patch.
> > 
> > Regards,
> > Lucas
> > 

-- 
Pengutronix e.K.             | Lucas Stach                 |
Industrial Linux Solutions   | http://www.pengutronix.de/  |

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

* Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-20  8:27             ` Lucas Stach
  0 siblings, 0 replies; 53+ messages in thread
From: Lucas Stach @ 2015-08-20  8:27 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Wangzhou (B),
	Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, lorenzo.pieralisi, james.morse, Liviu.Dudau,
	jason, robh, linux-pci, linux-arm-kernel, devicetree,
	Yuanzhichang, Zhudacai, zhangjukuo, qiuzhenfa, liudongdong (C),
	qiujiang, xuwei (O), Liguozhu (Kenneth)

Hi Gab,

Am Mittwoch, den 19.08.2015, 16:34 +0000 schrieb Gabriele Paoloni:
> Hi Lucas
> 
> First of all many thanks for the quick reply, really appreciated
> 
> > -----Original Message-----
> > From: Lucas Stach [mailto:l.stach@pengutronix.de]
> > Sent: Wednesday, August 19, 2015 4:37 PM
> > To: Gabriele Paoloni
> > Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com; Pratyush Anand;
> > Arnd Bergmann; linux@arm.linux.org.uk; thomas.petazzoni@free-
> > electrons.com; lorenzo.pieralisi@arm.com; james.morse@arm.com;
> > Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org; linux-
> > pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> > devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > 
> > Hi Gab,
> > 
> > Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele Paoloni:
> > > Hi Lucas
> > >
> > > I have rewritten the patch to take into account multiple controllers.
> > >
> > > As you can see now there is a static var in dw_pcie_host_init() that
> > tracks
> > > the bus numbers used.
> > 
> > This is wrong. The DT specifies the valid bus number range. You can not
> > just assign the next free bus number to the root bus.
> 
> I think this is what is being done in
> http://lxr.free-electrons.com/source/arch/arm/kernel/bios32.c#L495
> and currently designware assigns the root bus number in
> http://lxr.free-electrons.com/source/drivers/pci/host/pcie-designware.c#L730
> 
You found the right spot. It works a bit different than I remember, but
is less broken than your current code. :)

It actually assigns the next instance a root bus number behind the
current instances bus range. Please note the difference to your code
which assigns the next free bus number, which may still lay within the
current instances bus range.

> 
> In general I agree with you but if you look at all the current drivers 
> based on designware none of them define the "bus-range" dtb property.
> Therefore doing as you say would break the current driver when we have
> multiple controllers...am I right?
> 
The current _code_ works fine for multiple controllers. It's just that
you must define the bus range property in the DTB if you want to enable
multiple instances of one controller and support a kernel without PCI
domains support. As all current implementations have only a single
instance of the controller per SoC, or depend on PCI domain support,
it's totally fine for them to not define the bus ranges property, as
it's an optional property and it is well defined how things behave if it
is absent. We absolutely need to keep that specified behavior.

> If that is the case in order to fix this in the way you say I would need
> to assign "bus-range" for all the PCIe drivers with multiple controllers:
> in this case I would split the default range evenly (that is, if we have 
> two controllers I would define "bus-range"  0-127 and 128-255)
> 
> If you think this solution is ok I can go for it. My only doubt was about
> touching other vendors DTBs....
> 
You don't need to touch any of the current DTBs, as they are fine with
the default bus range behavior. You need to keep the specified behavior
of the bus range property with the new code.

Regards,
Lucas
> 
> > 
> > It is perfectly valid to have a bus range of 0x00-0x10 assigned to one
> > instance and 0x50-0xff to the next instance. Additional with PCIe
> > hotplug you may not use the full range of the bus numbers on one
> > instance at the first scan, but only later populate more buses when
> > more
> > bridges are added to the tree.
> > 
> > > Drivers that do not specify the bus range in the DTB set pp-
> > >root_bus_nr = DW_ROOT_NR_UNDEFINED.
> > > Designware will check if the flag is set and will use the automatic
> > bus range
> > > assignment.
> > 
> > No, please lets get rid of this assignment altogether. The glue drivers
> > have no business in assigning the bus range. Please remove the
> > pp->root_bus_nr assignment from all the glue drivers.
> > 
> > "bus range" is a generic DW PCIe property, so just parse the root bus
> > number from the DT, it is handled the same way for all the DW based
> > PCIe
> > drivers. The bindings specifies that if the bus range property is
> > missing the range is 0x00-0xff, so you can default to 0 as the root bus
> > number in that case.
> > 
> > Also I would think this conversion warrants a patch on its own and
> > should not be mixed in the ARM64 support patch.
> > 
> > Regards,
> > Lucas
> > 

-- 
Pengutronix e.K.             | Lucas Stach                 |
Industrial Linux Solutions   | http://www.pengutronix.de/  |


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

* [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-20  8:27             ` Lucas Stach
  0 siblings, 0 replies; 53+ messages in thread
From: Lucas Stach @ 2015-08-20  8:27 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Gab,

Am Mittwoch, den 19.08.2015, 16:34 +0000 schrieb Gabriele Paoloni:
> Hi Lucas
> 
> First of all many thanks for the quick reply, really appreciated
> 
> > -----Original Message-----
> > From: Lucas Stach [mailto:l.stach at pengutronix.de]
> > Sent: Wednesday, August 19, 2015 4:37 PM
> > To: Gabriele Paoloni
> > Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1 at gmail.com; Pratyush Anand;
> > Arnd Bergmann; linux at arm.linux.org.uk; thomas.petazzoni at free-
> > electrons.com; lorenzo.pieralisi at arm.com; james.morse at arm.com;
> > Liviu.Dudau at arm.com; jason at lakedaemon.net; robh at kernel.org; linux-
> > pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> > devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > 
> > Hi Gab,
> > 
> > Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele Paoloni:
> > > Hi Lucas
> > >
> > > I have rewritten the patch to take into account multiple controllers.
> > >
> > > As you can see now there is a static var in dw_pcie_host_init() that
> > tracks
> > > the bus numbers used.
> > 
> > This is wrong. The DT specifies the valid bus number range. You can not
> > just assign the next free bus number to the root bus.
> 
> I think this is what is being done in
> http://lxr.free-electrons.com/source/arch/arm/kernel/bios32.c#L495
> and currently designware assigns the root bus number in
> http://lxr.free-electrons.com/source/drivers/pci/host/pcie-designware.c#L730
> 
You found the right spot. It works a bit different than I remember, but
is less broken than your current code. :)

It actually assigns the next instance a root bus number behind the
current instances bus range. Please note the difference to your code
which assigns the next free bus number, which may still lay within the
current instances bus range.

> 
> In general I agree with you but if you look at all the current drivers 
> based on designware none of them define the "bus-range" dtb property.
> Therefore doing as you say would break the current driver when we have
> multiple controllers...am I right?
> 
The current _code_ works fine for multiple controllers. It's just that
you must define the bus range property in the DTB if you want to enable
multiple instances of one controller and support a kernel without PCI
domains support. As all current implementations have only a single
instance of the controller per SoC, or depend on PCI domain support,
it's totally fine for them to not define the bus ranges property, as
it's an optional property and it is well defined how things behave if it
is absent. We absolutely need to keep that specified behavior.

> If that is the case in order to fix this in the way you say I would need
> to assign "bus-range" for all the PCIe drivers with multiple controllers:
> in this case I would split the default range evenly (that is, if we have 
> two controllers I would define "bus-range"  0-127 and 128-255)
> 
> If you think this solution is ok I can go for it. My only doubt was about
> touching other vendors DTBs....
> 
You don't need to touch any of the current DTBs, as they are fine with
the default bus range behavior. You need to keep the specified behavior
of the bus range property with the new code.

Regards,
Lucas
> 
> > 
> > It is perfectly valid to have a bus range of 0x00-0x10 assigned to one
> > instance and 0x50-0xff to the next instance. Additional with PCIe
> > hotplug you may not use the full range of the bus numbers on one
> > instance at the first scan, but only later populate more buses when
> > more
> > bridges are added to the tree.
> > 
> > > Drivers that do not specify the bus range in the DTB set pp-
> > >root_bus_nr = DW_ROOT_NR_UNDEFINED.
> > > Designware will check if the flag is set and will use the automatic
> > bus range
> > > assignment.
> > 
> > No, please lets get rid of this assignment altogether. The glue drivers
> > have no business in assigning the bus range. Please remove the
> > pp->root_bus_nr assignment from all the glue drivers.
> > 
> > "bus range" is a generic DW PCIe property, so just parse the root bus
> > number from the DT, it is handled the same way for all the DW based
> > PCIe
> > drivers. The bindings specifies that if the bus range property is
> > missing the range is 0x00-0xff, so you can default to 0 as the root bus
> > number in that case.
> > 
> > Also I would think this conversion warrants a patch on its own and
> > should not be mixed in the ARM64 support patch.
> > 
> > Regards,
> > Lucas
> > 

-- 
Pengutronix e.K.             | Lucas Stach                 |
Industrial Linux Solutions   | http://www.pengutronix.de/  |

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

* RE: [PATCH v7 3/6] PCI: designware: Add ARM64 support
  2015-08-20  8:27             ` Lucas Stach
  (?)
@ 2015-08-20 11:10               ` Gabriele Paoloni
  -1 siblings, 0 replies; 53+ messages in thread
From: Gabriele Paoloni @ 2015-08-20 11:10 UTC (permalink / raw)
  To: Lucas Stach
  Cc: Wangzhou (B),
	Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, lorenzo.pieralisi, james.morse, Liviu.Dudau,
	jason, robh, linux-pci, linux-arm-kernel, devicetree,
	Yuanzhichang, Zhudacai, zhangjukuo, qiuzhe

Hi Lucas

Again many thanks for explaining and for your time.

I got your point now and I have dug a bit better in the PCI_DOMAINS code.

However I have a question...see inline below

> -----Original Message-----
> From: Lucas Stach [mailto:l.stach@pengutronix.de]
> Sent: Thursday, August 20, 2015 9:27 AM
> To: Gabriele Paoloni
> Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com; Pratyush Anand;
> Arnd Bergmann; linux@arm.linux.org.uk; thomas.petazzoni@free-
> electrons.com; lorenzo.pieralisi@arm.com; james.morse@arm.com;
> Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org; linux-
> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> 
> Hi Gab,
> 
> Am Mittwoch, den 19.08.2015, 16:34 +0000 schrieb Gabriele Paoloni:
> > Hi Lucas
> >
> > First of all many thanks for the quick reply, really appreciated
> >
> > > -----Original Message-----
> > > From: Lucas Stach [mailto:l.stach@pengutronix.de]
> > > Sent: Wednesday, August 19, 2015 4:37 PM
> > > To: Gabriele Paoloni
> > > Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com; Pratyush
> Anand;
> > > Arnd Bergmann; linux@arm.linux.org.uk; thomas.petazzoni@free-
> > > electrons.com; lorenzo.pieralisi@arm.com; james.morse@arm.com;
> > > Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org; linux-
> > > pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> > > devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> > > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > >
> > > Hi Gab,
> > >
> > > Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele Paoloni:
> > > > Hi Lucas
> > > >
> > > > I have rewritten the patch to take into account multiple
> controllers.
> > > >
> > > > As you can see now there is a static var in dw_pcie_host_init()
> that
> > > tracks
> > > > the bus numbers used.
> > >
> > > This is wrong. The DT specifies the valid bus number range. You can
> not
> > > just assign the next free bus number to the root bus.
> >
> > I think this is what is being done in
> > http://lxr.free-electrons.com/source/arch/arm/kernel/bios32.c#L495
> > and currently designware assigns the root bus number in
> > http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
> designware.c#L730
> >
> You found the right spot. It works a bit different than I remember, but
> is less broken than your current code. :)
> 
> It actually assigns the next instance a root bus number behind the
> current instances bus range. Please note the difference to your code
> which assigns the next free bus number, which may still lay within the
> current instances bus range.

Mmmm here I have done a mistake: in the current designware the number of hw
controllers is always 1
http://lxr.free-electrons.com/source/drivers/pci/host/pcie-designware.c#L510
So the loop in bios32.c does not work on multiple PCIe ports...
However your comment about PCI_DOMAINS enlightened my mind and now I see
that when CONFIG_PCI_DOMAINS is defined we have the domains numbers
(tracked by __domain_nr).
So (correct me if I am wrong) if we have 2 PCIe ports that do not specify
the "bus-range" property, both root ports will enumerate starting from 
root_bus_nr = 0 and everything will still work ok.

So if my assumption is correct, I do not see why the orginal patch from Wang 
Zhou is wrong. 
The only point can be that assigning pp->root_bus_nr = 0 is not required 
as pp memory is kzalloc'ed (an therefore init to zero).


> 
> >
> > In general I agree with you but if you look at all the current
> drivers
> > based on designware none of them define the "bus-range" dtb property.
> > Therefore doing as you say would break the current driver when we
> have
> > multiple controllers...am I right?
> >
> The current _code_ works fine for multiple controllers. It's just that
> you must define the bus range property in the DTB if you want to enable
> multiple instances of one controller and support a kernel without PCI
> domains support. As all current implementations have only a single
> instance of the controller per SoC, or depend on PCI domain support,
> it's totally fine for them to not define the bus ranges property, as
> it's an optional property and it is well defined how things behave if
> it
> is absent. We absolutely need to keep that specified behavior.
> 
> > If that is the case in order to fix this in the way you say I would
> need
> > to assign "bus-range" for all the PCIe drivers with multiple
> controllers:
> > in this case I would split the default range evenly (that is, if we
> have
> > two controllers I would define "bus-range"  0-127 and 128-255)
> >
> > If you think this solution is ok I can go for it. My only doubt was
> about
> > touching other vendors DTBs....
> >
> You don't need to touch any of the current DTBs, as they are fine with
> the default bus range behavior. You need to keep the specified behavior
> of the bus range property with the new code.
> 
> Regards,
> Lucas
> >
> > >
> > > It is perfectly valid to have a bus range of 0x00-0x10 assigned to
> one
> > > instance and 0x50-0xff to the next instance. Additional with PCIe
> > > hotplug you may not use the full range of the bus numbers on one
> > > instance at the first scan, but only later populate more buses when
> > > more
> > > bridges are added to the tree.
> > >
> > > > Drivers that do not specify the bus range in the DTB set pp-
> > > >root_bus_nr = DW_ROOT_NR_UNDEFINED.
> > > > Designware will check if the flag is set and will use the
> automatic
> > > bus range
> > > > assignment.
> > >
> > > No, please lets get rid of this assignment altogether. The glue
> drivers
> > > have no business in assigning the bus range. Please remove the
> > > pp->root_bus_nr assignment from all the glue drivers.
> > >
> > > "bus range" is a generic DW PCIe property, so just parse the root
> bus
> > > number from the DT, it is handled the same way for all the DW based
> > > PCIe
> > > drivers. The bindings specifies that if the bus range property is
> > > missing the range is 0x00-0xff, so you can default to 0 as the root
> bus
> > > number in that case.
> > >
> > > Also I would think this conversion warrants a patch on its own and
> > > should not be mixed in the ARM64 support patch.
> > >
> > > Regards,
> > > Lucas
> > >
> 
> --
> Pengutronix e.K.             | Lucas Stach                 |
> Industrial Linux Solutions   | http://www.pengutronix.de/  |


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

* RE: [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-20 11:10               ` Gabriele Paoloni
  0 siblings, 0 replies; 53+ messages in thread
From: Gabriele Paoloni @ 2015-08-20 11:10 UTC (permalink / raw)
  To: Lucas Stach
  Cc: Wangzhou (B),
	Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, lorenzo.pieralisi, james.morse, Liviu.Dudau,
	jason, robh, linux-pci, linux-arm-kernel, devicetree,
	Yuanzhichang, Zhudacai, zhangjukuo, qiuzhenfa, liudongdong (C),
	qiujiang, xuwei (O), Liguozhu (Kenneth)

SGkgTHVjYXMNCg0KQWdhaW4gbWFueSB0aGFua3MgZm9yIGV4cGxhaW5pbmcgYW5kIGZvciB5b3Vy
IHRpbWUuDQoNCkkgZ290IHlvdXIgcG9pbnQgbm93IGFuZCBJIGhhdmUgZHVnIGEgYml0IGJldHRl
ciBpbiB0aGUgUENJX0RPTUFJTlMgY29kZS4NCg0KSG93ZXZlciBJIGhhdmUgYSBxdWVzdGlvbi4u
LnNlZSBpbmxpbmUgYmVsb3cNCg0KPiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9t
OiBMdWNhcyBTdGFjaCBbbWFpbHRvOmwuc3RhY2hAcGVuZ3V0cm9uaXguZGVdDQo+IFNlbnQ6IFRo
dXJzZGF5LCBBdWd1c3QgMjAsIDIwMTUgOToyNyBBTQ0KPiBUbzogR2FicmllbGUgUGFvbG9uaQ0K
PiBDYzogV2FuZ3pob3UgKEIpOyBCam9ybiBIZWxnYWFzOyBqaW5nb29oYW4xQGdtYWlsLmNvbTsg
UHJhdHl1c2ggQW5hbmQ7DQo+IEFybmQgQmVyZ21hbm47IGxpbnV4QGFybS5saW51eC5vcmcudWs7
IHRob21hcy5wZXRhenpvbmlAZnJlZS0NCj4gZWxlY3Ryb25zLmNvbTsgbG9yZW56by5waWVyYWxp
c2lAYXJtLmNvbTsgamFtZXMubW9yc2VAYXJtLmNvbTsNCj4gTGl2aXUuRHVkYXVAYXJtLmNvbTsg
amFzb25AbGFrZWRhZW1vbi5uZXQ7IHJvYmhAa2VybmVsLm9yZzsgbGludXgtDQo+IHBjaUB2Z2Vy
Lmtlcm5lbC5vcmc7IGxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZzsNCj4gZGV2
aWNldHJlZUB2Z2VyLmtlcm5lbC5vcmc7IFl1YW56aGljaGFuZzsgWmh1ZGFjYWk7IHpoYW5nanVr
dW87DQo+IHFpdXpoZW5mYTsgbGl1ZG9uZ2RvbmcgKEMpOyBxaXVqaWFuZzsgeHV3ZWkgKE8pOyBM
aWd1b3podSAoS2VubmV0aCkNCj4gU3ViamVjdDogUmU6IFtQQVRDSCB2NyAzLzZdIFBDSTogZGVz
aWdud2FyZTogQWRkIEFSTTY0IHN1cHBvcnQNCj4gDQo+IEhpIEdhYiwNCj4gDQo+IEFtIE1pdHR3
b2NoLCBkZW4gMTkuMDguMjAxNSwgMTY6MzQgKzAwMDAgc2NocmllYiBHYWJyaWVsZSBQYW9sb25p
Og0KPiA+IEhpIEx1Y2FzDQo+ID4NCj4gPiBGaXJzdCBvZiBhbGwgbWFueSB0aGFua3MgZm9yIHRo
ZSBxdWljayByZXBseSwgcmVhbGx5IGFwcHJlY2lhdGVkDQo+ID4NCj4gPiA+IC0tLS0tT3JpZ2lu
YWwgTWVzc2FnZS0tLS0tDQo+ID4gPiBGcm9tOiBMdWNhcyBTdGFjaCBbbWFpbHRvOmwuc3RhY2hA
cGVuZ3V0cm9uaXguZGVdDQo+ID4gPiBTZW50OiBXZWRuZXNkYXksIEF1Z3VzdCAxOSwgMjAxNSA0
OjM3IFBNDQo+ID4gPiBUbzogR2FicmllbGUgUGFvbG9uaQ0KPiA+ID4gQ2M6IFdhbmd6aG91IChC
KTsgQmpvcm4gSGVsZ2FhczsgamluZ29vaGFuMUBnbWFpbC5jb207IFByYXR5dXNoDQo+IEFuYW5k
Ow0KPiA+ID4gQXJuZCBCZXJnbWFubjsgbGludXhAYXJtLmxpbnV4Lm9yZy51azsgdGhvbWFzLnBl
dGF6em9uaUBmcmVlLQ0KPiA+ID4gZWxlY3Ryb25zLmNvbTsgbG9yZW56by5waWVyYWxpc2lAYXJt
LmNvbTsgamFtZXMubW9yc2VAYXJtLmNvbTsNCj4gPiA+IExpdml1LkR1ZGF1QGFybS5jb207IGph
c29uQGxha2VkYWVtb24ubmV0OyByb2JoQGtlcm5lbC5vcmc7IGxpbnV4LQ0KPiA+ID4gcGNpQHZn
ZXIua2VybmVsLm9yZzsgbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnOw0KPiA+
ID4gZGV2aWNldHJlZUB2Z2VyLmtlcm5lbC5vcmc7IFl1YW56aGljaGFuZzsgWmh1ZGFjYWk7IHpo
YW5nanVrdW87DQo+ID4gPiBxaXV6aGVuZmE7IGxpdWRvbmdkb25nIChDKTsgcWl1amlhbmc7IHh1
d2VpIChPKTsgTGlndW96aHUgKEtlbm5ldGgpDQo+ID4gPiBTdWJqZWN0OiBSZTogW1BBVENIIHY3
IDMvNl0gUENJOiBkZXNpZ253YXJlOiBBZGQgQVJNNjQgc3VwcG9ydA0KPiA+ID4NCj4gPiA+IEhp
IEdhYiwNCj4gPiA+DQo+ID4gPiBBbSBNaXR0d29jaCwgZGVuIDE5LjA4LjIwMTUsIDE1OjE2ICsw
MDAwIHNjaHJpZWIgR2FicmllbGUgUGFvbG9uaToNCj4gPiA+ID4gSGkgTHVjYXMNCj4gPiA+ID4N
Cj4gPiA+ID4gSSBoYXZlIHJld3JpdHRlbiB0aGUgcGF0Y2ggdG8gdGFrZSBpbnRvIGFjY291bnQg
bXVsdGlwbGUNCj4gY29udHJvbGxlcnMuDQo+ID4gPiA+DQo+ID4gPiA+IEFzIHlvdSBjYW4gc2Vl
IG5vdyB0aGVyZSBpcyBhIHN0YXRpYyB2YXIgaW4gZHdfcGNpZV9ob3N0X2luaXQoKQ0KPiB0aGF0
DQo+ID4gPiB0cmFja3MNCj4gPiA+ID4gdGhlIGJ1cyBudW1iZXJzIHVzZWQuDQo+ID4gPg0KPiA+
ID4gVGhpcyBpcyB3cm9uZy4gVGhlIERUIHNwZWNpZmllcyB0aGUgdmFsaWQgYnVzIG51bWJlciBy
YW5nZS4gWW91IGNhbg0KPiBub3QNCj4gPiA+IGp1c3QgYXNzaWduIHRoZSBuZXh0IGZyZWUgYnVz
IG51bWJlciB0byB0aGUgcm9vdCBidXMuDQo+ID4NCj4gPiBJIHRoaW5rIHRoaXMgaXMgd2hhdCBp
cyBiZWluZyBkb25lIGluDQo+ID4gaHR0cDovL2x4ci5mcmVlLWVsZWN0cm9ucy5jb20vc291cmNl
L2FyY2gvYXJtL2tlcm5lbC9iaW9zMzIuYyNMNDk1DQo+ID4gYW5kIGN1cnJlbnRseSBkZXNpZ253
YXJlIGFzc2lnbnMgdGhlIHJvb3QgYnVzIG51bWJlciBpbg0KPiA+IGh0dHA6Ly9seHIuZnJlZS1l
bGVjdHJvbnMuY29tL3NvdXJjZS9kcml2ZXJzL3BjaS9ob3N0L3BjaWUtDQo+IGRlc2lnbndhcmUu
YyNMNzMwDQo+ID4NCj4gWW91IGZvdW5kIHRoZSByaWdodCBzcG90LiBJdCB3b3JrcyBhIGJpdCBk
aWZmZXJlbnQgdGhhbiBJIHJlbWVtYmVyLCBidXQNCj4gaXMgbGVzcyBicm9rZW4gdGhhbiB5b3Vy
IGN1cnJlbnQgY29kZS4gOikNCj4gDQo+IEl0IGFjdHVhbGx5IGFzc2lnbnMgdGhlIG5leHQgaW5z
dGFuY2UgYSByb290IGJ1cyBudW1iZXIgYmVoaW5kIHRoZQ0KPiBjdXJyZW50IGluc3RhbmNlcyBi
dXMgcmFuZ2UuIFBsZWFzZSBub3RlIHRoZSBkaWZmZXJlbmNlIHRvIHlvdXIgY29kZQ0KPiB3aGlj
aCBhc3NpZ25zIHRoZSBuZXh0IGZyZWUgYnVzIG51bWJlciwgd2hpY2ggbWF5IHN0aWxsIGxheSB3
aXRoaW4gdGhlDQo+IGN1cnJlbnQgaW5zdGFuY2VzIGJ1cyByYW5nZS4NCg0KTW1tbSBoZXJlIEkg
aGF2ZSBkb25lIGEgbWlzdGFrZTogaW4gdGhlIGN1cnJlbnQgZGVzaWdud2FyZSB0aGUgbnVtYmVy
IG9mIGh3DQpjb250cm9sbGVycyBpcyBhbHdheXMgMQ0KaHR0cDovL2x4ci5mcmVlLWVsZWN0cm9u
cy5jb20vc291cmNlL2RyaXZlcnMvcGNpL2hvc3QvcGNpZS1kZXNpZ253YXJlLmMjTDUxMA0KU28g
dGhlIGxvb3AgaW4gYmlvczMyLmMgZG9lcyBub3Qgd29yayBvbiBtdWx0aXBsZSBQQ0llIHBvcnRz
Li4uDQpIb3dldmVyIHlvdXIgY29tbWVudCBhYm91dCBQQ0lfRE9NQUlOUyBlbmxpZ2h0ZW5lZCBt
eSBtaW5kIGFuZCBub3cgSSBzZWUNCnRoYXQgd2hlbiBDT05GSUdfUENJX0RPTUFJTlMgaXMgZGVm
aW5lZCB3ZSBoYXZlIHRoZSBkb21haW5zIG51bWJlcnMNCih0cmFja2VkIGJ5IF9fZG9tYWluX25y
KS4NClNvIChjb3JyZWN0IG1lIGlmIEkgYW0gd3JvbmcpIGlmIHdlIGhhdmUgMiBQQ0llIHBvcnRz
IHRoYXQgZG8gbm90IHNwZWNpZnkNCnRoZSAiYnVzLXJhbmdlIiBwcm9wZXJ0eSwgYm90aCByb290
IHBvcnRzIHdpbGwgZW51bWVyYXRlIHN0YXJ0aW5nIGZyb20gDQpyb290X2J1c19uciA9IDAgYW5k
IGV2ZXJ5dGhpbmcgd2lsbCBzdGlsbCB3b3JrIG9rLg0KDQpTbyBpZiBteSBhc3N1bXB0aW9uIGlz
IGNvcnJlY3QsIEkgZG8gbm90IHNlZSB3aHkgdGhlIG9yZ2luYWwgcGF0Y2ggZnJvbSBXYW5nIA0K
WmhvdSBpcyB3cm9uZy4gDQpUaGUgb25seSBwb2ludCBjYW4gYmUgdGhhdCBhc3NpZ25pbmcgcHAt
PnJvb3RfYnVzX25yID0gMCBpcyBub3QgcmVxdWlyZWQgDQphcyBwcCBtZW1vcnkgaXMga3phbGxv
YydlZCAoYW4gdGhlcmVmb3JlIGluaXQgdG8gemVybykuDQoNCg0KPiANCj4gPg0KPiA+IEluIGdl
bmVyYWwgSSBhZ3JlZSB3aXRoIHlvdSBidXQgaWYgeW91IGxvb2sgYXQgYWxsIHRoZSBjdXJyZW50
DQo+IGRyaXZlcnMNCj4gPiBiYXNlZCBvbiBkZXNpZ253YXJlIG5vbmUgb2YgdGhlbSBkZWZpbmUg
dGhlICJidXMtcmFuZ2UiIGR0YiBwcm9wZXJ0eS4NCj4gPiBUaGVyZWZvcmUgZG9pbmcgYXMgeW91
IHNheSB3b3VsZCBicmVhayB0aGUgY3VycmVudCBkcml2ZXIgd2hlbiB3ZQ0KPiBoYXZlDQo+ID4g
bXVsdGlwbGUgY29udHJvbGxlcnMuLi5hbSBJIHJpZ2h0Pw0KPiA+DQo+IFRoZSBjdXJyZW50IF9j
b2RlXyB3b3JrcyBmaW5lIGZvciBtdWx0aXBsZSBjb250cm9sbGVycy4gSXQncyBqdXN0IHRoYXQN
Cj4geW91IG11c3QgZGVmaW5lIHRoZSBidXMgcmFuZ2UgcHJvcGVydHkgaW4gdGhlIERUQiBpZiB5
b3Ugd2FudCB0byBlbmFibGUNCj4gbXVsdGlwbGUgaW5zdGFuY2VzIG9mIG9uZSBjb250cm9sbGVy
IGFuZCBzdXBwb3J0IGEga2VybmVsIHdpdGhvdXQgUENJDQo+IGRvbWFpbnMgc3VwcG9ydC4gQXMg
YWxsIGN1cnJlbnQgaW1wbGVtZW50YXRpb25zIGhhdmUgb25seSBhIHNpbmdsZQ0KPiBpbnN0YW5j
ZSBvZiB0aGUgY29udHJvbGxlciBwZXIgU29DLCBvciBkZXBlbmQgb24gUENJIGRvbWFpbiBzdXBw
b3J0LA0KPiBpdCdzIHRvdGFsbHkgZmluZSBmb3IgdGhlbSB0byBub3QgZGVmaW5lIHRoZSBidXMg
cmFuZ2VzIHByb3BlcnR5LCBhcw0KPiBpdCdzIGFuIG9wdGlvbmFsIHByb3BlcnR5IGFuZCBpdCBp
cyB3ZWxsIGRlZmluZWQgaG93IHRoaW5ncyBiZWhhdmUgaWYNCj4gaXQNCj4gaXMgYWJzZW50LiBX
ZSBhYnNvbHV0ZWx5IG5lZWQgdG8ga2VlcCB0aGF0IHNwZWNpZmllZCBiZWhhdmlvci4NCj4gDQo+
ID4gSWYgdGhhdCBpcyB0aGUgY2FzZSBpbiBvcmRlciB0byBmaXggdGhpcyBpbiB0aGUgd2F5IHlv
dSBzYXkgSSB3b3VsZA0KPiBuZWVkDQo+ID4gdG8gYXNzaWduICJidXMtcmFuZ2UiIGZvciBhbGwg
dGhlIFBDSWUgZHJpdmVycyB3aXRoIG11bHRpcGxlDQo+IGNvbnRyb2xsZXJzOg0KPiA+IGluIHRo
aXMgY2FzZSBJIHdvdWxkIHNwbGl0IHRoZSBkZWZhdWx0IHJhbmdlIGV2ZW5seSAodGhhdCBpcywg
aWYgd2UNCj4gaGF2ZQ0KPiA+IHR3byBjb250cm9sbGVycyBJIHdvdWxkIGRlZmluZSAiYnVzLXJh
bmdlIiAgMC0xMjcgYW5kIDEyOC0yNTUpDQo+ID4NCj4gPiBJZiB5b3UgdGhpbmsgdGhpcyBzb2x1
dGlvbiBpcyBvayBJIGNhbiBnbyBmb3IgaXQuIE15IG9ubHkgZG91YnQgd2FzDQo+IGFib3V0DQo+
ID4gdG91Y2hpbmcgb3RoZXIgdmVuZG9ycyBEVEJzLi4uLg0KPiA+DQo+IFlvdSBkb24ndCBuZWVk
IHRvIHRvdWNoIGFueSBvZiB0aGUgY3VycmVudCBEVEJzLCBhcyB0aGV5IGFyZSBmaW5lIHdpdGgN
Cj4gdGhlIGRlZmF1bHQgYnVzIHJhbmdlIGJlaGF2aW9yLiBZb3UgbmVlZCB0byBrZWVwIHRoZSBz
cGVjaWZpZWQgYmVoYXZpb3INCj4gb2YgdGhlIGJ1cyByYW5nZSBwcm9wZXJ0eSB3aXRoIHRoZSBu
ZXcgY29kZS4NCj4gDQo+IFJlZ2FyZHMsDQo+IEx1Y2FzDQo+ID4NCj4gPiA+DQo+ID4gPiBJdCBp
cyBwZXJmZWN0bHkgdmFsaWQgdG8gaGF2ZSBhIGJ1cyByYW5nZSBvZiAweDAwLTB4MTAgYXNzaWdu
ZWQgdG8NCj4gb25lDQo+ID4gPiBpbnN0YW5jZSBhbmQgMHg1MC0weGZmIHRvIHRoZSBuZXh0IGlu
c3RhbmNlLiBBZGRpdGlvbmFsIHdpdGggUENJZQ0KPiA+ID4gaG90cGx1ZyB5b3UgbWF5IG5vdCB1
c2UgdGhlIGZ1bGwgcmFuZ2Ugb2YgdGhlIGJ1cyBudW1iZXJzIG9uIG9uZQ0KPiA+ID4gaW5zdGFu
Y2UgYXQgdGhlIGZpcnN0IHNjYW4sIGJ1dCBvbmx5IGxhdGVyIHBvcHVsYXRlIG1vcmUgYnVzZXMg
d2hlbg0KPiA+ID4gbW9yZQ0KPiA+ID4gYnJpZGdlcyBhcmUgYWRkZWQgdG8gdGhlIHRyZWUuDQo+
ID4gPg0KPiA+ID4gPiBEcml2ZXJzIHRoYXQgZG8gbm90IHNwZWNpZnkgdGhlIGJ1cyByYW5nZSBp
biB0aGUgRFRCIHNldCBwcC0NCj4gPiA+ID5yb290X2J1c19uciA9IERXX1JPT1RfTlJfVU5ERUZJ
TkVELg0KPiA+ID4gPiBEZXNpZ253YXJlIHdpbGwgY2hlY2sgaWYgdGhlIGZsYWcgaXMgc2V0IGFu
ZCB3aWxsIHVzZSB0aGUNCj4gYXV0b21hdGljDQo+ID4gPiBidXMgcmFuZ2UNCj4gPiA+ID4gYXNz
aWdubWVudC4NCj4gPiA+DQo+ID4gPiBObywgcGxlYXNlIGxldHMgZ2V0IHJpZCBvZiB0aGlzIGFz
c2lnbm1lbnQgYWx0b2dldGhlci4gVGhlIGdsdWUNCj4gZHJpdmVycw0KPiA+ID4gaGF2ZSBubyBi
dXNpbmVzcyBpbiBhc3NpZ25pbmcgdGhlIGJ1cyByYW5nZS4gUGxlYXNlIHJlbW92ZSB0aGUNCj4g
PiA+IHBwLT5yb290X2J1c19uciBhc3NpZ25tZW50IGZyb20gYWxsIHRoZSBnbHVlIGRyaXZlcnMu
DQo+ID4gPg0KPiA+ID4gImJ1cyByYW5nZSIgaXMgYSBnZW5lcmljIERXIFBDSWUgcHJvcGVydHks
IHNvIGp1c3QgcGFyc2UgdGhlIHJvb3QNCj4gYnVzDQo+ID4gPiBudW1iZXIgZnJvbSB0aGUgRFQs
IGl0IGlzIGhhbmRsZWQgdGhlIHNhbWUgd2F5IGZvciBhbGwgdGhlIERXIGJhc2VkDQo+ID4gPiBQ
Q0llDQo+ID4gPiBkcml2ZXJzLiBUaGUgYmluZGluZ3Mgc3BlY2lmaWVzIHRoYXQgaWYgdGhlIGJ1
cyByYW5nZSBwcm9wZXJ0eSBpcw0KPiA+ID4gbWlzc2luZyB0aGUgcmFuZ2UgaXMgMHgwMC0weGZm
LCBzbyB5b3UgY2FuIGRlZmF1bHQgdG8gMCBhcyB0aGUgcm9vdA0KPiBidXMNCj4gPiA+IG51bWJl
ciBpbiB0aGF0IGNhc2UuDQo+ID4gPg0KPiA+ID4gQWxzbyBJIHdvdWxkIHRoaW5rIHRoaXMgY29u
dmVyc2lvbiB3YXJyYW50cyBhIHBhdGNoIG9uIGl0cyBvd24gYW5kDQo+ID4gPiBzaG91bGQgbm90
IGJlIG1peGVkIGluIHRoZSBBUk02NCBzdXBwb3J0IHBhdGNoLg0KPiA+ID4NCj4gPiA+IFJlZ2Fy
ZHMsDQo+ID4gPiBMdWNhcw0KPiA+ID4NCj4gDQo+IC0tDQo+IFBlbmd1dHJvbml4IGUuSy4gICAg
ICAgICAgICAgfCBMdWNhcyBTdGFjaCAgICAgICAgICAgICAgICAgfA0KPiBJbmR1c3RyaWFsIExp
bnV4IFNvbHV0aW9ucyAgIHwgaHR0cDovL3d3dy5wZW5ndXRyb25peC5kZS8gIHwNCg0K

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

* [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-20 11:10               ` Gabriele Paoloni
  0 siblings, 0 replies; 53+ messages in thread
From: Gabriele Paoloni @ 2015-08-20 11:10 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Lucas

Again many thanks for explaining and for your time.

I got your point now and I have dug a bit better in the PCI_DOMAINS code.

However I have a question...see inline below

> -----Original Message-----
> From: Lucas Stach [mailto:l.stach at pengutronix.de]
> Sent: Thursday, August 20, 2015 9:27 AM
> To: Gabriele Paoloni
> Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1 at gmail.com; Pratyush Anand;
> Arnd Bergmann; linux at arm.linux.org.uk; thomas.petazzoni at free-
> electrons.com; lorenzo.pieralisi at arm.com; james.morse at arm.com;
> Liviu.Dudau at arm.com; jason at lakedaemon.net; robh at kernel.org; linux-
> pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> 
> Hi Gab,
> 
> Am Mittwoch, den 19.08.2015, 16:34 +0000 schrieb Gabriele Paoloni:
> > Hi Lucas
> >
> > First of all many thanks for the quick reply, really appreciated
> >
> > > -----Original Message-----
> > > From: Lucas Stach [mailto:l.stach at pengutronix.de]
> > > Sent: Wednesday, August 19, 2015 4:37 PM
> > > To: Gabriele Paoloni
> > > Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1 at gmail.com; Pratyush
> Anand;
> > > Arnd Bergmann; linux at arm.linux.org.uk; thomas.petazzoni at free-
> > > electrons.com; lorenzo.pieralisi at arm.com; james.morse at arm.com;
> > > Liviu.Dudau at arm.com; jason at lakedaemon.net; robh at kernel.org; linux-
> > > pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> > > devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> > > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > >
> > > Hi Gab,
> > >
> > > Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele Paoloni:
> > > > Hi Lucas
> > > >
> > > > I have rewritten the patch to take into account multiple
> controllers.
> > > >
> > > > As you can see now there is a static var in dw_pcie_host_init()
> that
> > > tracks
> > > > the bus numbers used.
> > >
> > > This is wrong. The DT specifies the valid bus number range. You can
> not
> > > just assign the next free bus number to the root bus.
> >
> > I think this is what is being done in
> > http://lxr.free-electrons.com/source/arch/arm/kernel/bios32.c#L495
> > and currently designware assigns the root bus number in
> > http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
> designware.c#L730
> >
> You found the right spot. It works a bit different than I remember, but
> is less broken than your current code. :)
> 
> It actually assigns the next instance a root bus number behind the
> current instances bus range. Please note the difference to your code
> which assigns the next free bus number, which may still lay within the
> current instances bus range.

Mmmm here I have done a mistake: in the current designware the number of hw
controllers is always 1
http://lxr.free-electrons.com/source/drivers/pci/host/pcie-designware.c#L510
So the loop in bios32.c does not work on multiple PCIe ports...
However your comment about PCI_DOMAINS enlightened my mind and now I see
that when CONFIG_PCI_DOMAINS is defined we have the domains numbers
(tracked by __domain_nr).
So (correct me if I am wrong) if we have 2 PCIe ports that do not specify
the "bus-range" property, both root ports will enumerate starting from 
root_bus_nr = 0 and everything will still work ok.

So if my assumption is correct, I do not see why the orginal patch from Wang 
Zhou is wrong. 
The only point can be that assigning pp->root_bus_nr = 0 is not required 
as pp memory is kzalloc'ed (an therefore init to zero).


> 
> >
> > In general I agree with you but if you look at all the current
> drivers
> > based on designware none of them define the "bus-range" dtb property.
> > Therefore doing as you say would break the current driver when we
> have
> > multiple controllers...am I right?
> >
> The current _code_ works fine for multiple controllers. It's just that
> you must define the bus range property in the DTB if you want to enable
> multiple instances of one controller and support a kernel without PCI
> domains support. As all current implementations have only a single
> instance of the controller per SoC, or depend on PCI domain support,
> it's totally fine for them to not define the bus ranges property, as
> it's an optional property and it is well defined how things behave if
> it
> is absent. We absolutely need to keep that specified behavior.
> 
> > If that is the case in order to fix this in the way you say I would
> need
> > to assign "bus-range" for all the PCIe drivers with multiple
> controllers:
> > in this case I would split the default range evenly (that is, if we
> have
> > two controllers I would define "bus-range"  0-127 and 128-255)
> >
> > If you think this solution is ok I can go for it. My only doubt was
> about
> > touching other vendors DTBs....
> >
> You don't need to touch any of the current DTBs, as they are fine with
> the default bus range behavior. You need to keep the specified behavior
> of the bus range property with the new code.
> 
> Regards,
> Lucas
> >
> > >
> > > It is perfectly valid to have a bus range of 0x00-0x10 assigned to
> one
> > > instance and 0x50-0xff to the next instance. Additional with PCIe
> > > hotplug you may not use the full range of the bus numbers on one
> > > instance at the first scan, but only later populate more buses when
> > > more
> > > bridges are added to the tree.
> > >
> > > > Drivers that do not specify the bus range in the DTB set pp-
> > > >root_bus_nr = DW_ROOT_NR_UNDEFINED.
> > > > Designware will check if the flag is set and will use the
> automatic
> > > bus range
> > > > assignment.
> > >
> > > No, please lets get rid of this assignment altogether. The glue
> drivers
> > > have no business in assigning the bus range. Please remove the
> > > pp->root_bus_nr assignment from all the glue drivers.
> > >
> > > "bus range" is a generic DW PCIe property, so just parse the root
> bus
> > > number from the DT, it is handled the same way for all the DW based
> > > PCIe
> > > drivers. The bindings specifies that if the bus range property is
> > > missing the range is 0x00-0xff, so you can default to 0 as the root
> bus
> > > number in that case.
> > >
> > > Also I would think this conversion warrants a patch on its own and
> > > should not be mixed in the ARM64 support patch.
> > >
> > > Regards,
> > > Lucas
> > >
> 
> --
> Pengutronix e.K.             | Lucas Stach                 |
> Industrial Linux Solutions   | http://www.pengutronix.de/  |

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

* Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
  2015-08-20 11:10               ` Gabriele Paoloni
  (?)
@ 2015-08-21 13:42                 ` Liviu Dudau
  -1 siblings, 0 replies; 53+ messages in thread
From: Liviu Dudau @ 2015-08-21 13:42 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Lucas Stach, Wangzhou (B),
	Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, Lorenzo Pieralisi, James Morse, jason, robh,
	linux-pci, linux-arm-kernel, devicetree, Yuanzhichang, Zhudacai,
	zhangjukuo, qiuzhenfa

On Thu, Aug 20, 2015 at 12:10:24PM +0100, Gabriele Paoloni wrote:
> Hi Lucas
> 
> Again many thanks for explaining and for your time.
> 
> I got your point now and I have dug a bit better in the PCI_DOMAINS code.
> 
> However I have a question...see inline below
> 
> > -----Original Message-----
> > From: Lucas Stach [mailto:l.stach@pengutronix.de]
> > Sent: Thursday, August 20, 2015 9:27 AM
> > To: Gabriele Paoloni
> > Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com; Pratyush Anand;
> > Arnd Bergmann; linux@arm.linux.org.uk; thomas.petazzoni@free-
> > electrons.com; lorenzo.pieralisi@arm.com; james.morse@arm.com;
> > Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org; linux-
> > pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> > devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > 
> > Hi Gab,
> > 
> > Am Mittwoch, den 19.08.2015, 16:34 +0000 schrieb Gabriele Paoloni:
> > > Hi Lucas
> > >
> > > First of all many thanks for the quick reply, really appreciated
> > >
> > > > -----Original Message-----
> > > > From: Lucas Stach [mailto:l.stach@pengutronix.de]
> > > > Sent: Wednesday, August 19, 2015 4:37 PM
> > > > To: Gabriele Paoloni
> > > > Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com; Pratyush
> > Anand;
> > > > Arnd Bergmann; linux@arm.linux.org.uk; thomas.petazzoni@free-
> > > > electrons.com; lorenzo.pieralisi@arm.com; james.morse@arm.com;
> > > > Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org; linux-
> > > > pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> > > > devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > > > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> > > > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > > >
> > > > Hi Gab,
> > > >
> > > > Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele Paoloni:
> > > > > Hi Lucas
> > > > >
> > > > > I have rewritten the patch to take into account multiple
> > controllers.
> > > > >
> > > > > As you can see now there is a static var in dw_pcie_host_init()
> > that
> > > > tracks
> > > > > the bus numbers used.
> > > >
> > > > This is wrong. The DT specifies the valid bus number range. You can
> > not
> > > > just assign the next free bus number to the root bus.
> > >
> > > I think this is what is being done in
> > > http://lxr.free-electrons.com/source/arch/arm/kernel/bios32.c#L495
> > > and currently designware assigns the root bus number in
> > > http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
> > designware.c#L730
> > >
> > You found the right spot. It works a bit different than I remember, but
> > is less broken than your current code. :)
> > 
> > It actually assigns the next instance a root bus number behind the
> > current instances bus range. Please note the difference to your code
> > which assigns the next free bus number, which may still lay within the
> > current instances bus range.

Hi Gabriele,

> 
> Mmmm here I have done a mistake: in the current designware the number of hw
> controllers is always 1
> http://lxr.free-electrons.com/source/drivers/pci/host/pcie-designware.c#L510
> So the loop in bios32.c does not work on multiple PCIe ports...

Bios32.c is broken for multiple PCIe hosts for multiple reasons, this is just
one of them. Hence the effort to get rid of it for maintained drivers.

> However your comment about PCI_DOMAINS enlightened my mind and now I see
> that when CONFIG_PCI_DOMAINS is defined we have the domains numbers
> (tracked by __domain_nr).

CONFIG_PCI_DOMAINS in itself doesn't do much without adding code to your driver.
You could request a new domain for each controller with a special property to
disable that behaviour in the dts, or you could enable CONFIG_PCI_DOMAINS_GENERIC
which will give you a new domain automatically.

> So (correct me if I am wrong) if we have 2 PCIe ports that do not specify
> the "bus-range" property, both root ports will enumerate starting from 
> root_bus_nr = 0 and everything will still work ok.

Correct.

Best regards,
Liviu

> 
> So if my assumption is correct, I do not see why the orginal patch from Wang 
> Zhou is wrong. 
> The only point can be that assigning pp->root_bus_nr = 0 is not required 
> as pp memory is kzalloc'ed (an therefore init to zero).
> 
> 
> > 
> > >
> > > In general I agree with you but if you look at all the current
> > drivers
> > > based on designware none of them define the "bus-range" dtb property.
> > > Therefore doing as you say would break the current driver when we
> > have
> > > multiple controllers...am I right?
> > >
> > The current _code_ works fine for multiple controllers. It's just that
> > you must define the bus range property in the DTB if you want to enable
> > multiple instances of one controller and support a kernel without PCI
> > domains support. As all current implementations have only a single
> > instance of the controller per SoC, or depend on PCI domain support,
> > it's totally fine for them to not define the bus ranges property, as
> > it's an optional property and it is well defined how things behave if
> > it
> > is absent. We absolutely need to keep that specified behavior.
> > 
> > > If that is the case in order to fix this in the way you say I would
> > need
> > > to assign "bus-range" for all the PCIe drivers with multiple
> > controllers:
> > > in this case I would split the default range evenly (that is, if we
> > have
> > > two controllers I would define "bus-range"  0-127 and 128-255)
> > >
> > > If you think this solution is ok I can go for it. My only doubt was
> > about
> > > touching other vendors DTBs....
> > >
> > You don't need to touch any of the current DTBs, as they are fine with
> > the default bus range behavior. You need to keep the specified behavior
> > of the bus range property with the new code.
> > 
> > Regards,
> > Lucas
> > >
> > > >
> > > > It is perfectly valid to have a bus range of 0x00-0x10 assigned to
> > one
> > > > instance and 0x50-0xff to the next instance. Additional with PCIe
> > > > hotplug you may not use the full range of the bus numbers on one
> > > > instance at the first scan, but only later populate more buses when
> > > > more
> > > > bridges are added to the tree.
> > > >
> > > > > Drivers that do not specify the bus range in the DTB set pp-
> > > > >root_bus_nr = DW_ROOT_NR_UNDEFINED.
> > > > > Designware will check if the flag is set and will use the
> > automatic
> > > > bus range
> > > > > assignment.
> > > >
> > > > No, please lets get rid of this assignment altogether. The glue
> > drivers
> > > > have no business in assigning the bus range. Please remove the
> > > > pp->root_bus_nr assignment from all the glue drivers.
> > > >
> > > > "bus range" is a generic DW PCIe property, so just parse the root
> > bus
> > > > number from the DT, it is handled the same way for all the DW based
> > > > PCIe
> > > > drivers. The bindings specifies that if the bus range property is
> > > > missing the range is 0x00-0xff, so you can default to 0 as the root
> > bus
> > > > number in that case.
> > > >
> > > > Also I would think this conversion warrants a patch on its own and
> > > > should not be mixed in the ARM64 support patch.
> > > >
> > > > Regards,
> > > > Lucas
> > > >
> > 
> > --
> > Pengutronix e.K.             | Lucas Stach                 |
> > Industrial Linux Solutions   | http://www.pengutronix.de/  |
> 

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

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

* Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-21 13:42                 ` Liviu Dudau
  0 siblings, 0 replies; 53+ messages in thread
From: Liviu Dudau @ 2015-08-21 13:42 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Lucas Stach, Wangzhou (B),
	Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, Lorenzo Pieralisi, James Morse, jason, robh,
	linux-pci, linux-arm-kernel, devicetree, Yuanzhichang, Zhudacai,
	zhangjukuo, qiuzhenfa, liudongdong (C), qiujiang, xuwei (O),
	liguozhu

On Thu, Aug 20, 2015 at 12:10:24PM +0100, Gabriele Paoloni wrote:
> Hi Lucas
> 
> Again many thanks for explaining and for your time.
> 
> I got your point now and I have dug a bit better in the PCI_DOMAINS code.
> 
> However I have a question...see inline below
> 
> > -----Original Message-----
> > From: Lucas Stach [mailto:l.stach@pengutronix.de]
> > Sent: Thursday, August 20, 2015 9:27 AM
> > To: Gabriele Paoloni
> > Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com; Pratyush Anand;
> > Arnd Bergmann; linux@arm.linux.org.uk; thomas.petazzoni@free-
> > electrons.com; lorenzo.pieralisi@arm.com; james.morse@arm.com;
> > Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org; linux-
> > pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> > devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > 
> > Hi Gab,
> > 
> > Am Mittwoch, den 19.08.2015, 16:34 +0000 schrieb Gabriele Paoloni:
> > > Hi Lucas
> > >
> > > First of all many thanks for the quick reply, really appreciated
> > >
> > > > -----Original Message-----
> > > > From: Lucas Stach [mailto:l.stach@pengutronix.de]
> > > > Sent: Wednesday, August 19, 2015 4:37 PM
> > > > To: Gabriele Paoloni
> > > > Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com; Pratyush
> > Anand;
> > > > Arnd Bergmann; linux@arm.linux.org.uk; thomas.petazzoni@free-
> > > > electrons.com; lorenzo.pieralisi@arm.com; james.morse@arm.com;
> > > > Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org; linux-
> > > > pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> > > > devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > > > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> > > > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > > >
> > > > Hi Gab,
> > > >
> > > > Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele Paoloni:
> > > > > Hi Lucas
> > > > >
> > > > > I have rewritten the patch to take into account multiple
> > controllers.
> > > > >
> > > > > As you can see now there is a static var in dw_pcie_host_init()
> > that
> > > > tracks
> > > > > the bus numbers used.
> > > >
> > > > This is wrong. The DT specifies the valid bus number range. You can
> > not
> > > > just assign the next free bus number to the root bus.
> > >
> > > I think this is what is being done in
> > > http://lxr.free-electrons.com/source/arch/arm/kernel/bios32.c#L495
> > > and currently designware assigns the root bus number in
> > > http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
> > designware.c#L730
> > >
> > You found the right spot. It works a bit different than I remember, but
> > is less broken than your current code. :)
> > 
> > It actually assigns the next instance a root bus number behind the
> > current instances bus range. Please note the difference to your code
> > which assigns the next free bus number, which may still lay within the
> > current instances bus range.

Hi Gabriele,

> 
> Mmmm here I have done a mistake: in the current designware the number of hw
> controllers is always 1
> http://lxr.free-electrons.com/source/drivers/pci/host/pcie-designware.c#L510
> So the loop in bios32.c does not work on multiple PCIe ports...

Bios32.c is broken for multiple PCIe hosts for multiple reasons, this is just
one of them. Hence the effort to get rid of it for maintained drivers.

> However your comment about PCI_DOMAINS enlightened my mind and now I see
> that when CONFIG_PCI_DOMAINS is defined we have the domains numbers
> (tracked by __domain_nr).

CONFIG_PCI_DOMAINS in itself doesn't do much without adding code to your driver.
You could request a new domain for each controller with a special property to
disable that behaviour in the dts, or you could enable CONFIG_PCI_DOMAINS_GENERIC
which will give you a new domain automatically.

> So (correct me if I am wrong) if we have 2 PCIe ports that do not specify
> the "bus-range" property, both root ports will enumerate starting from 
> root_bus_nr = 0 and everything will still work ok.

Correct.

Best regards,
Liviu

> 
> So if my assumption is correct, I do not see why the orginal patch from Wang 
> Zhou is wrong. 
> The only point can be that assigning pp->root_bus_nr = 0 is not required 
> as pp memory is kzalloc'ed (an therefore init to zero).
> 
> 
> > 
> > >
> > > In general I agree with you but if you look at all the current
> > drivers
> > > based on designware none of them define the "bus-range" dtb property.
> > > Therefore doing as you say would break the current driver when we
> > have
> > > multiple controllers...am I right?
> > >
> > The current _code_ works fine for multiple controllers. It's just that
> > you must define the bus range property in the DTB if you want to enable
> > multiple instances of one controller and support a kernel without PCI
> > domains support. As all current implementations have only a single
> > instance of the controller per SoC, or depend on PCI domain support,
> > it's totally fine for them to not define the bus ranges property, as
> > it's an optional property and it is well defined how things behave if
> > it
> > is absent. We absolutely need to keep that specified behavior.
> > 
> > > If that is the case in order to fix this in the way you say I would
> > need
> > > to assign "bus-range" for all the PCIe drivers with multiple
> > controllers:
> > > in this case I would split the default range evenly (that is, if we
> > have
> > > two controllers I would define "bus-range"  0-127 and 128-255)
> > >
> > > If you think this solution is ok I can go for it. My only doubt was
> > about
> > > touching other vendors DTBs....
> > >
> > You don't need to touch any of the current DTBs, as they are fine with
> > the default bus range behavior. You need to keep the specified behavior
> > of the bus range property with the new code.
> > 
> > Regards,
> > Lucas
> > >
> > > >
> > > > It is perfectly valid to have a bus range of 0x00-0x10 assigned to
> > one
> > > > instance and 0x50-0xff to the next instance. Additional with PCIe
> > > > hotplug you may not use the full range of the bus numbers on one
> > > > instance at the first scan, but only later populate more buses when
> > > > more
> > > > bridges are added to the tree.
> > > >
> > > > > Drivers that do not specify the bus range in the DTB set pp-
> > > > >root_bus_nr = DW_ROOT_NR_UNDEFINED.
> > > > > Designware will check if the flag is set and will use the
> > automatic
> > > > bus range
> > > > > assignment.
> > > >
> > > > No, please lets get rid of this assignment altogether. The glue
> > drivers
> > > > have no business in assigning the bus range. Please remove the
> > > > pp->root_bus_nr assignment from all the glue drivers.
> > > >
> > > > "bus range" is a generic DW PCIe property, so just parse the root
> > bus
> > > > number from the DT, it is handled the same way for all the DW based
> > > > PCIe
> > > > drivers. The bindings specifies that if the bus range property is
> > > > missing the range is 0x00-0xff, so you can default to 0 as the root
> > bus
> > > > number in that case.
> > > >
> > > > Also I would think this conversion warrants a patch on its own and
> > > > should not be mixed in the ARM64 support patch.
> > > >
> > > > Regards,
> > > > Lucas
> > > >
> > 
> > --
> > Pengutronix e.K.             | Lucas Stach                 |
> > Industrial Linux Solutions   | http://www.pengutronix.de/  |
> 

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


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

* [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-21 13:42                 ` Liviu Dudau
  0 siblings, 0 replies; 53+ messages in thread
From: Liviu Dudau @ 2015-08-21 13:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 20, 2015 at 12:10:24PM +0100, Gabriele Paoloni wrote:
> Hi Lucas
> 
> Again many thanks for explaining and for your time.
> 
> I got your point now and I have dug a bit better in the PCI_DOMAINS code.
> 
> However I have a question...see inline below
> 
> > -----Original Message-----
> > From: Lucas Stach [mailto:l.stach at pengutronix.de]
> > Sent: Thursday, August 20, 2015 9:27 AM
> > To: Gabriele Paoloni
> > Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1 at gmail.com; Pratyush Anand;
> > Arnd Bergmann; linux at arm.linux.org.uk; thomas.petazzoni at free-
> > electrons.com; lorenzo.pieralisi at arm.com; james.morse at arm.com;
> > Liviu.Dudau at arm.com; jason at lakedaemon.net; robh at kernel.org; linux-
> > pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> > devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > 
> > Hi Gab,
> > 
> > Am Mittwoch, den 19.08.2015, 16:34 +0000 schrieb Gabriele Paoloni:
> > > Hi Lucas
> > >
> > > First of all many thanks for the quick reply, really appreciated
> > >
> > > > -----Original Message-----
> > > > From: Lucas Stach [mailto:l.stach at pengutronix.de]
> > > > Sent: Wednesday, August 19, 2015 4:37 PM
> > > > To: Gabriele Paoloni
> > > > Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1 at gmail.com; Pratyush
> > Anand;
> > > > Arnd Bergmann; linux at arm.linux.org.uk; thomas.petazzoni at free-
> > > > electrons.com; lorenzo.pieralisi at arm.com; james.morse at arm.com;
> > > > Liviu.Dudau at arm.com; jason at lakedaemon.net; robh at kernel.org; linux-
> > > > pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> > > > devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > > > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> > > > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > > >
> > > > Hi Gab,
> > > >
> > > > Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele Paoloni:
> > > > > Hi Lucas
> > > > >
> > > > > I have rewritten the patch to take into account multiple
> > controllers.
> > > > >
> > > > > As you can see now there is a static var in dw_pcie_host_init()
> > that
> > > > tracks
> > > > > the bus numbers used.
> > > >
> > > > This is wrong. The DT specifies the valid bus number range. You can
> > not
> > > > just assign the next free bus number to the root bus.
> > >
> > > I think this is what is being done in
> > > http://lxr.free-electrons.com/source/arch/arm/kernel/bios32.c#L495
> > > and currently designware assigns the root bus number in
> > > http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
> > designware.c#L730
> > >
> > You found the right spot. It works a bit different than I remember, but
> > is less broken than your current code. :)
> > 
> > It actually assigns the next instance a root bus number behind the
> > current instances bus range. Please note the difference to your code
> > which assigns the next free bus number, which may still lay within the
> > current instances bus range.

Hi Gabriele,

> 
> Mmmm here I have done a mistake: in the current designware the number of hw
> controllers is always 1
> http://lxr.free-electrons.com/source/drivers/pci/host/pcie-designware.c#L510
> So the loop in bios32.c does not work on multiple PCIe ports...

Bios32.c is broken for multiple PCIe hosts for multiple reasons, this is just
one of them. Hence the effort to get rid of it for maintained drivers.

> However your comment about PCI_DOMAINS enlightened my mind and now I see
> that when CONFIG_PCI_DOMAINS is defined we have the domains numbers
> (tracked by __domain_nr).

CONFIG_PCI_DOMAINS in itself doesn't do much without adding code to your driver.
You could request a new domain for each controller with a special property to
disable that behaviour in the dts, or you could enable CONFIG_PCI_DOMAINS_GENERIC
which will give you a new domain automatically.

> So (correct me if I am wrong) if we have 2 PCIe ports that do not specify
> the "bus-range" property, both root ports will enumerate starting from 
> root_bus_nr = 0 and everything will still work ok.

Correct.

Best regards,
Liviu

> 
> So if my assumption is correct, I do not see why the orginal patch from Wang 
> Zhou is wrong. 
> The only point can be that assigning pp->root_bus_nr = 0 is not required 
> as pp memory is kzalloc'ed (an therefore init to zero).
> 
> 
> > 
> > >
> > > In general I agree with you but if you look at all the current
> > drivers
> > > based on designware none of them define the "bus-range" dtb property.
> > > Therefore doing as you say would break the current driver when we
> > have
> > > multiple controllers...am I right?
> > >
> > The current _code_ works fine for multiple controllers. It's just that
> > you must define the bus range property in the DTB if you want to enable
> > multiple instances of one controller and support a kernel without PCI
> > domains support. As all current implementations have only a single
> > instance of the controller per SoC, or depend on PCI domain support,
> > it's totally fine for them to not define the bus ranges property, as
> > it's an optional property and it is well defined how things behave if
> > it
> > is absent. We absolutely need to keep that specified behavior.
> > 
> > > If that is the case in order to fix this in the way you say I would
> > need
> > > to assign "bus-range" for all the PCIe drivers with multiple
> > controllers:
> > > in this case I would split the default range evenly (that is, if we
> > have
> > > two controllers I would define "bus-range"  0-127 and 128-255)
> > >
> > > If you think this solution is ok I can go for it. My only doubt was
> > about
> > > touching other vendors DTBs....
> > >
> > You don't need to touch any of the current DTBs, as they are fine with
> > the default bus range behavior. You need to keep the specified behavior
> > of the bus range property with the new code.
> > 
> > Regards,
> > Lucas
> > >
> > > >
> > > > It is perfectly valid to have a bus range of 0x00-0x10 assigned to
> > one
> > > > instance and 0x50-0xff to the next instance. Additional with PCIe
> > > > hotplug you may not use the full range of the bus numbers on one
> > > > instance at the first scan, but only later populate more buses when
> > > > more
> > > > bridges are added to the tree.
> > > >
> > > > > Drivers that do not specify the bus range in the DTB set pp-
> > > > >root_bus_nr = DW_ROOT_NR_UNDEFINED.
> > > > > Designware will check if the flag is set and will use the
> > automatic
> > > > bus range
> > > > > assignment.
> > > >
> > > > No, please lets get rid of this assignment altogether. The glue
> > drivers
> > > > have no business in assigning the bus range. Please remove the
> > > > pp->root_bus_nr assignment from all the glue drivers.
> > > >
> > > > "bus range" is a generic DW PCIe property, so just parse the root
> > bus
> > > > number from the DT, it is handled the same way for all the DW based
> > > > PCIe
> > > > drivers. The bindings specifies that if the bus range property is
> > > > missing the range is 0x00-0xff, so you can default to 0 as the root
> > bus
> > > > number in that case.
> > > >
> > > > Also I would think this conversion warrants a patch on its own and
> > > > should not be mixed in the ARM64 support patch.
> > > >
> > > > Regards,
> > > > Lucas
> > > >
> > 
> > --
> > Pengutronix e.K.             | Lucas Stach                 |
> > Industrial Linux Solutions   | http://www.pengutronix.de/  |
> 

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

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

* RE: [PATCH v7 3/6] PCI: designware: Add ARM64 support
  2015-08-21 13:42                 ` Liviu Dudau
  (?)
@ 2015-08-21 14:19                   ` Gabriele Paoloni
  -1 siblings, 0 replies; 53+ messages in thread
From: Gabriele Paoloni @ 2015-08-21 14:19 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Lucas Stach, Wangzhou (B),
	Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, Lorenzo Pieralisi, James Morse, jason, robh,
	linux-pci, linux-arm-kernel, devicetree, Yuanzhichang, Zhudacai,
	zhangjukuo, qiuzhenfa

Hi Liviu

Many Thanks for reviewing

> -----Original Message-----
> From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-
> owner@vger.kernel.org] On Behalf Of Liviu Dudau
> Sent: Friday, August 21, 2015 2:43 PM
> To: Gabriele Paoloni
> Cc: Lucas Stach; Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com;
> Pratyush Anand; Arnd Bergmann; linux@arm.linux.org.uk;
> thomas.petazzoni@free-electrons.com; Lorenzo Pieralisi; James Morse;
> jason@lakedaemon.net; robh@kernel.org; linux-pci@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; devicetree@vger.kernel.org;
> Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; liudongdong (C);
> qiujiang; xuwei (O); Liguozhu (Kenneth)
> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> 
> On Thu, Aug 20, 2015 at 12:10:24PM +0100, Gabriele Paoloni wrote:
> > Hi Lucas
> >
> > Again many thanks for explaining and for your time.
> >
> > I got your point now and I have dug a bit better in the PCI_DOMAINS
> code.
> >
> > However I have a question...see inline below
> >
> > > -----Original Message-----
> > > From: Lucas Stach [mailto:l.stach@pengutronix.de]
> > > Sent: Thursday, August 20, 2015 9:27 AM
> > > To: Gabriele Paoloni
> > > Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com; Pratyush
> Anand;
> > > Arnd Bergmann; linux@arm.linux.org.uk; thomas.petazzoni@free-
> > > electrons.com; lorenzo.pieralisi@arm.com; james.morse@arm.com;
> > > Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org; linux-
> > > pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> > > devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> > > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > >
> > > Hi Gab,
> > >
> > > Am Mittwoch, den 19.08.2015, 16:34 +0000 schrieb Gabriele Paoloni:
> > > > Hi Lucas
> > > >
> > > > First of all many thanks for the quick reply, really appreciated
> > > >
> > > > > -----Original Message-----
> > > > > From: Lucas Stach [mailto:l.stach@pengutronix.de]
> > > > > Sent: Wednesday, August 19, 2015 4:37 PM
> > > > > To: Gabriele Paoloni
> > > > > Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com; Pratyush
> > > Anand;
> > > > > Arnd Bergmann; linux@arm.linux.org.uk; thomas.petazzoni@free-
> > > > > electrons.com; lorenzo.pieralisi@arm.com; james.morse@arm.com;
> > > > > Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org;
> linux-
> > > > > pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> > > > > devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > > > > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu
> (Kenneth)
> > > > > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > > > >
> > > > > Hi Gab,
> > > > >
> > > > > Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele
> Paoloni:
> > > > > > Hi Lucas
> > > > > >
> > > > > > I have rewritten the patch to take into account multiple
> > > controllers.
> > > > > >
> > > > > > As you can see now there is a static var in
> dw_pcie_host_init()
> > > that
> > > > > tracks
> > > > > > the bus numbers used.
> > > > >
> > > > > This is wrong. The DT specifies the valid bus number range. You
> can
> > > not
> > > > > just assign the next free bus number to the root bus.
> > > >
> > > > I think this is what is being done in
> > > > http://lxr.free-
> electrons.com/source/arch/arm/kernel/bios32.c#L495
> > > > and currently designware assigns the root bus number in
> > > > http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
> > > designware.c#L730
> > > >
> > > You found the right spot. It works a bit different than I remember,
> but
> > > is less broken than your current code. :)
> > >
> > > It actually assigns the next instance a root bus number behind the
> > > current instances bus range. Please note the difference to your
> code
> > > which assigns the next free bus number, which may still lay within
> the
> > > current instances bus range.
> 
> Hi Gabriele,
> 
> >
> > Mmmm here I have done a mistake: in the current designware the number
> of hw
> > controllers is always 1
> > http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
> designware.c#L510
> > So the loop in bios32.c does not work on multiple PCIe ports...
> 
> Bios32.c is broken for multiple PCIe hosts for multiple reasons, this
> is just
> one of them. Hence the effort to get rid of it for maintained drivers.

As you can see we're pushing hard for this :)

> 
> > However your comment about PCI_DOMAINS enlightened my mind and now I
> see
> > that when CONFIG_PCI_DOMAINS is defined we have the domains numbers
> > (tracked by __domain_nr).
> 
> CONFIG_PCI_DOMAINS in itself doesn't do much without adding code to
> your driver.
> You could request a new domain for each controller with a special
> property to
> disable that behaviour in the dts, or you could enable
> CONFIG_PCI_DOMAINS_GENERIC
> which will give you a new domain automatically.

So far I see that for ARM and ARM64 CONFIG_PCI_DOMAINS_GENERIC defaults to 
the same value as CONFIG_PCI_DOMAINS (see arch/arm/Kconfig, arch/arm64/Kconfig). 
So I think this is how current designware based drivers get multiple PCIe 
controller to work (they just enable CONFIG_PCI_DOMAINS)...

 

> 
> > So (correct me if I am wrong) if we have 2 PCIe ports that do not
> specify
> > the "bus-range" property, both root ports will enumerate starting
> from
> > root_bus_nr = 0 and everything will still work ok.
> 
> Correct.
> 
> Best regards,
> Liviu
> 
> >
> > So if my assumption is correct, I do not see why the orginal patch
> from Wang
> > Zhou is wrong.
> > The only point can be that assigning pp->root_bus_nr = 0 is not
> required
> > as pp memory is kzalloc'ed (an therefore init to zero).
> >
> >
> > >
> > > >
> > > > In general I agree with you but if you look at all the current
> > > drivers
> > > > based on designware none of them define the "bus-range" dtb
> property.
> > > > Therefore doing as you say would break the current driver when we
> > > have
> > > > multiple controllers...am I right?
> > > >
> > > The current _code_ works fine for multiple controllers. It's just
> that
> > > you must define the bus range property in the DTB if you want to
> enable
> > > multiple instances of one controller and support a kernel without
> PCI
> > > domains support. As all current implementations have only a single
> > > instance of the controller per SoC, or depend on PCI domain support,
> > > it's totally fine for them to not define the bus ranges property,
> as
> > > it's an optional property and it is well defined how things behave
> if
> > > it
> > > is absent. We absolutely need to keep that specified behavior.
> > >
> > > > If that is the case in order to fix this in the way you say I
> would
> > > need
> > > > to assign "bus-range" for all the PCIe drivers with multiple
> > > controllers:
> > > > in this case I would split the default range evenly (that is, if
> we
> > > have
> > > > two controllers I would define "bus-range"  0-127 and 128-255)
> > > >
> > > > If you think this solution is ok I can go for it. My only doubt
> was
> > > about
> > > > touching other vendors DTBs....
> > > >
> > > You don't need to touch any of the current DTBs, as they are fine
> with
> > > the default bus range behavior. You need to keep the specified
> behavior
> > > of the bus range property with the new code.
> > >
> > > Regards,
> > > Lucas
> > > >
> > > > >
> > > > > It is perfectly valid to have a bus range of 0x00-0x10 assigned
> to
> > > one
> > > > > instance and 0x50-0xff to the next instance. Additional with
> PCIe
> > > > > hotplug you may not use the full range of the bus numbers on
> one
> > > > > instance at the first scan, but only later populate more buses
> when
> > > > > more
> > > > > bridges are added to the tree.
> > > > >
> > > > > > Drivers that do not specify the bus range in the DTB set pp-
> > > > > >root_bus_nr = DW_ROOT_NR_UNDEFINED.
> > > > > > Designware will check if the flag is set and will use the
> > > automatic
> > > > > bus range
> > > > > > assignment.
> > > > >
> > > > > No, please lets get rid of this assignment altogether. The glue
> > > drivers
> > > > > have no business in assigning the bus range. Please remove the
> > > > > pp->root_bus_nr assignment from all the glue drivers.
> > > > >
> > > > > "bus range" is a generic DW PCIe property, so just parse the
> root
> > > bus
> > > > > number from the DT, it is handled the same way for all the DW
> based
> > > > > PCIe
> > > > > drivers. The bindings specifies that if the bus range property
> is
> > > > > missing the range is 0x00-0xff, so you can default to 0 as the
> root
> > > bus
> > > > > number in that case.
> > > > >
> > > > > Also I would think this conversion warrants a patch on its own
> and
> > > > > should not be mixed in the ARM64 support patch.
> > > > >
> > > > > Regards,
> > > > > Lucas
> > > > >
> > >
> > > --
> > > Pengutronix e.K.             | Lucas Stach                 |
> > > Industrial Linux Solutions   | http://www.pengutronix.de/  |
> >
> 
> --
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ¯\_(ツ)_/¯
> 
> --
> 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

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

* RE: [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-21 14:19                   ` Gabriele Paoloni
  0 siblings, 0 replies; 53+ messages in thread
From: Gabriele Paoloni @ 2015-08-21 14:19 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Lucas Stach, Wangzhou (B),
	Bjorn Helgaas, jingoohan1, Pratyush Anand, Arnd Bergmann, linux,
	thomas.petazzoni, Lorenzo Pieralisi, James Morse, jason, robh,
	linux-pci, linux-arm-kernel, devicetree, Yuanzhichang, Zhudacai,
	zhangjukuo, qiuzhenfa, liudongdong (C), qiujiang, xuwei (O),
	Liguozhu (Kenneth)

SGkgTGl2aXUNCg0KTWFueSBUaGFua3MgZm9yIHJldmlld2luZw0KDQo+IC0tLS0tT3JpZ2luYWwg
TWVzc2FnZS0tLS0tDQo+IEZyb206IGxpbnV4LXBjaS1vd25lckB2Z2VyLmtlcm5lbC5vcmcgW21h
aWx0bzpsaW51eC1wY2ktDQo+IG93bmVyQHZnZXIua2VybmVsLm9yZ10gT24gQmVoYWxmIE9mIExp
dml1IER1ZGF1DQo+IFNlbnQ6IEZyaWRheSwgQXVndXN0IDIxLCAyMDE1IDI6NDMgUE0NCj4gVG86
IEdhYnJpZWxlIFBhb2xvbmkNCj4gQ2M6IEx1Y2FzIFN0YWNoOyBXYW5nemhvdSAoQik7IEJqb3Ju
IEhlbGdhYXM7IGppbmdvb2hhbjFAZ21haWwuY29tOw0KPiBQcmF0eXVzaCBBbmFuZDsgQXJuZCBC
ZXJnbWFubjsgbGludXhAYXJtLmxpbnV4Lm9yZy51azsNCj4gdGhvbWFzLnBldGF6em9uaUBmcmVl
LWVsZWN0cm9ucy5jb207IExvcmVuem8gUGllcmFsaXNpOyBKYW1lcyBNb3JzZTsNCj4gamFzb25A
bGFrZWRhZW1vbi5uZXQ7IHJvYmhAa2VybmVsLm9yZzsgbGludXgtcGNpQHZnZXIua2VybmVsLm9y
ZzsNCj4gbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnOyBkZXZpY2V0cmVlQHZn
ZXIua2VybmVsLm9yZzsNCj4gWXVhbnpoaWNoYW5nOyBaaHVkYWNhaTsgemhhbmdqdWt1bzsgcWl1
emhlbmZhOyBsaXVkb25nZG9uZyAoQyk7DQo+IHFpdWppYW5nOyB4dXdlaSAoTyk7IExpZ3Vvemh1
IChLZW5uZXRoKQ0KPiBTdWJqZWN0OiBSZTogW1BBVENIIHY3IDMvNl0gUENJOiBkZXNpZ253YXJl
OiBBZGQgQVJNNjQgc3VwcG9ydA0KPiANCj4gT24gVGh1LCBBdWcgMjAsIDIwMTUgYXQgMTI6MTA6
MjRQTSArMDEwMCwgR2FicmllbGUgUGFvbG9uaSB3cm90ZToNCj4gPiBIaSBMdWNhcw0KPiA+DQo+
ID4gQWdhaW4gbWFueSB0aGFua3MgZm9yIGV4cGxhaW5pbmcgYW5kIGZvciB5b3VyIHRpbWUuDQo+
ID4NCj4gPiBJIGdvdCB5b3VyIHBvaW50IG5vdyBhbmQgSSBoYXZlIGR1ZyBhIGJpdCBiZXR0ZXIg
aW4gdGhlIFBDSV9ET01BSU5TDQo+IGNvZGUuDQo+ID4NCj4gPiBIb3dldmVyIEkgaGF2ZSBhIHF1
ZXN0aW9uLi4uc2VlIGlubGluZSBiZWxvdw0KPiA+DQo+ID4gPiAtLS0tLU9yaWdpbmFsIE1lc3Nh
Z2UtLS0tLQ0KPiA+ID4gRnJvbTogTHVjYXMgU3RhY2ggW21haWx0bzpsLnN0YWNoQHBlbmd1dHJv
bml4LmRlXQ0KPiA+ID4gU2VudDogVGh1cnNkYXksIEF1Z3VzdCAyMCwgMjAxNSA5OjI3IEFNDQo+
ID4gPiBUbzogR2FicmllbGUgUGFvbG9uaQ0KPiA+ID4gQ2M6IFdhbmd6aG91IChCKTsgQmpvcm4g
SGVsZ2FhczsgamluZ29vaGFuMUBnbWFpbC5jb207IFByYXR5dXNoDQo+IEFuYW5kOw0KPiA+ID4g
QXJuZCBCZXJnbWFubjsgbGludXhAYXJtLmxpbnV4Lm9yZy51azsgdGhvbWFzLnBldGF6em9uaUBm
cmVlLQ0KPiA+ID4gZWxlY3Ryb25zLmNvbTsgbG9yZW56by5waWVyYWxpc2lAYXJtLmNvbTsgamFt
ZXMubW9yc2VAYXJtLmNvbTsNCj4gPiA+IExpdml1LkR1ZGF1QGFybS5jb207IGphc29uQGxha2Vk
YWVtb24ubmV0OyByb2JoQGtlcm5lbC5vcmc7IGxpbnV4LQ0KPiA+ID4gcGNpQHZnZXIua2VybmVs
Lm9yZzsgbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnOw0KPiA+ID4gZGV2aWNl
dHJlZUB2Z2VyLmtlcm5lbC5vcmc7IFl1YW56aGljaGFuZzsgWmh1ZGFjYWk7IHpoYW5nanVrdW87
DQo+ID4gPiBxaXV6aGVuZmE7IGxpdWRvbmdkb25nIChDKTsgcWl1amlhbmc7IHh1d2VpIChPKTsg
TGlndW96aHUgKEtlbm5ldGgpDQo+ID4gPiBTdWJqZWN0OiBSZTogW1BBVENIIHY3IDMvNl0gUENJ
OiBkZXNpZ253YXJlOiBBZGQgQVJNNjQgc3VwcG9ydA0KPiA+ID4NCj4gPiA+IEhpIEdhYiwNCj4g
PiA+DQo+ID4gPiBBbSBNaXR0d29jaCwgZGVuIDE5LjA4LjIwMTUsIDE2OjM0ICswMDAwIHNjaHJp
ZWIgR2FicmllbGUgUGFvbG9uaToNCj4gPiA+ID4gSGkgTHVjYXMNCj4gPiA+ID4NCj4gPiA+ID4g
Rmlyc3Qgb2YgYWxsIG1hbnkgdGhhbmtzIGZvciB0aGUgcXVpY2sgcmVwbHksIHJlYWxseSBhcHBy
ZWNpYXRlZA0KPiA+ID4gPg0KPiA+ID4gPiA+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+
ID4gPiA+ID4gRnJvbTogTHVjYXMgU3RhY2ggW21haWx0bzpsLnN0YWNoQHBlbmd1dHJvbml4LmRl
XQ0KPiA+ID4gPiA+IFNlbnQ6IFdlZG5lc2RheSwgQXVndXN0IDE5LCAyMDE1IDQ6MzcgUE0NCj4g
PiA+ID4gPiBUbzogR2FicmllbGUgUGFvbG9uaQ0KPiA+ID4gPiA+IENjOiBXYW5nemhvdSAoQik7
IEJqb3JuIEhlbGdhYXM7IGppbmdvb2hhbjFAZ21haWwuY29tOyBQcmF0eXVzaA0KPiA+ID4gQW5h
bmQ7DQo+ID4gPiA+ID4gQXJuZCBCZXJnbWFubjsgbGludXhAYXJtLmxpbnV4Lm9yZy51azsgdGhv
bWFzLnBldGF6em9uaUBmcmVlLQ0KPiA+ID4gPiA+IGVsZWN0cm9ucy5jb207IGxvcmVuem8ucGll
cmFsaXNpQGFybS5jb207IGphbWVzLm1vcnNlQGFybS5jb207DQo+ID4gPiA+ID4gTGl2aXUuRHVk
YXVAYXJtLmNvbTsgamFzb25AbGFrZWRhZW1vbi5uZXQ7IHJvYmhAa2VybmVsLm9yZzsNCj4gbGlu
dXgtDQo+ID4gPiA+ID4gcGNpQHZnZXIua2VybmVsLm9yZzsgbGludXgtYXJtLWtlcm5lbEBsaXN0
cy5pbmZyYWRlYWQub3JnOw0KPiA+ID4gPiA+IGRldmljZXRyZWVAdmdlci5rZXJuZWwub3JnOyBZ
dWFuemhpY2hhbmc7IFpodWRhY2FpOyB6aGFuZ2p1a3VvOw0KPiA+ID4gPiA+IHFpdXpoZW5mYTsg
bGl1ZG9uZ2RvbmcgKEMpOyBxaXVqaWFuZzsgeHV3ZWkgKE8pOyBMaWd1b3podQ0KPiAoS2VubmV0
aCkNCj4gPiA+ID4gPiBTdWJqZWN0OiBSZTogW1BBVENIIHY3IDMvNl0gUENJOiBkZXNpZ253YXJl
OiBBZGQgQVJNNjQgc3VwcG9ydA0KPiA+ID4gPiA+DQo+ID4gPiA+ID4gSGkgR2FiLA0KPiA+ID4g
PiA+DQo+ID4gPiA+ID4gQW0gTWl0dHdvY2gsIGRlbiAxOS4wOC4yMDE1LCAxNToxNiArMDAwMCBz
Y2hyaWViIEdhYnJpZWxlDQo+IFBhb2xvbmk6DQo+ID4gPiA+ID4gPiBIaSBMdWNhcw0KPiA+ID4g
PiA+ID4NCj4gPiA+ID4gPiA+IEkgaGF2ZSByZXdyaXR0ZW4gdGhlIHBhdGNoIHRvIHRha2UgaW50
byBhY2NvdW50IG11bHRpcGxlDQo+ID4gPiBjb250cm9sbGVycy4NCj4gPiA+ID4gPiA+DQo+ID4g
PiA+ID4gPiBBcyB5b3UgY2FuIHNlZSBub3cgdGhlcmUgaXMgYSBzdGF0aWMgdmFyIGluDQo+IGR3
X3BjaWVfaG9zdF9pbml0KCkNCj4gPiA+IHRoYXQNCj4gPiA+ID4gPiB0cmFja3MNCj4gPiA+ID4g
PiA+IHRoZSBidXMgbnVtYmVycyB1c2VkLg0KPiA+ID4gPiA+DQo+ID4gPiA+ID4gVGhpcyBpcyB3
cm9uZy4gVGhlIERUIHNwZWNpZmllcyB0aGUgdmFsaWQgYnVzIG51bWJlciByYW5nZS4gWW91DQo+
IGNhbg0KPiA+ID4gbm90DQo+ID4gPiA+ID4ganVzdCBhc3NpZ24gdGhlIG5leHQgZnJlZSBidXMg
bnVtYmVyIHRvIHRoZSByb290IGJ1cy4NCj4gPiA+ID4NCj4gPiA+ID4gSSB0aGluayB0aGlzIGlz
IHdoYXQgaXMgYmVpbmcgZG9uZSBpbg0KPiA+ID4gPiBodHRwOi8vbHhyLmZyZWUtDQo+IGVsZWN0
cm9ucy5jb20vc291cmNlL2FyY2gvYXJtL2tlcm5lbC9iaW9zMzIuYyNMNDk1DQo+ID4gPiA+IGFu
ZCBjdXJyZW50bHkgZGVzaWdud2FyZSBhc3NpZ25zIHRoZSByb290IGJ1cyBudW1iZXIgaW4NCj4g
PiA+ID4gaHR0cDovL2x4ci5mcmVlLWVsZWN0cm9ucy5jb20vc291cmNlL2RyaXZlcnMvcGNpL2hv
c3QvcGNpZS0NCj4gPiA+IGRlc2lnbndhcmUuYyNMNzMwDQo+ID4gPiA+DQo+ID4gPiBZb3UgZm91
bmQgdGhlIHJpZ2h0IHNwb3QuIEl0IHdvcmtzIGEgYml0IGRpZmZlcmVudCB0aGFuIEkgcmVtZW1i
ZXIsDQo+IGJ1dA0KPiA+ID4gaXMgbGVzcyBicm9rZW4gdGhhbiB5b3VyIGN1cnJlbnQgY29kZS4g
OikNCj4gPiA+DQo+ID4gPiBJdCBhY3R1YWxseSBhc3NpZ25zIHRoZSBuZXh0IGluc3RhbmNlIGEg
cm9vdCBidXMgbnVtYmVyIGJlaGluZCB0aGUNCj4gPiA+IGN1cnJlbnQgaW5zdGFuY2VzIGJ1cyBy
YW5nZS4gUGxlYXNlIG5vdGUgdGhlIGRpZmZlcmVuY2UgdG8geW91cg0KPiBjb2RlDQo+ID4gPiB3
aGljaCBhc3NpZ25zIHRoZSBuZXh0IGZyZWUgYnVzIG51bWJlciwgd2hpY2ggbWF5IHN0aWxsIGxh
eSB3aXRoaW4NCj4gdGhlDQo+ID4gPiBjdXJyZW50IGluc3RhbmNlcyBidXMgcmFuZ2UuDQo+IA0K
PiBIaSBHYWJyaWVsZSwNCj4gDQo+ID4NCj4gPiBNbW1tIGhlcmUgSSBoYXZlIGRvbmUgYSBtaXN0
YWtlOiBpbiB0aGUgY3VycmVudCBkZXNpZ253YXJlIHRoZSBudW1iZXINCj4gb2YgaHcNCj4gPiBj
b250cm9sbGVycyBpcyBhbHdheXMgMQ0KPiA+IGh0dHA6Ly9seHIuZnJlZS1lbGVjdHJvbnMuY29t
L3NvdXJjZS9kcml2ZXJzL3BjaS9ob3N0L3BjaWUtDQo+IGRlc2lnbndhcmUuYyNMNTEwDQo+ID4g
U28gdGhlIGxvb3AgaW4gYmlvczMyLmMgZG9lcyBub3Qgd29yayBvbiBtdWx0aXBsZSBQQ0llIHBv
cnRzLi4uDQo+IA0KPiBCaW9zMzIuYyBpcyBicm9rZW4gZm9yIG11bHRpcGxlIFBDSWUgaG9zdHMg
Zm9yIG11bHRpcGxlIHJlYXNvbnMsIHRoaXMNCj4gaXMganVzdA0KPiBvbmUgb2YgdGhlbS4gSGVu
Y2UgdGhlIGVmZm9ydCB0byBnZXQgcmlkIG9mIGl0IGZvciBtYWludGFpbmVkIGRyaXZlcnMuDQoN
CkFzIHlvdSBjYW4gc2VlIHdlJ3JlIHB1c2hpbmcgaGFyZCBmb3IgdGhpcyA6KQ0KDQo+IA0KPiA+
IEhvd2V2ZXIgeW91ciBjb21tZW50IGFib3V0IFBDSV9ET01BSU5TIGVubGlnaHRlbmVkIG15IG1p
bmQgYW5kIG5vdyBJDQo+IHNlZQ0KPiA+IHRoYXQgd2hlbiBDT05GSUdfUENJX0RPTUFJTlMgaXMg
ZGVmaW5lZCB3ZSBoYXZlIHRoZSBkb21haW5zIG51bWJlcnMNCj4gPiAodHJhY2tlZCBieSBfX2Rv
bWFpbl9ucikuDQo+IA0KPiBDT05GSUdfUENJX0RPTUFJTlMgaW4gaXRzZWxmIGRvZXNuJ3QgZG8g
bXVjaCB3aXRob3V0IGFkZGluZyBjb2RlIHRvDQo+IHlvdXIgZHJpdmVyLg0KPiBZb3UgY291bGQg
cmVxdWVzdCBhIG5ldyBkb21haW4gZm9yIGVhY2ggY29udHJvbGxlciB3aXRoIGEgc3BlY2lhbA0K
PiBwcm9wZXJ0eSB0bw0KPiBkaXNhYmxlIHRoYXQgYmVoYXZpb3VyIGluIHRoZSBkdHMsIG9yIHlv
dSBjb3VsZCBlbmFibGUNCj4gQ09ORklHX1BDSV9ET01BSU5TX0dFTkVSSUMNCj4gd2hpY2ggd2ls
bCBnaXZlIHlvdSBhIG5ldyBkb21haW4gYXV0b21hdGljYWxseS4NCg0KU28gZmFyIEkgc2VlIHRo
YXQgZm9yIEFSTSBhbmQgQVJNNjQgQ09ORklHX1BDSV9ET01BSU5TX0dFTkVSSUMgZGVmYXVsdHMg
dG8gDQp0aGUgc2FtZSB2YWx1ZSBhcyBDT05GSUdfUENJX0RPTUFJTlMgKHNlZSBhcmNoL2FybS9L
Y29uZmlnLCBhcmNoL2FybTY0L0tjb25maWcpLiANClNvIEkgdGhpbmsgdGhpcyBpcyBob3cgY3Vy
cmVudCBkZXNpZ253YXJlIGJhc2VkIGRyaXZlcnMgZ2V0IG11bHRpcGxlIFBDSWUgDQpjb250cm9s
bGVyIHRvIHdvcmsgKHRoZXkganVzdCBlbmFibGUgQ09ORklHX1BDSV9ET01BSU5TKS4uLg0KDQog
DQoNCj4gDQo+ID4gU28gKGNvcnJlY3QgbWUgaWYgSSBhbSB3cm9uZykgaWYgd2UgaGF2ZSAyIFBD
SWUgcG9ydHMgdGhhdCBkbyBub3QNCj4gc3BlY2lmeQ0KPiA+IHRoZSAiYnVzLXJhbmdlIiBwcm9w
ZXJ0eSwgYm90aCByb290IHBvcnRzIHdpbGwgZW51bWVyYXRlIHN0YXJ0aW5nDQo+IGZyb20NCj4g
PiByb290X2J1c19uciA9IDAgYW5kIGV2ZXJ5dGhpbmcgd2lsbCBzdGlsbCB3b3JrIG9rLg0KPiAN
Cj4gQ29ycmVjdC4NCj4gDQo+IEJlc3QgcmVnYXJkcywNCj4gTGl2aXUNCj4gDQo+ID4NCj4gPiBT
byBpZiBteSBhc3N1bXB0aW9uIGlzIGNvcnJlY3QsIEkgZG8gbm90IHNlZSB3aHkgdGhlIG9yZ2lu
YWwgcGF0Y2gNCj4gZnJvbSBXYW5nDQo+ID4gWmhvdSBpcyB3cm9uZy4NCj4gPiBUaGUgb25seSBw
b2ludCBjYW4gYmUgdGhhdCBhc3NpZ25pbmcgcHAtPnJvb3RfYnVzX25yID0gMCBpcyBub3QNCj4g
cmVxdWlyZWQNCj4gPiBhcyBwcCBtZW1vcnkgaXMga3phbGxvYydlZCAoYW4gdGhlcmVmb3JlIGlu
aXQgdG8gemVybykuDQo+ID4NCj4gPg0KPiA+ID4NCj4gPiA+ID4NCj4gPiA+ID4gSW4gZ2VuZXJh
bCBJIGFncmVlIHdpdGggeW91IGJ1dCBpZiB5b3UgbG9vayBhdCBhbGwgdGhlIGN1cnJlbnQNCj4g
PiA+IGRyaXZlcnMNCj4gPiA+ID4gYmFzZWQgb24gZGVzaWdud2FyZSBub25lIG9mIHRoZW0gZGVm
aW5lIHRoZSAiYnVzLXJhbmdlIiBkdGINCj4gcHJvcGVydHkuDQo+ID4gPiA+IFRoZXJlZm9yZSBk
b2luZyBhcyB5b3Ugc2F5IHdvdWxkIGJyZWFrIHRoZSBjdXJyZW50IGRyaXZlciB3aGVuIHdlDQo+
ID4gPiBoYXZlDQo+ID4gPiA+IG11bHRpcGxlIGNvbnRyb2xsZXJzLi4uYW0gSSByaWdodD8NCj4g
PiA+ID4NCj4gPiA+IFRoZSBjdXJyZW50IF9jb2RlXyB3b3JrcyBmaW5lIGZvciBtdWx0aXBsZSBj
b250cm9sbGVycy4gSXQncyBqdXN0DQo+IHRoYXQNCj4gPiA+IHlvdSBtdXN0IGRlZmluZSB0aGUg
YnVzIHJhbmdlIHByb3BlcnR5IGluIHRoZSBEVEIgaWYgeW91IHdhbnQgdG8NCj4gZW5hYmxlDQo+
ID4gPiBtdWx0aXBsZSBpbnN0YW5jZXMgb2Ygb25lIGNvbnRyb2xsZXIgYW5kIHN1cHBvcnQgYSBr
ZXJuZWwgd2l0aG91dA0KPiBQQ0kNCj4gPiA+IGRvbWFpbnMgc3VwcG9ydC4gQXMgYWxsIGN1cnJl
bnQgaW1wbGVtZW50YXRpb25zIGhhdmUgb25seSBhIHNpbmdsZQ0KPiA+ID4gaW5zdGFuY2Ugb2Yg
dGhlIGNvbnRyb2xsZXIgcGVyIFNvQywgb3IgZGVwZW5kIG9uIFBDSSBkb21haW4gc3VwcG9ydCwN
Cj4gPiA+IGl0J3MgdG90YWxseSBmaW5lIGZvciB0aGVtIHRvIG5vdCBkZWZpbmUgdGhlIGJ1cyBy
YW5nZXMgcHJvcGVydHksDQo+IGFzDQo+ID4gPiBpdCdzIGFuIG9wdGlvbmFsIHByb3BlcnR5IGFu
ZCBpdCBpcyB3ZWxsIGRlZmluZWQgaG93IHRoaW5ncyBiZWhhdmUNCj4gaWYNCj4gPiA+IGl0DQo+
ID4gPiBpcyBhYnNlbnQuIFdlIGFic29sdXRlbHkgbmVlZCB0byBrZWVwIHRoYXQgc3BlY2lmaWVk
IGJlaGF2aW9yLg0KPiA+ID4NCj4gPiA+ID4gSWYgdGhhdCBpcyB0aGUgY2FzZSBpbiBvcmRlciB0
byBmaXggdGhpcyBpbiB0aGUgd2F5IHlvdSBzYXkgSQ0KPiB3b3VsZA0KPiA+ID4gbmVlZA0KPiA+
ID4gPiB0byBhc3NpZ24gImJ1cy1yYW5nZSIgZm9yIGFsbCB0aGUgUENJZSBkcml2ZXJzIHdpdGgg
bXVsdGlwbGUNCj4gPiA+IGNvbnRyb2xsZXJzOg0KPiA+ID4gPiBpbiB0aGlzIGNhc2UgSSB3b3Vs
ZCBzcGxpdCB0aGUgZGVmYXVsdCByYW5nZSBldmVubHkgKHRoYXQgaXMsIGlmDQo+IHdlDQo+ID4g
PiBoYXZlDQo+ID4gPiA+IHR3byBjb250cm9sbGVycyBJIHdvdWxkIGRlZmluZSAiYnVzLXJhbmdl
IiAgMC0xMjcgYW5kIDEyOC0yNTUpDQo+ID4gPiA+DQo+ID4gPiA+IElmIHlvdSB0aGluayB0aGlz
IHNvbHV0aW9uIGlzIG9rIEkgY2FuIGdvIGZvciBpdC4gTXkgb25seSBkb3VidA0KPiB3YXMNCj4g
PiA+IGFib3V0DQo+ID4gPiA+IHRvdWNoaW5nIG90aGVyIHZlbmRvcnMgRFRCcy4uLi4NCj4gPiA+
ID4NCj4gPiA+IFlvdSBkb24ndCBuZWVkIHRvIHRvdWNoIGFueSBvZiB0aGUgY3VycmVudCBEVEJz
LCBhcyB0aGV5IGFyZSBmaW5lDQo+IHdpdGgNCj4gPiA+IHRoZSBkZWZhdWx0IGJ1cyByYW5nZSBi
ZWhhdmlvci4gWW91IG5lZWQgdG8ga2VlcCB0aGUgc3BlY2lmaWVkDQo+IGJlaGF2aW9yDQo+ID4g
PiBvZiB0aGUgYnVzIHJhbmdlIHByb3BlcnR5IHdpdGggdGhlIG5ldyBjb2RlLg0KPiA+ID4NCj4g
PiA+IFJlZ2FyZHMsDQo+ID4gPiBMdWNhcw0KPiA+ID4gPg0KPiA+ID4gPiA+DQo+ID4gPiA+ID4g
SXQgaXMgcGVyZmVjdGx5IHZhbGlkIHRvIGhhdmUgYSBidXMgcmFuZ2Ugb2YgMHgwMC0weDEwIGFz
c2lnbmVkDQo+IHRvDQo+ID4gPiBvbmUNCj4gPiA+ID4gPiBpbnN0YW5jZSBhbmQgMHg1MC0weGZm
IHRvIHRoZSBuZXh0IGluc3RhbmNlLiBBZGRpdGlvbmFsIHdpdGgNCj4gUENJZQ0KPiA+ID4gPiA+
IGhvdHBsdWcgeW91IG1heSBub3QgdXNlIHRoZSBmdWxsIHJhbmdlIG9mIHRoZSBidXMgbnVtYmVy
cyBvbg0KPiBvbmUNCj4gPiA+ID4gPiBpbnN0YW5jZSBhdCB0aGUgZmlyc3Qgc2NhbiwgYnV0IG9u
bHkgbGF0ZXIgcG9wdWxhdGUgbW9yZSBidXNlcw0KPiB3aGVuDQo+ID4gPiA+ID4gbW9yZQ0KPiA+
ID4gPiA+IGJyaWRnZXMgYXJlIGFkZGVkIHRvIHRoZSB0cmVlLg0KPiA+ID4gPiA+DQo+ID4gPiA+
ID4gPiBEcml2ZXJzIHRoYXQgZG8gbm90IHNwZWNpZnkgdGhlIGJ1cyByYW5nZSBpbiB0aGUgRFRC
IHNldCBwcC0NCj4gPiA+ID4gPiA+cm9vdF9idXNfbnIgPSBEV19ST09UX05SX1VOREVGSU5FRC4N
Cj4gPiA+ID4gPiA+IERlc2lnbndhcmUgd2lsbCBjaGVjayBpZiB0aGUgZmxhZyBpcyBzZXQgYW5k
IHdpbGwgdXNlIHRoZQ0KPiA+ID4gYXV0b21hdGljDQo+ID4gPiA+ID4gYnVzIHJhbmdlDQo+ID4g
PiA+ID4gPiBhc3NpZ25tZW50Lg0KPiA+ID4gPiA+DQo+ID4gPiA+ID4gTm8sIHBsZWFzZSBsZXRz
IGdldCByaWQgb2YgdGhpcyBhc3NpZ25tZW50IGFsdG9nZXRoZXIuIFRoZSBnbHVlDQo+ID4gPiBk
cml2ZXJzDQo+ID4gPiA+ID4gaGF2ZSBubyBidXNpbmVzcyBpbiBhc3NpZ25pbmcgdGhlIGJ1cyBy
YW5nZS4gUGxlYXNlIHJlbW92ZSB0aGUNCj4gPiA+ID4gPiBwcC0+cm9vdF9idXNfbnIgYXNzaWdu
bWVudCBmcm9tIGFsbCB0aGUgZ2x1ZSBkcml2ZXJzLg0KPiA+ID4gPiA+DQo+ID4gPiA+ID4gImJ1
cyByYW5nZSIgaXMgYSBnZW5lcmljIERXIFBDSWUgcHJvcGVydHksIHNvIGp1c3QgcGFyc2UgdGhl
DQo+IHJvb3QNCj4gPiA+IGJ1cw0KPiA+ID4gPiA+IG51bWJlciBmcm9tIHRoZSBEVCwgaXQgaXMg
aGFuZGxlZCB0aGUgc2FtZSB3YXkgZm9yIGFsbCB0aGUgRFcNCj4gYmFzZWQNCj4gPiA+ID4gPiBQ
Q0llDQo+ID4gPiA+ID4gZHJpdmVycy4gVGhlIGJpbmRpbmdzIHNwZWNpZmllcyB0aGF0IGlmIHRo
ZSBidXMgcmFuZ2UgcHJvcGVydHkNCj4gaXMNCj4gPiA+ID4gPiBtaXNzaW5nIHRoZSByYW5nZSBp
cyAweDAwLTB4ZmYsIHNvIHlvdSBjYW4gZGVmYXVsdCB0byAwIGFzIHRoZQ0KPiByb290DQo+ID4g
PiBidXMNCj4gPiA+ID4gPiBudW1iZXIgaW4gdGhhdCBjYXNlLg0KPiA+ID4gPiA+DQo+ID4gPiA+
ID4gQWxzbyBJIHdvdWxkIHRoaW5rIHRoaXMgY29udmVyc2lvbiB3YXJyYW50cyBhIHBhdGNoIG9u
IGl0cyBvd24NCj4gYW5kDQo+ID4gPiA+ID4gc2hvdWxkIG5vdCBiZSBtaXhlZCBpbiB0aGUgQVJN
NjQgc3VwcG9ydCBwYXRjaC4NCj4gPiA+ID4gPg0KPiA+ID4gPiA+IFJlZ2FyZHMsDQo+ID4gPiA+
ID4gTHVjYXMNCj4gPiA+ID4gPg0KPiA+ID4NCj4gPiA+IC0tDQo+ID4gPiBQZW5ndXRyb25peCBl
LksuICAgICAgICAgICAgIHwgTHVjYXMgU3RhY2ggICAgICAgICAgICAgICAgIHwNCj4gPiA+IElu
ZHVzdHJpYWwgTGludXggU29sdXRpb25zICAgfCBodHRwOi8vd3d3LnBlbmd1dHJvbml4LmRlLyAg
fA0KPiA+DQo+IA0KPiAtLQ0KPiA9PT09PT09PT09PT09PT09PT09PQ0KPiB8IEkgd291bGQgbGlr
ZSB0byB8DQo+IHwgZml4IHRoZSB3b3JsZCwgIHwNCj4gfCBidXQgdGhleSdyZSBub3QgfA0KPiB8
IGdpdmluZyBtZSB0aGUgICB8DQo+ICBcIHNvdXJjZSBjb2RlISAgLw0KPiAgIC0tLS0tLS0tLS0t
LS0tLQ0KPiAgICAgwq9cXyjjg4QpXy/Crw0KPiANCj4gLS0NCj4gVG8gdW5zdWJzY3JpYmUgZnJv
bSB0aGlzIGxpc3Q6IHNlbmQgdGhlIGxpbmUgInVuc3Vic2NyaWJlIGxpbnV4LXBjaSIgaW4NCj4g
dGhlIGJvZHkgb2YgYSBtZXNzYWdlIHRvIG1ham9yZG9tb0B2Z2VyLmtlcm5lbC5vcmcNCj4gTW9y
ZSBtYWpvcmRvbW8gaW5mbyBhdCAgaHR0cDovL3ZnZXIua2VybmVsLm9yZy9tYWpvcmRvbW8taW5m
by5odG1sDQo=

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

* [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-21 14:19                   ` Gabriele Paoloni
  0 siblings, 0 replies; 53+ messages in thread
From: Gabriele Paoloni @ 2015-08-21 14:19 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Liviu

Many Thanks for reviewing

> -----Original Message-----
> From: linux-pci-owner at vger.kernel.org [mailto:linux-pci-
> owner at vger.kernel.org] On Behalf Of Liviu Dudau
> Sent: Friday, August 21, 2015 2:43 PM
> To: Gabriele Paoloni
> Cc: Lucas Stach; Wangzhou (B); Bjorn Helgaas; jingoohan1 at gmail.com;
> Pratyush Anand; Arnd Bergmann; linux at arm.linux.org.uk;
> thomas.petazzoni at free-electrons.com; Lorenzo Pieralisi; James Morse;
> jason at lakedaemon.net; robh at kernel.org; linux-pci at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.org;
> Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; liudongdong (C);
> qiujiang; xuwei (O); Liguozhu (Kenneth)
> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> 
> On Thu, Aug 20, 2015 at 12:10:24PM +0100, Gabriele Paoloni wrote:
> > Hi Lucas
> >
> > Again many thanks for explaining and for your time.
> >
> > I got your point now and I have dug a bit better in the PCI_DOMAINS
> code.
> >
> > However I have a question...see inline below
> >
> > > -----Original Message-----
> > > From: Lucas Stach [mailto:l.stach at pengutronix.de]
> > > Sent: Thursday, August 20, 2015 9:27 AM
> > > To: Gabriele Paoloni
> > > Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1 at gmail.com; Pratyush
> Anand;
> > > Arnd Bergmann; linux at arm.linux.org.uk; thomas.petazzoni at free-
> > > electrons.com; lorenzo.pieralisi at arm.com; james.morse at arm.com;
> > > Liviu.Dudau at arm.com; jason at lakedaemon.net; robh at kernel.org; linux-
> > > pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> > > devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> > > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > >
> > > Hi Gab,
> > >
> > > Am Mittwoch, den 19.08.2015, 16:34 +0000 schrieb Gabriele Paoloni:
> > > > Hi Lucas
> > > >
> > > > First of all many thanks for the quick reply, really appreciated
> > > >
> > > > > -----Original Message-----
> > > > > From: Lucas Stach [mailto:l.stach at pengutronix.de]
> > > > > Sent: Wednesday, August 19, 2015 4:37 PM
> > > > > To: Gabriele Paoloni
> > > > > Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1 at gmail.com; Pratyush
> > > Anand;
> > > > > Arnd Bergmann; linux at arm.linux.org.uk; thomas.petazzoni at free-
> > > > > electrons.com; lorenzo.pieralisi at arm.com; james.morse at arm.com;
> > > > > Liviu.Dudau at arm.com; jason at lakedaemon.net; robh at kernel.org;
> linux-
> > > > > pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> > > > > devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> > > > > qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu
> (Kenneth)
> > > > > Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> > > > >
> > > > > Hi Gab,
> > > > >
> > > > > Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele
> Paoloni:
> > > > > > Hi Lucas
> > > > > >
> > > > > > I have rewritten the patch to take into account multiple
> > > controllers.
> > > > > >
> > > > > > As you can see now there is a static var in
> dw_pcie_host_init()
> > > that
> > > > > tracks
> > > > > > the bus numbers used.
> > > > >
> > > > > This is wrong. The DT specifies the valid bus number range. You
> can
> > > not
> > > > > just assign the next free bus number to the root bus.
> > > >
> > > > I think this is what is being done in
> > > > http://lxr.free-
> electrons.com/source/arch/arm/kernel/bios32.c#L495
> > > > and currently designware assigns the root bus number in
> > > > http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
> > > designware.c#L730
> > > >
> > > You found the right spot. It works a bit different than I remember,
> but
> > > is less broken than your current code. :)
> > >
> > > It actually assigns the next instance a root bus number behind the
> > > current instances bus range. Please note the difference to your
> code
> > > which assigns the next free bus number, which may still lay within
> the
> > > current instances bus range.
> 
> Hi Gabriele,
> 
> >
> > Mmmm here I have done a mistake: in the current designware the number
> of hw
> > controllers is always 1
> > http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
> designware.c#L510
> > So the loop in bios32.c does not work on multiple PCIe ports...
> 
> Bios32.c is broken for multiple PCIe hosts for multiple reasons, this
> is just
> one of them. Hence the effort to get rid of it for maintained drivers.

As you can see we're pushing hard for this :)

> 
> > However your comment about PCI_DOMAINS enlightened my mind and now I
> see
> > that when CONFIG_PCI_DOMAINS is defined we have the domains numbers
> > (tracked by __domain_nr).
> 
> CONFIG_PCI_DOMAINS in itself doesn't do much without adding code to
> your driver.
> You could request a new domain for each controller with a special
> property to
> disable that behaviour in the dts, or you could enable
> CONFIG_PCI_DOMAINS_GENERIC
> which will give you a new domain automatically.

So far I see that for ARM and ARM64 CONFIG_PCI_DOMAINS_GENERIC defaults to 
the same value as CONFIG_PCI_DOMAINS (see arch/arm/Kconfig, arch/arm64/Kconfig). 
So I think this is how current designware based drivers get multiple PCIe 
controller to work (they just enable CONFIG_PCI_DOMAINS)...

 

> 
> > So (correct me if I am wrong) if we have 2 PCIe ports that do not
> specify
> > the "bus-range" property, both root ports will enumerate starting
> from
> > root_bus_nr = 0 and everything will still work ok.
> 
> Correct.
> 
> Best regards,
> Liviu
> 
> >
> > So if my assumption is correct, I do not see why the orginal patch
> from Wang
> > Zhou is wrong.
> > The only point can be that assigning pp->root_bus_nr = 0 is not
> required
> > as pp memory is kzalloc'ed (an therefore init to zero).
> >
> >
> > >
> > > >
> > > > In general I agree with you but if you look at all the current
> > > drivers
> > > > based on designware none of them define the "bus-range" dtb
> property.
> > > > Therefore doing as you say would break the current driver when we
> > > have
> > > > multiple controllers...am I right?
> > > >
> > > The current _code_ works fine for multiple controllers. It's just
> that
> > > you must define the bus range property in the DTB if you want to
> enable
> > > multiple instances of one controller and support a kernel without
> PCI
> > > domains support. As all current implementations have only a single
> > > instance of the controller per SoC, or depend on PCI domain support,
> > > it's totally fine for them to not define the bus ranges property,
> as
> > > it's an optional property and it is well defined how things behave
> if
> > > it
> > > is absent. We absolutely need to keep that specified behavior.
> > >
> > > > If that is the case in order to fix this in the way you say I
> would
> > > need
> > > > to assign "bus-range" for all the PCIe drivers with multiple
> > > controllers:
> > > > in this case I would split the default range evenly (that is, if
> we
> > > have
> > > > two controllers I would define "bus-range"  0-127 and 128-255)
> > > >
> > > > If you think this solution is ok I can go for it. My only doubt
> was
> > > about
> > > > touching other vendors DTBs....
> > > >
> > > You don't need to touch any of the current DTBs, as they are fine
> with
> > > the default bus range behavior. You need to keep the specified
> behavior
> > > of the bus range property with the new code.
> > >
> > > Regards,
> > > Lucas
> > > >
> > > > >
> > > > > It is perfectly valid to have a bus range of 0x00-0x10 assigned
> to
> > > one
> > > > > instance and 0x50-0xff to the next instance. Additional with
> PCIe
> > > > > hotplug you may not use the full range of the bus numbers on
> one
> > > > > instance at the first scan, but only later populate more buses
> when
> > > > > more
> > > > > bridges are added to the tree.
> > > > >
> > > > > > Drivers that do not specify the bus range in the DTB set pp-
> > > > > >root_bus_nr = DW_ROOT_NR_UNDEFINED.
> > > > > > Designware will check if the flag is set and will use the
> > > automatic
> > > > > bus range
> > > > > > assignment.
> > > > >
> > > > > No, please lets get rid of this assignment altogether. The glue
> > > drivers
> > > > > have no business in assigning the bus range. Please remove the
> > > > > pp->root_bus_nr assignment from all the glue drivers.
> > > > >
> > > > > "bus range" is a generic DW PCIe property, so just parse the
> root
> > > bus
> > > > > number from the DT, it is handled the same way for all the DW
> based
> > > > > PCIe
> > > > > drivers. The bindings specifies that if the bus range property
> is
> > > > > missing the range is 0x00-0xff, so you can default to 0 as the
> root
> > > bus
> > > > > number in that case.
> > > > >
> > > > > Also I would think this conversion warrants a patch on its own
> and
> > > > > should not be mixed in the ARM64 support patch.
> > > > >
> > > > > Regards,
> > > > > Lucas
> > > > >
> > >
> > > --
> > > Pengutronix e.K.             | Lucas Stach                 |
> > > Industrial Linux Solutions   | http://www.pengutronix.de/  |
> >
> 
> --
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ?\_(?)_/?
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
  2015-08-21 14:19                   ` Gabriele Paoloni
  (?)
@ 2015-08-24  6:26                     ` Zhou Wang
  -1 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-24  6:26 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Liviu Dudau, Lucas Stach, Bjorn Helgaas, jingoohan1,
	Pratyush Anand, Arnd Bergmann, linux, thomas.petazzoni,
	Lorenzo Pieralisi, James Morse, jason, robh, linux-pci,
	linux-arm-kernel, devicetree, Yuanzhichang, Zhudacai, zhangjukuo,
	qiuzhenfa

On 2015/8/21 22:19, Gabriele Paoloni wrote:
> Hi Liviu
> 
> Many Thanks for reviewing
> 
>> -----Original Message-----
>> From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-
>> owner@vger.kernel.org] On Behalf Of Liviu Dudau
>> Sent: Friday, August 21, 2015 2:43 PM
>> To: Gabriele Paoloni
>> Cc: Lucas Stach; Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com;
>> Pratyush Anand; Arnd Bergmann; linux@arm.linux.org.uk;
>> thomas.petazzoni@free-electrons.com; Lorenzo Pieralisi; James Morse;
>> jason@lakedaemon.net; robh@kernel.org; linux-pci@vger.kernel.org;
>> linux-arm-kernel@lists.infradead.org; devicetree@vger.kernel.org;
>> Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; liudongdong (C);
>> qiujiang; xuwei (O); Liguozhu (Kenneth)
>> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
>>
>> On Thu, Aug 20, 2015 at 12:10:24PM +0100, Gabriele Paoloni wrote:
>>> Hi Lucas
>>>
>>> Again many thanks for explaining and for your time.
>>>
>>> I got your point now and I have dug a bit better in the PCI_DOMAINS
>> code.
>>>
>>> However I have a question...see inline below
>>>
>>>> -----Original Message-----
>>>> From: Lucas Stach [mailto:l.stach@pengutronix.de]
>>>> Sent: Thursday, August 20, 2015 9:27 AM
>>>> To: Gabriele Paoloni
>>>> Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com; Pratyush
>> Anand;
>>>> Arnd Bergmann; linux@arm.linux.org.uk; thomas.petazzoni@free-
>>>> electrons.com; lorenzo.pieralisi@arm.com; james.morse@arm.com;
>>>> Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org; linux-
>>>> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
>>>> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
>>>> qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
>>>> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
>>>>
>>>> Hi Gab,
>>>>
>>>> Am Mittwoch, den 19.08.2015, 16:34 +0000 schrieb Gabriele Paoloni:
>>>>> Hi Lucas
>>>>>
>>>>> First of all many thanks for the quick reply, really appreciated
>>>>>
>>>>>> -----Original Message-----
>>>>>> From: Lucas Stach [mailto:l.stach@pengutronix.de]
>>>>>> Sent: Wednesday, August 19, 2015 4:37 PM
>>>>>> To: Gabriele Paoloni
>>>>>> Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com; Pratyush
>>>> Anand;
>>>>>> Arnd Bergmann; linux@arm.linux.org.uk; thomas.petazzoni@free-
>>>>>> electrons.com; lorenzo.pieralisi@arm.com; james.morse@arm.com;
>>>>>> Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org;
>> linux-
>>>>>> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
>>>>>> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
>>>>>> qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu
>> (Kenneth)
>>>>>> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
>>>>>>
>>>>>> Hi Gab,
>>>>>>
>>>>>> Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele
>> Paoloni:
>>>>>>> Hi Lucas
>>>>>>>
>>>>>>> I have rewritten the patch to take into account multiple
>>>> controllers.
>>>>>>>
>>>>>>> As you can see now there is a static var in
>> dw_pcie_host_init()
>>>> that
>>>>>> tracks
>>>>>>> the bus numbers used.
>>>>>>
>>>>>> This is wrong. The DT specifies the valid bus number range. You
>> can
>>>> not
>>>>>> just assign the next free bus number to the root bus.
>>>>>
>>>>> I think this is what is being done in
>>>>> http://lxr.free-
>> electrons.com/source/arch/arm/kernel/bios32.c#L495
>>>>> and currently designware assigns the root bus number in
>>>>> http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
>>>> designware.c#L730
>>>>>
>>>> You found the right spot. It works a bit different than I remember,
>> but
>>>> is less broken than your current code. :)
>>>>
>>>> It actually assigns the next instance a root bus number behind the
>>>> current instances bus range. Please note the difference to your
>> code
>>>> which assigns the next free bus number, which may still lay within
>> the
>>>> current instances bus range.
>>
>> Hi Gabriele,
>>
>>>
>>> Mmmm here I have done a mistake: in the current designware the number
>> of hw
>>> controllers is always 1
>>> http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
>> designware.c#L510
>>> So the loop in bios32.c does not work on multiple PCIe ports...
>>
>> Bios32.c is broken for multiple PCIe hosts for multiple reasons, this
>> is just
>> one of them. Hence the effort to get rid of it for maintained drivers.
> 
> As you can see we're pushing hard for this :)
>

How about we pass pp->busn->start to pci_create_root_bus as root bus number?
We get pp->busn->start from resource list(res) whose elements come from
of_pci_get_host_bridge_resources.

If there is a bus-range item in dts, root bus number will get from it.
Oppositely, root bus number will be default value(0x0).

Thanks,
Zhou

>>
>>> However your comment about PCI_DOMAINS enlightened my mind and now I
>> see
>>> that when CONFIG_PCI_DOMAINS is defined we have the domains numbers
>>> (tracked by __domain_nr).
>>
>> CONFIG_PCI_DOMAINS in itself doesn't do much without adding code to
>> your driver.
>> You could request a new domain for each controller with a special
>> property to
>> disable that behaviour in the dts, or you could enable
>> CONFIG_PCI_DOMAINS_GENERIC
>> which will give you a new domain automatically.
> 
> So far I see that for ARM and ARM64 CONFIG_PCI_DOMAINS_GENERIC defaults to 
> the same value as CONFIG_PCI_DOMAINS (see arch/arm/Kconfig, arch/arm64/Kconfig). 
> So I think this is how current designware based drivers get multiple PCIe 
> controller to work (they just enable CONFIG_PCI_DOMAINS)...
> 
>  
> 
>>
>>> So (correct me if I am wrong) if we have 2 PCIe ports that do not
>> specify
>>> the "bus-range" property, both root ports will enumerate starting
>> from
>>> root_bus_nr = 0 and everything will still work ok.
>>
>> Correct.
>>
>> Best regards,
>> Liviu
>>
>>>
>>> So if my assumption is correct, I do not see why the orginal patch
>> from Wang
>>> Zhou is wrong.
>>> The only point can be that assigning pp->root_bus_nr = 0 is not
>> required
>>> as pp memory is kzalloc'ed (an therefore init to zero).
>>>
>>>
>>>>
>>>>>
>>>>> In general I agree with you but if you look at all the current
>>>> drivers
>>>>> based on designware none of them define the "bus-range" dtb
>> property.
>>>>> Therefore doing as you say would break the current driver when we
>>>> have
>>>>> multiple controllers...am I right?
>>>>>
>>>> The current _code_ works fine for multiple controllers. It's just
>> that
>>>> you must define the bus range property in the DTB if you want to
>> enable
>>>> multiple instances of one controller and support a kernel without
>> PCI
>>>> domains support. As all current implementations have only a single
>>>> instance of the controller per SoC, or depend on PCI domain support,
>>>> it's totally fine for them to not define the bus ranges property,
>> as
>>>> it's an optional property and it is well defined how things behave
>> if
>>>> it
>>>> is absent. We absolutely need to keep that specified behavior.
>>>>
>>>>> If that is the case in order to fix this in the way you say I
>> would
>>>> need
>>>>> to assign "bus-range" for all the PCIe drivers with multiple
>>>> controllers:
>>>>> in this case I would split the default range evenly (that is, if
>> we
>>>> have
>>>>> two controllers I would define "bus-range"  0-127 and 128-255)
>>>>>
>>>>> If you think this solution is ok I can go for it. My only doubt
>> was
>>>> about
>>>>> touching other vendors DTBs....
>>>>>
>>>> You don't need to touch any of the current DTBs, as they are fine
>> with
>>>> the default bus range behavior. You need to keep the specified
>> behavior
>>>> of the bus range property with the new code.
>>>>
>>>> Regards,
>>>> Lucas
>>>>>
>>>>>>
>>>>>> It is perfectly valid to have a bus range of 0x00-0x10 assigned
>> to
>>>> one
>>>>>> instance and 0x50-0xff to the next instance. Additional with
>> PCIe
>>>>>> hotplug you may not use the full range of the bus numbers on
>> one
>>>>>> instance at the first scan, but only later populate more buses
>> when
>>>>>> more
>>>>>> bridges are added to the tree.
>>>>>>
>>>>>>> Drivers that do not specify the bus range in the DTB set pp-
>>>>>>> root_bus_nr = DW_ROOT_NR_UNDEFINED.
>>>>>>> Designware will check if the flag is set and will use the
>>>> automatic
>>>>>> bus range
>>>>>>> assignment.
>>>>>>
>>>>>> No, please lets get rid of this assignment altogether. The glue
>>>> drivers
>>>>>> have no business in assigning the bus range. Please remove the
>>>>>> pp->root_bus_nr assignment from all the glue drivers.
>>>>>>
>>>>>> "bus range" is a generic DW PCIe property, so just parse the
>> root
>>>> bus
>>>>>> number from the DT, it is handled the same way for all the DW
>> based
>>>>>> PCIe
>>>>>> drivers. The bindings specifies that if the bus range property
>> is
>>>>>> missing the range is 0x00-0xff, so you can default to 0 as the
>> root
>>>> bus
>>>>>> number in that case.
>>>>>>
>>>>>> Also I would think this conversion warrants a patch on its own
>> and
>>>>>> should not be mixed in the ARM64 support patch.
>>>>>>
>>>>>> Regards,
>>>>>> Lucas
>>>>>>
>>>>
>>>> --
>>>> Pengutronix e.K.             | Lucas Stach                 |
>>>> Industrial Linux Solutions   | http://www.pengutronix.de/  |
>>>
>>
>> --
>> ====================
>> | I would like to |
>> | fix the world,  |
>> | but they're not |
>> | giving me the   |
>>  \ source code!  /
>>   ---------------
>>     ¯\_(ツ)_/¯
>>
>> --
>> 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

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

* Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-24  6:26                     ` Zhou Wang
  0 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-24  6:26 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Liviu Dudau, Lucas Stach, Bjorn Helgaas, jingoohan1,
	Pratyush Anand, Arnd Bergmann, linux, thomas.petazzoni,
	Lorenzo Pieralisi, James Morse, jason, robh, linux-pci,
	linux-arm-kernel, devicetree, Yuanzhichang, Zhudacai, zhangjukuo,
	qiuzhenfa, liudongdong (C), qiujiang, xuwei (O),
	Liguozhu (Kenneth)

On 2015/8/21 22:19, Gabriele Paoloni wrote:
> Hi Liviu
> 
> Many Thanks for reviewing
> 
>> -----Original Message-----
>> From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-
>> owner@vger.kernel.org] On Behalf Of Liviu Dudau
>> Sent: Friday, August 21, 2015 2:43 PM
>> To: Gabriele Paoloni
>> Cc: Lucas Stach; Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com;
>> Pratyush Anand; Arnd Bergmann; linux@arm.linux.org.uk;
>> thomas.petazzoni@free-electrons.com; Lorenzo Pieralisi; James Morse;
>> jason@lakedaemon.net; robh@kernel.org; linux-pci@vger.kernel.org;
>> linux-arm-kernel@lists.infradead.org; devicetree@vger.kernel.org;
>> Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; liudongdong (C);
>> qiujiang; xuwei (O); Liguozhu (Kenneth)
>> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
>>
>> On Thu, Aug 20, 2015 at 12:10:24PM +0100, Gabriele Paoloni wrote:
>>> Hi Lucas
>>>
>>> Again many thanks for explaining and for your time.
>>>
>>> I got your point now and I have dug a bit better in the PCI_DOMAINS
>> code.
>>>
>>> However I have a question...see inline below
>>>
>>>> -----Original Message-----
>>>> From: Lucas Stach [mailto:l.stach@pengutronix.de]
>>>> Sent: Thursday, August 20, 2015 9:27 AM
>>>> To: Gabriele Paoloni
>>>> Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com; Pratyush
>> Anand;
>>>> Arnd Bergmann; linux@arm.linux.org.uk; thomas.petazzoni@free-
>>>> electrons.com; lorenzo.pieralisi@arm.com; james.morse@arm.com;
>>>> Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org; linux-
>>>> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
>>>> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
>>>> qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
>>>> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
>>>>
>>>> Hi Gab,
>>>>
>>>> Am Mittwoch, den 19.08.2015, 16:34 +0000 schrieb Gabriele Paoloni:
>>>>> Hi Lucas
>>>>>
>>>>> First of all many thanks for the quick reply, really appreciated
>>>>>
>>>>>> -----Original Message-----
>>>>>> From: Lucas Stach [mailto:l.stach@pengutronix.de]
>>>>>> Sent: Wednesday, August 19, 2015 4:37 PM
>>>>>> To: Gabriele Paoloni
>>>>>> Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com; Pratyush
>>>> Anand;
>>>>>> Arnd Bergmann; linux@arm.linux.org.uk; thomas.petazzoni@free-
>>>>>> electrons.com; lorenzo.pieralisi@arm.com; james.morse@arm.com;
>>>>>> Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org;
>> linux-
>>>>>> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
>>>>>> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
>>>>>> qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu
>> (Kenneth)
>>>>>> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
>>>>>>
>>>>>> Hi Gab,
>>>>>>
>>>>>> Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele
>> Paoloni:
>>>>>>> Hi Lucas
>>>>>>>
>>>>>>> I have rewritten the patch to take into account multiple
>>>> controllers.
>>>>>>>
>>>>>>> As you can see now there is a static var in
>> dw_pcie_host_init()
>>>> that
>>>>>> tracks
>>>>>>> the bus numbers used.
>>>>>>
>>>>>> This is wrong. The DT specifies the valid bus number range. You
>> can
>>>> not
>>>>>> just assign the next free bus number to the root bus.
>>>>>
>>>>> I think this is what is being done in
>>>>> http://lxr.free-
>> electrons.com/source/arch/arm/kernel/bios32.c#L495
>>>>> and currently designware assigns the root bus number in
>>>>> http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
>>>> designware.c#L730
>>>>>
>>>> You found the right spot. It works a bit different than I remember,
>> but
>>>> is less broken than your current code. :)
>>>>
>>>> It actually assigns the next instance a root bus number behind the
>>>> current instances bus range. Please note the difference to your
>> code
>>>> which assigns the next free bus number, which may still lay within
>> the
>>>> current instances bus range.
>>
>> Hi Gabriele,
>>
>>>
>>> Mmmm here I have done a mistake: in the current designware the number
>> of hw
>>> controllers is always 1
>>> http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
>> designware.c#L510
>>> So the loop in bios32.c does not work on multiple PCIe ports...
>>
>> Bios32.c is broken for multiple PCIe hosts for multiple reasons, this
>> is just
>> one of them. Hence the effort to get rid of it for maintained drivers.
> 
> As you can see we're pushing hard for this :)
>

How about we pass pp->busn->start to pci_create_root_bus as root bus number?
We get pp->busn->start from resource list(res) whose elements come from
of_pci_get_host_bridge_resources.

If there is a bus-range item in dts, root bus number will get from it.
Oppositely, root bus number will be default value(0x0).

Thanks,
Zhou

>>
>>> However your comment about PCI_DOMAINS enlightened my mind and now I
>> see
>>> that when CONFIG_PCI_DOMAINS is defined we have the domains numbers
>>> (tracked by __domain_nr).
>>
>> CONFIG_PCI_DOMAINS in itself doesn't do much without adding code to
>> your driver.
>> You could request a new domain for each controller with a special
>> property to
>> disable that behaviour in the dts, or you could enable
>> CONFIG_PCI_DOMAINS_GENERIC
>> which will give you a new domain automatically.
> 
> So far I see that for ARM and ARM64 CONFIG_PCI_DOMAINS_GENERIC defaults to 
> the same value as CONFIG_PCI_DOMAINS (see arch/arm/Kconfig, arch/arm64/Kconfig). 
> So I think this is how current designware based drivers get multiple PCIe 
> controller to work (they just enable CONFIG_PCI_DOMAINS)...
> 
>  
> 
>>
>>> So (correct me if I am wrong) if we have 2 PCIe ports that do not
>> specify
>>> the "bus-range" property, both root ports will enumerate starting
>> from
>>> root_bus_nr = 0 and everything will still work ok.
>>
>> Correct.
>>
>> Best regards,
>> Liviu
>>
>>>
>>> So if my assumption is correct, I do not see why the orginal patch
>> from Wang
>>> Zhou is wrong.
>>> The only point can be that assigning pp->root_bus_nr = 0 is not
>> required
>>> as pp memory is kzalloc'ed (an therefore init to zero).
>>>
>>>
>>>>
>>>>>
>>>>> In general I agree with you but if you look at all the current
>>>> drivers
>>>>> based on designware none of them define the "bus-range" dtb
>> property.
>>>>> Therefore doing as you say would break the current driver when we
>>>> have
>>>>> multiple controllers...am I right?
>>>>>
>>>> The current _code_ works fine for multiple controllers. It's just
>> that
>>>> you must define the bus range property in the DTB if you want to
>> enable
>>>> multiple instances of one controller and support a kernel without
>> PCI
>>>> domains support. As all current implementations have only a single
>>>> instance of the controller per SoC, or depend on PCI domain support,
>>>> it's totally fine for them to not define the bus ranges property,
>> as
>>>> it's an optional property and it is well defined how things behave
>> if
>>>> it
>>>> is absent. We absolutely need to keep that specified behavior.
>>>>
>>>>> If that is the case in order to fix this in the way you say I
>> would
>>>> need
>>>>> to assign "bus-range" for all the PCIe drivers with multiple
>>>> controllers:
>>>>> in this case I would split the default range evenly (that is, if
>> we
>>>> have
>>>>> two controllers I would define "bus-range"  0-127 and 128-255)
>>>>>
>>>>> If you think this solution is ok I can go for it. My only doubt
>> was
>>>> about
>>>>> touching other vendors DTBs....
>>>>>
>>>> You don't need to touch any of the current DTBs, as they are fine
>> with
>>>> the default bus range behavior. You need to keep the specified
>> behavior
>>>> of the bus range property with the new code.
>>>>
>>>> Regards,
>>>> Lucas
>>>>>
>>>>>>
>>>>>> It is perfectly valid to have a bus range of 0x00-0x10 assigned
>> to
>>>> one
>>>>>> instance and 0x50-0xff to the next instance. Additional with
>> PCIe
>>>>>> hotplug you may not use the full range of the bus numbers on
>> one
>>>>>> instance at the first scan, but only later populate more buses
>> when
>>>>>> more
>>>>>> bridges are added to the tree.
>>>>>>
>>>>>>> Drivers that do not specify the bus range in the DTB set pp-
>>>>>>> root_bus_nr = DW_ROOT_NR_UNDEFINED.
>>>>>>> Designware will check if the flag is set and will use the
>>>> automatic
>>>>>> bus range
>>>>>>> assignment.
>>>>>>
>>>>>> No, please lets get rid of this assignment altogether. The glue
>>>> drivers
>>>>>> have no business in assigning the bus range. Please remove the
>>>>>> pp->root_bus_nr assignment from all the glue drivers.
>>>>>>
>>>>>> "bus range" is a generic DW PCIe property, so just parse the
>> root
>>>> bus
>>>>>> number from the DT, it is handled the same way for all the DW
>> based
>>>>>> PCIe
>>>>>> drivers. The bindings specifies that if the bus range property
>> is
>>>>>> missing the range is 0x00-0xff, so you can default to 0 as the
>> root
>>>> bus
>>>>>> number in that case.
>>>>>>
>>>>>> Also I would think this conversion warrants a patch on its own
>> and
>>>>>> should not be mixed in the ARM64 support patch.
>>>>>>
>>>>>> Regards,
>>>>>> Lucas
>>>>>>
>>>>
>>>> --
>>>> Pengutronix e.K.             | Lucas Stach                 |
>>>> Industrial Linux Solutions   | http://www.pengutronix.de/  |
>>>
>>
>> --
>> ====================
>> | I would like to |
>> | fix the world,  |
>> | but they're not |
>> | giving me the   |
>>  \ source code!  /
>>   ---------------
>>     ¯\_(ツ)_/¯
>>
>> --
>> 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



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

* [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-24  6:26                     ` Zhou Wang
  0 siblings, 0 replies; 53+ messages in thread
From: Zhou Wang @ 2015-08-24  6:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 2015/8/21 22:19, Gabriele Paoloni wrote:
> Hi Liviu
> 
> Many Thanks for reviewing
> 
>> -----Original Message-----
>> From: linux-pci-owner at vger.kernel.org [mailto:linux-pci-
>> owner at vger.kernel.org] On Behalf Of Liviu Dudau
>> Sent: Friday, August 21, 2015 2:43 PM
>> To: Gabriele Paoloni
>> Cc: Lucas Stach; Wangzhou (B); Bjorn Helgaas; jingoohan1 at gmail.com;
>> Pratyush Anand; Arnd Bergmann; linux at arm.linux.org.uk;
>> thomas.petazzoni at free-electrons.com; Lorenzo Pieralisi; James Morse;
>> jason at lakedaemon.net; robh at kernel.org; linux-pci at vger.kernel.org;
>> linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.org;
>> Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; liudongdong (C);
>> qiujiang; xuwei (O); Liguozhu (Kenneth)
>> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
>>
>> On Thu, Aug 20, 2015 at 12:10:24PM +0100, Gabriele Paoloni wrote:
>>> Hi Lucas
>>>
>>> Again many thanks for explaining and for your time.
>>>
>>> I got your point now and I have dug a bit better in the PCI_DOMAINS
>> code.
>>>
>>> However I have a question...see inline below
>>>
>>>> -----Original Message-----
>>>> From: Lucas Stach [mailto:l.stach at pengutronix.de]
>>>> Sent: Thursday, August 20, 2015 9:27 AM
>>>> To: Gabriele Paoloni
>>>> Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1 at gmail.com; Pratyush
>> Anand;
>>>> Arnd Bergmann; linux at arm.linux.org.uk; thomas.petazzoni at free-
>>>> electrons.com; lorenzo.pieralisi at arm.com; james.morse at arm.com;
>>>> Liviu.Dudau at arm.com; jason at lakedaemon.net; robh at kernel.org; linux-
>>>> pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
>>>> devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
>>>> qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
>>>> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
>>>>
>>>> Hi Gab,
>>>>
>>>> Am Mittwoch, den 19.08.2015, 16:34 +0000 schrieb Gabriele Paoloni:
>>>>> Hi Lucas
>>>>>
>>>>> First of all many thanks for the quick reply, really appreciated
>>>>>
>>>>>> -----Original Message-----
>>>>>> From: Lucas Stach [mailto:l.stach at pengutronix.de]
>>>>>> Sent: Wednesday, August 19, 2015 4:37 PM
>>>>>> To: Gabriele Paoloni
>>>>>> Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1 at gmail.com; Pratyush
>>>> Anand;
>>>>>> Arnd Bergmann; linux at arm.linux.org.uk; thomas.petazzoni at free-
>>>>>> electrons.com; lorenzo.pieralisi at arm.com; james.morse at arm.com;
>>>>>> Liviu.Dudau at arm.com; jason at lakedaemon.net; robh at kernel.org;
>> linux-
>>>>>> pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
>>>>>> devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
>>>>>> qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu
>> (Kenneth)
>>>>>> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
>>>>>>
>>>>>> Hi Gab,
>>>>>>
>>>>>> Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele
>> Paoloni:
>>>>>>> Hi Lucas
>>>>>>>
>>>>>>> I have rewritten the patch to take into account multiple
>>>> controllers.
>>>>>>>
>>>>>>> As you can see now there is a static var in
>> dw_pcie_host_init()
>>>> that
>>>>>> tracks
>>>>>>> the bus numbers used.
>>>>>>
>>>>>> This is wrong. The DT specifies the valid bus number range. You
>> can
>>>> not
>>>>>> just assign the next free bus number to the root bus.
>>>>>
>>>>> I think this is what is being done in
>>>>> http://lxr.free-
>> electrons.com/source/arch/arm/kernel/bios32.c#L495
>>>>> and currently designware assigns the root bus number in
>>>>> http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
>>>> designware.c#L730
>>>>>
>>>> You found the right spot. It works a bit different than I remember,
>> but
>>>> is less broken than your current code. :)
>>>>
>>>> It actually assigns the next instance a root bus number behind the
>>>> current instances bus range. Please note the difference to your
>> code
>>>> which assigns the next free bus number, which may still lay within
>> the
>>>> current instances bus range.
>>
>> Hi Gabriele,
>>
>>>
>>> Mmmm here I have done a mistake: in the current designware the number
>> of hw
>>> controllers is always 1
>>> http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
>> designware.c#L510
>>> So the loop in bios32.c does not work on multiple PCIe ports...
>>
>> Bios32.c is broken for multiple PCIe hosts for multiple reasons, this
>> is just
>> one of them. Hence the effort to get rid of it for maintained drivers.
> 
> As you can see we're pushing hard for this :)
>

How about we pass pp->busn->start to pci_create_root_bus as root bus number?
We get pp->busn->start from resource list(res) whose elements come from
of_pci_get_host_bridge_resources.

If there is a bus-range item in dts, root bus number will get from it.
Oppositely, root bus number will be default value(0x0).

Thanks,
Zhou

>>
>>> However your comment about PCI_DOMAINS enlightened my mind and now I
>> see
>>> that when CONFIG_PCI_DOMAINS is defined we have the domains numbers
>>> (tracked by __domain_nr).
>>
>> CONFIG_PCI_DOMAINS in itself doesn't do much without adding code to
>> your driver.
>> You could request a new domain for each controller with a special
>> property to
>> disable that behaviour in the dts, or you could enable
>> CONFIG_PCI_DOMAINS_GENERIC
>> which will give you a new domain automatically.
> 
> So far I see that for ARM and ARM64 CONFIG_PCI_DOMAINS_GENERIC defaults to 
> the same value as CONFIG_PCI_DOMAINS (see arch/arm/Kconfig, arch/arm64/Kconfig). 
> So I think this is how current designware based drivers get multiple PCIe 
> controller to work (they just enable CONFIG_PCI_DOMAINS)...
> 
>  
> 
>>
>>> So (correct me if I am wrong) if we have 2 PCIe ports that do not
>> specify
>>> the "bus-range" property, both root ports will enumerate starting
>> from
>>> root_bus_nr = 0 and everything will still work ok.
>>
>> Correct.
>>
>> Best regards,
>> Liviu
>>
>>>
>>> So if my assumption is correct, I do not see why the orginal patch
>> from Wang
>>> Zhou is wrong.
>>> The only point can be that assigning pp->root_bus_nr = 0 is not
>> required
>>> as pp memory is kzalloc'ed (an therefore init to zero).
>>>
>>>
>>>>
>>>>>
>>>>> In general I agree with you but if you look at all the current
>>>> drivers
>>>>> based on designware none of them define the "bus-range" dtb
>> property.
>>>>> Therefore doing as you say would break the current driver when we
>>>> have
>>>>> multiple controllers...am I right?
>>>>>
>>>> The current _code_ works fine for multiple controllers. It's just
>> that
>>>> you must define the bus range property in the DTB if you want to
>> enable
>>>> multiple instances of one controller and support a kernel without
>> PCI
>>>> domains support. As all current implementations have only a single
>>>> instance of the controller per SoC, or depend on PCI domain support,
>>>> it's totally fine for them to not define the bus ranges property,
>> as
>>>> it's an optional property and it is well defined how things behave
>> if
>>>> it
>>>> is absent. We absolutely need to keep that specified behavior.
>>>>
>>>>> If that is the case in order to fix this in the way you say I
>> would
>>>> need
>>>>> to assign "bus-range" for all the PCIe drivers with multiple
>>>> controllers:
>>>>> in this case I would split the default range evenly (that is, if
>> we
>>>> have
>>>>> two controllers I would define "bus-range"  0-127 and 128-255)
>>>>>
>>>>> If you think this solution is ok I can go for it. My only doubt
>> was
>>>> about
>>>>> touching other vendors DTBs....
>>>>>
>>>> You don't need to touch any of the current DTBs, as they are fine
>> with
>>>> the default bus range behavior. You need to keep the specified
>> behavior
>>>> of the bus range property with the new code.
>>>>
>>>> Regards,
>>>> Lucas
>>>>>
>>>>>>
>>>>>> It is perfectly valid to have a bus range of 0x00-0x10 assigned
>> to
>>>> one
>>>>>> instance and 0x50-0xff to the next instance. Additional with
>> PCIe
>>>>>> hotplug you may not use the full range of the bus numbers on
>> one
>>>>>> instance at the first scan, but only later populate more buses
>> when
>>>>>> more
>>>>>> bridges are added to the tree.
>>>>>>
>>>>>>> Drivers that do not specify the bus range in the DTB set pp-
>>>>>>> root_bus_nr = DW_ROOT_NR_UNDEFINED.
>>>>>>> Designware will check if the flag is set and will use the
>>>> automatic
>>>>>> bus range
>>>>>>> assignment.
>>>>>>
>>>>>> No, please lets get rid of this assignment altogether. The glue
>>>> drivers
>>>>>> have no business in assigning the bus range. Please remove the
>>>>>> pp->root_bus_nr assignment from all the glue drivers.
>>>>>>
>>>>>> "bus range" is a generic DW PCIe property, so just parse the
>> root
>>>> bus
>>>>>> number from the DT, it is handled the same way for all the DW
>> based
>>>>>> PCIe
>>>>>> drivers. The bindings specifies that if the bus range property
>> is
>>>>>> missing the range is 0x00-0xff, so you can default to 0 as the
>> root
>>>> bus
>>>>>> number in that case.
>>>>>>
>>>>>> Also I would think this conversion warrants a patch on its own
>> and
>>>>>> should not be mixed in the ARM64 support patch.
>>>>>>
>>>>>> Regards,
>>>>>> Lucas
>>>>>>
>>>>
>>>> --
>>>> Pengutronix e.K.             | Lucas Stach                 |
>>>> Industrial Linux Solutions   | http://www.pengutronix.de/  |
>>>
>>
>> --
>> ====================
>> | I would like to |
>> | fix the world,  |
>> | but they're not |
>> | giving me the   |
>>  \ source code!  /
>>   ---------------
>>     ?\_(?)_/?
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* RE: [PATCH v7 3/6] PCI: designware: Add ARM64 support
  2015-08-24  6:26                     ` Zhou Wang
  (?)
@ 2015-08-24  8:28                       ` Gabriele Paoloni
  -1 siblings, 0 replies; 53+ messages in thread
From: Gabriele Paoloni @ 2015-08-24  8:28 UTC (permalink / raw)
  To: Wangzhou (B)
  Cc: Liviu Dudau, Lucas Stach, Bjorn Helgaas, jingoohan1,
	Pratyush Anand, Arnd Bergmann, linux, thomas.petazzoni,
	Lorenzo Pieralisi, James Morse, jason, robh, linux-pci,
	linux-arm-kernel, devicetree, Yuanzhichang, Zhudacai, zhangjukuo,
	qiuzhenfa



> -----Original Message-----
> From: Wangzhou (B)
> Sent: Monday, August 24, 2015 7:26 AM
> To: Gabriele Paoloni
> Cc: Liviu Dudau; Lucas Stach; Bjorn Helgaas; jingoohan1@gmail.com;
> Pratyush Anand; Arnd Bergmann; linux@arm.linux.org.uk;
> thomas.petazzoni@free-electrons.com; Lorenzo Pieralisi; James Morse;
> jason@lakedaemon.net; robh@kernel.org; linux-pci@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; devicetree@vger.kernel.org;
> Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; liudongdong (C);
> qiujiang; xuwei (O); Liguozhu (Kenneth)
> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> 
> On 2015/8/21 22:19, Gabriele Paoloni wrote:
> > Hi Liviu
> >
> > Many Thanks for reviewing
> >
> >> -----Original Message-----
> >> From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-
> >> owner@vger.kernel.org] On Behalf Of Liviu Dudau
> >> Sent: Friday, August 21, 2015 2:43 PM
> >> To: Gabriele Paoloni
> >> Cc: Lucas Stach; Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com;
> >> Pratyush Anand; Arnd Bergmann; linux@arm.linux.org.uk;
> >> thomas.petazzoni@free-electrons.com; Lorenzo Pieralisi; James Morse;
> >> jason@lakedaemon.net; robh@kernel.org; linux-pci@vger.kernel.org;
> >> linux-arm-kernel@lists.infradead.org; devicetree@vger.kernel.org;
> >> Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; liudongdong (C);
> >> qiujiang; xuwei (O); Liguozhu (Kenneth)
> >> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> >>
> >> On Thu, Aug 20, 2015 at 12:10:24PM +0100, Gabriele Paoloni wrote:
> >>> Hi Lucas
> >>>
> >>> Again many thanks for explaining and for your time.
> >>>
> >>> I got your point now and I have dug a bit better in the PCI_DOMAINS
> >> code.
> >>>
> >>> However I have a question...see inline below
> >>>
> >>>> -----Original Message-----
> >>>> From: Lucas Stach [mailto:l.stach@pengutronix.de]
> >>>> Sent: Thursday, August 20, 2015 9:27 AM
> >>>> To: Gabriele Paoloni
> >>>> Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com; Pratyush
> >> Anand;
> >>>> Arnd Bergmann; linux@arm.linux.org.uk; thomas.petazzoni@free-
> >>>> electrons.com; lorenzo.pieralisi@arm.com; james.morse@arm.com;
> >>>> Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org; linux-
> >>>> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> >>>> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> >>>> qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> >>>> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> >>>>
> >>>> Hi Gab,
> >>>>
> >>>> Am Mittwoch, den 19.08.2015, 16:34 +0000 schrieb Gabriele Paoloni:
> >>>>> Hi Lucas
> >>>>>
> >>>>> First of all many thanks for the quick reply, really appreciated
> >>>>>
> >>>>>> -----Original Message-----
> >>>>>> From: Lucas Stach [mailto:l.stach@pengutronix.de]
> >>>>>> Sent: Wednesday, August 19, 2015 4:37 PM
> >>>>>> To: Gabriele Paoloni
> >>>>>> Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1@gmail.com; Pratyush
> >>>> Anand;
> >>>>>> Arnd Bergmann; linux@arm.linux.org.uk; thomas.petazzoni@free-
> >>>>>> electrons.com; lorenzo.pieralisi@arm.com; james.morse@arm.com;
> >>>>>> Liviu.Dudau@arm.com; jason@lakedaemon.net; robh@kernel.org;
> >> linux-
> >>>>>> pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> >>>>>> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> >>>>>> qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu
> >> (Kenneth)
> >>>>>> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> >>>>>>
> >>>>>> Hi Gab,
> >>>>>>
> >>>>>> Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele
> >> Paoloni:
> >>>>>>> Hi Lucas
> >>>>>>>
> >>>>>>> I have rewritten the patch to take into account multiple
> >>>> controllers.
> >>>>>>>
> >>>>>>> As you can see now there is a static var in
> >> dw_pcie_host_init()
> >>>> that
> >>>>>> tracks
> >>>>>>> the bus numbers used.
> >>>>>>
> >>>>>> This is wrong. The DT specifies the valid bus number range. You
> >> can
> >>>> not
> >>>>>> just assign the next free bus number to the root bus.
> >>>>>
> >>>>> I think this is what is being done in
> >>>>> http://lxr.free-
> >> electrons.com/source/arch/arm/kernel/bios32.c#L495
> >>>>> and currently designware assigns the root bus number in
> >>>>> http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
> >>>> designware.c#L730
> >>>>>
> >>>> You found the right spot. It works a bit different than I remember,
> >> but
> >>>> is less broken than your current code. :)
> >>>>
> >>>> It actually assigns the next instance a root bus number behind the
> >>>> current instances bus range. Please note the difference to your
> >> code
> >>>> which assigns the next free bus number, which may still lay within
> >> the
> >>>> current instances bus range.
> >>
> >> Hi Gabriele,
> >>
> >>>
> >>> Mmmm here I have done a mistake: in the current designware the
> number
> >> of hw
> >>> controllers is always 1
> >>> http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
> >> designware.c#L510
> >>> So the loop in bios32.c does not work on multiple PCIe ports...
> >>
> >> Bios32.c is broken for multiple PCIe hosts for multiple reasons,
> this
> >> is just
> >> one of them. Hence the effort to get rid of it for maintained
> drivers.
> >
> > As you can see we're pushing hard for this :)
> >
> 
> How about we pass pp->busn->start to pci_create_root_bus as root bus
> number?
> We get pp->busn->start from resource list(res) whose elements come from
> of_pci_get_host_bridge_resources.
> 
> If there is a bus-range item in dts, root bus number will get from it.
> Oppositely, root bus number will be default value(0x0).
> 
> Thanks,
> Zhou

Sounds good to me. So we can remove root_bus_nr

> 
> >>
> >>> However your comment about PCI_DOMAINS enlightened my mind and now
> I
> >> see
> >>> that when CONFIG_PCI_DOMAINS is defined we have the domains numbers
> >>> (tracked by __domain_nr).
> >>
> >> CONFIG_PCI_DOMAINS in itself doesn't do much without adding code to
> >> your driver.
> >> You could request a new domain for each controller with a special
> >> property to
> >> disable that behaviour in the dts, or you could enable
> >> CONFIG_PCI_DOMAINS_GENERIC
> >> which will give you a new domain automatically.
> >
> > So far I see that for ARM and ARM64 CONFIG_PCI_DOMAINS_GENERIC
> defaults to
> > the same value as CONFIG_PCI_DOMAINS (see arch/arm/Kconfig,
> arch/arm64/Kconfig).
> > So I think this is how current designware based drivers get multiple
> PCIe
> > controller to work (they just enable CONFIG_PCI_DOMAINS)...
> >
> >
> >
> >>
> >>> So (correct me if I am wrong) if we have 2 PCIe ports that do not
> >> specify
> >>> the "bus-range" property, both root ports will enumerate starting
> >> from
> >>> root_bus_nr = 0 and everything will still work ok.
> >>
> >> Correct.
> >>
> >> Best regards,
> >> Liviu
> >>
> >>>
> >>> So if my assumption is correct, I do not see why the orginal patch
> >> from Wang
> >>> Zhou is wrong.
> >>> The only point can be that assigning pp->root_bus_nr = 0 is not
> >> required
> >>> as pp memory is kzalloc'ed (an therefore init to zero).
> >>>
> >>>
> >>>>
> >>>>>
> >>>>> In general I agree with you but if you look at all the current
> >>>> drivers
> >>>>> based on designware none of them define the "bus-range" dtb
> >> property.
> >>>>> Therefore doing as you say would break the current driver when we
> >>>> have
> >>>>> multiple controllers...am I right?
> >>>>>
> >>>> The current _code_ works fine for multiple controllers. It's just
> >> that
> >>>> you must define the bus range property in the DTB if you want to
> >> enable
> >>>> multiple instances of one controller and support a kernel without
> >> PCI
> >>>> domains support. As all current implementations have only a single
> >>>> instance of the controller per SoC, or depend on PCI domain
> support,
> >>>> it's totally fine for them to not define the bus ranges property,
> >> as
> >>>> it's an optional property and it is well defined how things behave
> >> if
> >>>> it
> >>>> is absent. We absolutely need to keep that specified behavior.
> >>>>
> >>>>> If that is the case in order to fix this in the way you say I
> >> would
> >>>> need
> >>>>> to assign "bus-range" for all the PCIe drivers with multiple
> >>>> controllers:
> >>>>> in this case I would split the default range evenly (that is, if
> >> we
> >>>> have
> >>>>> two controllers I would define "bus-range"  0-127 and 128-255)
> >>>>>
> >>>>> If you think this solution is ok I can go for it. My only doubt
> >> was
> >>>> about
> >>>>> touching other vendors DTBs....
> >>>>>
> >>>> You don't need to touch any of the current DTBs, as they are fine
> >> with
> >>>> the default bus range behavior. You need to keep the specified
> >> behavior
> >>>> of the bus range property with the new code.
> >>>>
> >>>> Regards,
> >>>> Lucas
> >>>>>
> >>>>>>
> >>>>>> It is perfectly valid to have a bus range of 0x00-0x10 assigned
> >> to
> >>>> one
> >>>>>> instance and 0x50-0xff to the next instance. Additional with
> >> PCIe
> >>>>>> hotplug you may not use the full range of the bus numbers on
> >> one
> >>>>>> instance at the first scan, but only later populate more buses
> >> when
> >>>>>> more
> >>>>>> bridges are added to the tree.
> >>>>>>
> >>>>>>> Drivers that do not specify the bus range in the DTB set pp-
> >>>>>>> root_bus_nr = DW_ROOT_NR_UNDEFINED.
> >>>>>>> Designware will check if the flag is set and will use the
> >>>> automatic
> >>>>>> bus range
> >>>>>>> assignment.
> >>>>>>
> >>>>>> No, please lets get rid of this assignment altogether. The glue
> >>>> drivers
> >>>>>> have no business in assigning the bus range. Please remove the
> >>>>>> pp->root_bus_nr assignment from all the glue drivers.
> >>>>>>
> >>>>>> "bus range" is a generic DW PCIe property, so just parse the
> >> root
> >>>> bus
> >>>>>> number from the DT, it is handled the same way for all the DW
> >> based
> >>>>>> PCIe
> >>>>>> drivers. The bindings specifies that if the bus range property
> >> is
> >>>>>> missing the range is 0x00-0xff, so you can default to 0 as the
> >> root
> >>>> bus
> >>>>>> number in that case.
> >>>>>>
> >>>>>> Also I would think this conversion warrants a patch on its own
> >> and
> >>>>>> should not be mixed in the ARM64 support patch.
> >>>>>>
> >>>>>> Regards,
> >>>>>> Lucas
> >>>>>>
> >>>>
> >>>> --
> >>>> Pengutronix e.K.             | Lucas Stach                 |
> >>>> Industrial Linux Solutions   | http://www.pengutronix.de/  |
> >>>
> >>
> >> --
> >> ====================
> >> | I would like to |
> >> | fix the world,  |
> >> | but they're not |
> >> | giving me the   |
> >>  \ source code!  /
> >>   ---------------
> >>     ¯\_(ツ)_/¯
> >>
> >> --
> >> 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
> 


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

* RE: [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-24  8:28                       ` Gabriele Paoloni
  0 siblings, 0 replies; 53+ messages in thread
From: Gabriele Paoloni @ 2015-08-24  8:28 UTC (permalink / raw)
  To: Wangzhou (B)
  Cc: Liviu Dudau, Lucas Stach, Bjorn Helgaas, jingoohan1,
	Pratyush Anand, Arnd Bergmann, linux, thomas.petazzoni,
	Lorenzo Pieralisi, James Morse, jason, robh, linux-pci,
	linux-arm-kernel, devicetree, Yuanzhichang, Zhudacai, zhangjukuo,
	qiuzhenfa, liudongdong (C), qiujiang, xuwei (O),
	Liguozhu (Kenneth)

DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogV2FuZ3pob3UgKEIpDQo+
IFNlbnQ6IE1vbmRheSwgQXVndXN0IDI0LCAyMDE1IDc6MjYgQU0NCj4gVG86IEdhYnJpZWxlIFBh
b2xvbmkNCj4gQ2M6IExpdml1IER1ZGF1OyBMdWNhcyBTdGFjaDsgQmpvcm4gSGVsZ2Fhczsgamlu
Z29vaGFuMUBnbWFpbC5jb207DQo+IFByYXR5dXNoIEFuYW5kOyBBcm5kIEJlcmdtYW5uOyBsaW51
eEBhcm0ubGludXgub3JnLnVrOw0KPiB0aG9tYXMucGV0YXp6b25pQGZyZWUtZWxlY3Ryb25zLmNv
bTsgTG9yZW56byBQaWVyYWxpc2k7IEphbWVzIE1vcnNlOw0KPiBqYXNvbkBsYWtlZGFlbW9uLm5l
dDsgcm9iaEBrZXJuZWwub3JnOyBsaW51eC1wY2lAdmdlci5rZXJuZWwub3JnOw0KPiBsaW51eC1h
cm0ta2VybmVsQGxpc3RzLmluZnJhZGVhZC5vcmc7IGRldmljZXRyZWVAdmdlci5rZXJuZWwub3Jn
Ow0KPiBZdWFuemhpY2hhbmc7IFpodWRhY2FpOyB6aGFuZ2p1a3VvOyBxaXV6aGVuZmE7IGxpdWRv
bmdkb25nIChDKTsNCj4gcWl1amlhbmc7IHh1d2VpIChPKTsgTGlndW96aHUgKEtlbm5ldGgpDQo+
IFN1YmplY3Q6IFJlOiBbUEFUQ0ggdjcgMy82XSBQQ0k6IGRlc2lnbndhcmU6IEFkZCBBUk02NCBz
dXBwb3J0DQo+IA0KPiBPbiAyMDE1LzgvMjEgMjI6MTksIEdhYnJpZWxlIFBhb2xvbmkgd3JvdGU6
DQo+ID4gSGkgTGl2aXUNCj4gPg0KPiA+IE1hbnkgVGhhbmtzIGZvciByZXZpZXdpbmcNCj4gPg0K
PiA+PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiA+PiBGcm9tOiBsaW51eC1wY2ktb3du
ZXJAdmdlci5rZXJuZWwub3JnIFttYWlsdG86bGludXgtcGNpLQ0KPiA+PiBvd25lckB2Z2VyLmtl
cm5lbC5vcmddIE9uIEJlaGFsZiBPZiBMaXZpdSBEdWRhdQ0KPiA+PiBTZW50OiBGcmlkYXksIEF1
Z3VzdCAyMSwgMjAxNSAyOjQzIFBNDQo+ID4+IFRvOiBHYWJyaWVsZSBQYW9sb25pDQo+ID4+IENj
OiBMdWNhcyBTdGFjaDsgV2FuZ3pob3UgKEIpOyBCam9ybiBIZWxnYWFzOyBqaW5nb29oYW4xQGdt
YWlsLmNvbTsNCj4gPj4gUHJhdHl1c2ggQW5hbmQ7IEFybmQgQmVyZ21hbm47IGxpbnV4QGFybS5s
aW51eC5vcmcudWs7DQo+ID4+IHRob21hcy5wZXRhenpvbmlAZnJlZS1lbGVjdHJvbnMuY29tOyBM
b3JlbnpvIFBpZXJhbGlzaTsgSmFtZXMgTW9yc2U7DQo+ID4+IGphc29uQGxha2VkYWVtb24ubmV0
OyByb2JoQGtlcm5lbC5vcmc7IGxpbnV4LXBjaUB2Z2VyLmtlcm5lbC5vcmc7DQo+ID4+IGxpbnV4
LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZzsgZGV2aWNldHJlZUB2Z2VyLmtlcm5lbC5v
cmc7DQo+ID4+IFl1YW56aGljaGFuZzsgWmh1ZGFjYWk7IHpoYW5nanVrdW87IHFpdXpoZW5mYTsg
bGl1ZG9uZ2RvbmcgKEMpOw0KPiA+PiBxaXVqaWFuZzsgeHV3ZWkgKE8pOyBMaWd1b3podSAoS2Vu
bmV0aCkNCj4gPj4gU3ViamVjdDogUmU6IFtQQVRDSCB2NyAzLzZdIFBDSTogZGVzaWdud2FyZTog
QWRkIEFSTTY0IHN1cHBvcnQNCj4gPj4NCj4gPj4gT24gVGh1LCBBdWcgMjAsIDIwMTUgYXQgMTI6
MTA6MjRQTSArMDEwMCwgR2FicmllbGUgUGFvbG9uaSB3cm90ZToNCj4gPj4+IEhpIEx1Y2FzDQo+
ID4+Pg0KPiA+Pj4gQWdhaW4gbWFueSB0aGFua3MgZm9yIGV4cGxhaW5pbmcgYW5kIGZvciB5b3Vy
IHRpbWUuDQo+ID4+Pg0KPiA+Pj4gSSBnb3QgeW91ciBwb2ludCBub3cgYW5kIEkgaGF2ZSBkdWcg
YSBiaXQgYmV0dGVyIGluIHRoZSBQQ0lfRE9NQUlOUw0KPiA+PiBjb2RlLg0KPiA+Pj4NCj4gPj4+
IEhvd2V2ZXIgSSBoYXZlIGEgcXVlc3Rpb24uLi5zZWUgaW5saW5lIGJlbG93DQo+ID4+Pg0KPiA+
Pj4+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+ID4+Pj4gRnJvbTogTHVjYXMgU3RhY2gg
W21haWx0bzpsLnN0YWNoQHBlbmd1dHJvbml4LmRlXQ0KPiA+Pj4+IFNlbnQ6IFRodXJzZGF5LCBB
dWd1c3QgMjAsIDIwMTUgOToyNyBBTQ0KPiA+Pj4+IFRvOiBHYWJyaWVsZSBQYW9sb25pDQo+ID4+
Pj4gQ2M6IFdhbmd6aG91IChCKTsgQmpvcm4gSGVsZ2FhczsgamluZ29vaGFuMUBnbWFpbC5jb207
IFByYXR5dXNoDQo+ID4+IEFuYW5kOw0KPiA+Pj4+IEFybmQgQmVyZ21hbm47IGxpbnV4QGFybS5s
aW51eC5vcmcudWs7IHRob21hcy5wZXRhenpvbmlAZnJlZS0NCj4gPj4+PiBlbGVjdHJvbnMuY29t
OyBsb3JlbnpvLnBpZXJhbGlzaUBhcm0uY29tOyBqYW1lcy5tb3JzZUBhcm0uY29tOw0KPiA+Pj4+
IExpdml1LkR1ZGF1QGFybS5jb207IGphc29uQGxha2VkYWVtb24ubmV0OyByb2JoQGtlcm5lbC5v
cmc7IGxpbnV4LQ0KPiA+Pj4+IHBjaUB2Z2VyLmtlcm5lbC5vcmc7IGxpbnV4LWFybS1rZXJuZWxA
bGlzdHMuaW5mcmFkZWFkLm9yZzsNCj4gPj4+PiBkZXZpY2V0cmVlQHZnZXIua2VybmVsLm9yZzsg
WXVhbnpoaWNoYW5nOyBaaHVkYWNhaTsgemhhbmdqdWt1bzsNCj4gPj4+PiBxaXV6aGVuZmE7IGxp
dWRvbmdkb25nIChDKTsgcWl1amlhbmc7IHh1d2VpIChPKTsgTGlndW96aHUgKEtlbm5ldGgpDQo+
ID4+Pj4gU3ViamVjdDogUmU6IFtQQVRDSCB2NyAzLzZdIFBDSTogZGVzaWdud2FyZTogQWRkIEFS
TTY0IHN1cHBvcnQNCj4gPj4+Pg0KPiA+Pj4+IEhpIEdhYiwNCj4gPj4+Pg0KPiA+Pj4+IEFtIE1p
dHR3b2NoLCBkZW4gMTkuMDguMjAxNSwgMTY6MzQgKzAwMDAgc2NocmllYiBHYWJyaWVsZSBQYW9s
b25pOg0KPiA+Pj4+PiBIaSBMdWNhcw0KPiA+Pj4+Pg0KPiA+Pj4+PiBGaXJzdCBvZiBhbGwgbWFu
eSB0aGFua3MgZm9yIHRoZSBxdWljayByZXBseSwgcmVhbGx5IGFwcHJlY2lhdGVkDQo+ID4+Pj4+
DQo+ID4+Pj4+PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiA+Pj4+Pj4gRnJvbTogTHVj
YXMgU3RhY2ggW21haWx0bzpsLnN0YWNoQHBlbmd1dHJvbml4LmRlXQ0KPiA+Pj4+Pj4gU2VudDog
V2VkbmVzZGF5LCBBdWd1c3QgMTksIDIwMTUgNDozNyBQTQ0KPiA+Pj4+Pj4gVG86IEdhYnJpZWxl
IFBhb2xvbmkNCj4gPj4+Pj4+IENjOiBXYW5nemhvdSAoQik7IEJqb3JuIEhlbGdhYXM7IGppbmdv
b2hhbjFAZ21haWwuY29tOyBQcmF0eXVzaA0KPiA+Pj4+IEFuYW5kOw0KPiA+Pj4+Pj4gQXJuZCBC
ZXJnbWFubjsgbGludXhAYXJtLmxpbnV4Lm9yZy51azsgdGhvbWFzLnBldGF6em9uaUBmcmVlLQ0K
PiA+Pj4+Pj4gZWxlY3Ryb25zLmNvbTsgbG9yZW56by5waWVyYWxpc2lAYXJtLmNvbTsgamFtZXMu
bW9yc2VAYXJtLmNvbTsNCj4gPj4+Pj4+IExpdml1LkR1ZGF1QGFybS5jb207IGphc29uQGxha2Vk
YWVtb24ubmV0OyByb2JoQGtlcm5lbC5vcmc7DQo+ID4+IGxpbnV4LQ0KPiA+Pj4+Pj4gcGNpQHZn
ZXIua2VybmVsLm9yZzsgbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnOw0KPiA+
Pj4+Pj4gZGV2aWNldHJlZUB2Z2VyLmtlcm5lbC5vcmc7IFl1YW56aGljaGFuZzsgWmh1ZGFjYWk7
IHpoYW5nanVrdW87DQo+ID4+Pj4+PiBxaXV6aGVuZmE7IGxpdWRvbmdkb25nIChDKTsgcWl1amlh
bmc7IHh1d2VpIChPKTsgTGlndW96aHUNCj4gPj4gKEtlbm5ldGgpDQo+ID4+Pj4+PiBTdWJqZWN0
OiBSZTogW1BBVENIIHY3IDMvNl0gUENJOiBkZXNpZ253YXJlOiBBZGQgQVJNNjQgc3VwcG9ydA0K
PiA+Pj4+Pj4NCj4gPj4+Pj4+IEhpIEdhYiwNCj4gPj4+Pj4+DQo+ID4+Pj4+PiBBbSBNaXR0d29j
aCwgZGVuIDE5LjA4LjIwMTUsIDE1OjE2ICswMDAwIHNjaHJpZWIgR2FicmllbGUNCj4gPj4gUGFv
bG9uaToNCj4gPj4+Pj4+PiBIaSBMdWNhcw0KPiA+Pj4+Pj4+DQo+ID4+Pj4+Pj4gSSBoYXZlIHJl
d3JpdHRlbiB0aGUgcGF0Y2ggdG8gdGFrZSBpbnRvIGFjY291bnQgbXVsdGlwbGUNCj4gPj4+PiBj
b250cm9sbGVycy4NCj4gPj4+Pj4+Pg0KPiA+Pj4+Pj4+IEFzIHlvdSBjYW4gc2VlIG5vdyB0aGVy
ZSBpcyBhIHN0YXRpYyB2YXIgaW4NCj4gPj4gZHdfcGNpZV9ob3N0X2luaXQoKQ0KPiA+Pj4+IHRo
YXQNCj4gPj4+Pj4+IHRyYWNrcw0KPiA+Pj4+Pj4+IHRoZSBidXMgbnVtYmVycyB1c2VkLg0KPiA+
Pj4+Pj4NCj4gPj4+Pj4+IFRoaXMgaXMgd3JvbmcuIFRoZSBEVCBzcGVjaWZpZXMgdGhlIHZhbGlk
IGJ1cyBudW1iZXIgcmFuZ2UuIFlvdQ0KPiA+PiBjYW4NCj4gPj4+PiBub3QNCj4gPj4+Pj4+IGp1
c3QgYXNzaWduIHRoZSBuZXh0IGZyZWUgYnVzIG51bWJlciB0byB0aGUgcm9vdCBidXMuDQo+ID4+
Pj4+DQo+ID4+Pj4+IEkgdGhpbmsgdGhpcyBpcyB3aGF0IGlzIGJlaW5nIGRvbmUgaW4NCj4gPj4+
Pj4gaHR0cDovL2x4ci5mcmVlLQ0KPiA+PiBlbGVjdHJvbnMuY29tL3NvdXJjZS9hcmNoL2FybS9r
ZXJuZWwvYmlvczMyLmMjTDQ5NQ0KPiA+Pj4+PiBhbmQgY3VycmVudGx5IGRlc2lnbndhcmUgYXNz
aWducyB0aGUgcm9vdCBidXMgbnVtYmVyIGluDQo+ID4+Pj4+IGh0dHA6Ly9seHIuZnJlZS1lbGVj
dHJvbnMuY29tL3NvdXJjZS9kcml2ZXJzL3BjaS9ob3N0L3BjaWUtDQo+ID4+Pj4gZGVzaWdud2Fy
ZS5jI0w3MzANCj4gPj4+Pj4NCj4gPj4+PiBZb3UgZm91bmQgdGhlIHJpZ2h0IHNwb3QuIEl0IHdv
cmtzIGEgYml0IGRpZmZlcmVudCB0aGFuIEkgcmVtZW1iZXIsDQo+ID4+IGJ1dA0KPiA+Pj4+IGlz
IGxlc3MgYnJva2VuIHRoYW4geW91ciBjdXJyZW50IGNvZGUuIDopDQo+ID4+Pj4NCj4gPj4+PiBJ
dCBhY3R1YWxseSBhc3NpZ25zIHRoZSBuZXh0IGluc3RhbmNlIGEgcm9vdCBidXMgbnVtYmVyIGJl
aGluZCB0aGUNCj4gPj4+PiBjdXJyZW50IGluc3RhbmNlcyBidXMgcmFuZ2UuIFBsZWFzZSBub3Rl
IHRoZSBkaWZmZXJlbmNlIHRvIHlvdXINCj4gPj4gY29kZQ0KPiA+Pj4+IHdoaWNoIGFzc2lnbnMg
dGhlIG5leHQgZnJlZSBidXMgbnVtYmVyLCB3aGljaCBtYXkgc3RpbGwgbGF5IHdpdGhpbg0KPiA+
PiB0aGUNCj4gPj4+PiBjdXJyZW50IGluc3RhbmNlcyBidXMgcmFuZ2UuDQo+ID4+DQo+ID4+IEhp
IEdhYnJpZWxlLA0KPiA+Pg0KPiA+Pj4NCj4gPj4+IE1tbW0gaGVyZSBJIGhhdmUgZG9uZSBhIG1p
c3Rha2U6IGluIHRoZSBjdXJyZW50IGRlc2lnbndhcmUgdGhlDQo+IG51bWJlcg0KPiA+PiBvZiBo
dw0KPiA+Pj4gY29udHJvbGxlcnMgaXMgYWx3YXlzIDENCj4gPj4+IGh0dHA6Ly9seHIuZnJlZS1l
bGVjdHJvbnMuY29tL3NvdXJjZS9kcml2ZXJzL3BjaS9ob3N0L3BjaWUtDQo+ID4+IGRlc2lnbndh
cmUuYyNMNTEwDQo+ID4+PiBTbyB0aGUgbG9vcCBpbiBiaW9zMzIuYyBkb2VzIG5vdCB3b3JrIG9u
IG11bHRpcGxlIFBDSWUgcG9ydHMuLi4NCj4gPj4NCj4gPj4gQmlvczMyLmMgaXMgYnJva2VuIGZv
ciBtdWx0aXBsZSBQQ0llIGhvc3RzIGZvciBtdWx0aXBsZSByZWFzb25zLA0KPiB0aGlzDQo+ID4+
IGlzIGp1c3QNCj4gPj4gb25lIG9mIHRoZW0uIEhlbmNlIHRoZSBlZmZvcnQgdG8gZ2V0IHJpZCBv
ZiBpdCBmb3IgbWFpbnRhaW5lZA0KPiBkcml2ZXJzLg0KPiA+DQo+ID4gQXMgeW91IGNhbiBzZWUg
d2UncmUgcHVzaGluZyBoYXJkIGZvciB0aGlzIDopDQo+ID4NCj4gDQo+IEhvdyBhYm91dCB3ZSBw
YXNzIHBwLT5idXNuLT5zdGFydCB0byBwY2lfY3JlYXRlX3Jvb3RfYnVzIGFzIHJvb3QgYnVzDQo+
IG51bWJlcj8NCj4gV2UgZ2V0IHBwLT5idXNuLT5zdGFydCBmcm9tIHJlc291cmNlIGxpc3QocmVz
KSB3aG9zZSBlbGVtZW50cyBjb21lIGZyb20NCj4gb2ZfcGNpX2dldF9ob3N0X2JyaWRnZV9yZXNv
dXJjZXMuDQo+IA0KPiBJZiB0aGVyZSBpcyBhIGJ1cy1yYW5nZSBpdGVtIGluIGR0cywgcm9vdCBi
dXMgbnVtYmVyIHdpbGwgZ2V0IGZyb20gaXQuDQo+IE9wcG9zaXRlbHksIHJvb3QgYnVzIG51bWJl
ciB3aWxsIGJlIGRlZmF1bHQgdmFsdWUoMHgwKS4NCj4gDQo+IFRoYW5rcywNCj4gWmhvdQ0KDQpT
b3VuZHMgZ29vZCB0byBtZS4gU28gd2UgY2FuIHJlbW92ZSByb290X2J1c19ucg0KDQo+IA0KPiA+
Pg0KPiA+Pj4gSG93ZXZlciB5b3VyIGNvbW1lbnQgYWJvdXQgUENJX0RPTUFJTlMgZW5saWdodGVu
ZWQgbXkgbWluZCBhbmQgbm93DQo+IEkNCj4gPj4gc2VlDQo+ID4+PiB0aGF0IHdoZW4gQ09ORklH
X1BDSV9ET01BSU5TIGlzIGRlZmluZWQgd2UgaGF2ZSB0aGUgZG9tYWlucyBudW1iZXJzDQo+ID4+
PiAodHJhY2tlZCBieSBfX2RvbWFpbl9ucikuDQo+ID4+DQo+ID4+IENPTkZJR19QQ0lfRE9NQUlO
UyBpbiBpdHNlbGYgZG9lc24ndCBkbyBtdWNoIHdpdGhvdXQgYWRkaW5nIGNvZGUgdG8NCj4gPj4g
eW91ciBkcml2ZXIuDQo+ID4+IFlvdSBjb3VsZCByZXF1ZXN0IGEgbmV3IGRvbWFpbiBmb3IgZWFj
aCBjb250cm9sbGVyIHdpdGggYSBzcGVjaWFsDQo+ID4+IHByb3BlcnR5IHRvDQo+ID4+IGRpc2Fi
bGUgdGhhdCBiZWhhdmlvdXIgaW4gdGhlIGR0cywgb3IgeW91IGNvdWxkIGVuYWJsZQ0KPiA+PiBD
T05GSUdfUENJX0RPTUFJTlNfR0VORVJJQw0KPiA+PiB3aGljaCB3aWxsIGdpdmUgeW91IGEgbmV3
IGRvbWFpbiBhdXRvbWF0aWNhbGx5Lg0KPiA+DQo+ID4gU28gZmFyIEkgc2VlIHRoYXQgZm9yIEFS
TSBhbmQgQVJNNjQgQ09ORklHX1BDSV9ET01BSU5TX0dFTkVSSUMNCj4gZGVmYXVsdHMgdG8NCj4g
PiB0aGUgc2FtZSB2YWx1ZSBhcyBDT05GSUdfUENJX0RPTUFJTlMgKHNlZSBhcmNoL2FybS9LY29u
ZmlnLA0KPiBhcmNoL2FybTY0L0tjb25maWcpLg0KPiA+IFNvIEkgdGhpbmsgdGhpcyBpcyBob3cg
Y3VycmVudCBkZXNpZ253YXJlIGJhc2VkIGRyaXZlcnMgZ2V0IG11bHRpcGxlDQo+IFBDSWUNCj4g
PiBjb250cm9sbGVyIHRvIHdvcmsgKHRoZXkganVzdCBlbmFibGUgQ09ORklHX1BDSV9ET01BSU5T
KS4uLg0KPiA+DQo+ID4NCj4gPg0KPiA+Pg0KPiA+Pj4gU28gKGNvcnJlY3QgbWUgaWYgSSBhbSB3
cm9uZykgaWYgd2UgaGF2ZSAyIFBDSWUgcG9ydHMgdGhhdCBkbyBub3QNCj4gPj4gc3BlY2lmeQ0K
PiA+Pj4gdGhlICJidXMtcmFuZ2UiIHByb3BlcnR5LCBib3RoIHJvb3QgcG9ydHMgd2lsbCBlbnVt
ZXJhdGUgc3RhcnRpbmcNCj4gPj4gZnJvbQ0KPiA+Pj4gcm9vdF9idXNfbnIgPSAwIGFuZCBldmVy
eXRoaW5nIHdpbGwgc3RpbGwgd29yayBvay4NCj4gPj4NCj4gPj4gQ29ycmVjdC4NCj4gPj4NCj4g
Pj4gQmVzdCByZWdhcmRzLA0KPiA+PiBMaXZpdQ0KPiA+Pg0KPiA+Pj4NCj4gPj4+IFNvIGlmIG15
IGFzc3VtcHRpb24gaXMgY29ycmVjdCwgSSBkbyBub3Qgc2VlIHdoeSB0aGUgb3JnaW5hbCBwYXRj
aA0KPiA+PiBmcm9tIFdhbmcNCj4gPj4+IFpob3UgaXMgd3JvbmcuDQo+ID4+PiBUaGUgb25seSBw
b2ludCBjYW4gYmUgdGhhdCBhc3NpZ25pbmcgcHAtPnJvb3RfYnVzX25yID0gMCBpcyBub3QNCj4g
Pj4gcmVxdWlyZWQNCj4gPj4+IGFzIHBwIG1lbW9yeSBpcyBremFsbG9jJ2VkIChhbiB0aGVyZWZv
cmUgaW5pdCB0byB6ZXJvKS4NCj4gPj4+DQo+ID4+Pg0KPiA+Pj4+DQo+ID4+Pj4+DQo+ID4+Pj4+
IEluIGdlbmVyYWwgSSBhZ3JlZSB3aXRoIHlvdSBidXQgaWYgeW91IGxvb2sgYXQgYWxsIHRoZSBj
dXJyZW50DQo+ID4+Pj4gZHJpdmVycw0KPiA+Pj4+PiBiYXNlZCBvbiBkZXNpZ253YXJlIG5vbmUg
b2YgdGhlbSBkZWZpbmUgdGhlICJidXMtcmFuZ2UiIGR0Yg0KPiA+PiBwcm9wZXJ0eS4NCj4gPj4+
Pj4gVGhlcmVmb3JlIGRvaW5nIGFzIHlvdSBzYXkgd291bGQgYnJlYWsgdGhlIGN1cnJlbnQgZHJp
dmVyIHdoZW4gd2UNCj4gPj4+PiBoYXZlDQo+ID4+Pj4+IG11bHRpcGxlIGNvbnRyb2xsZXJzLi4u
YW0gSSByaWdodD8NCj4gPj4+Pj4NCj4gPj4+PiBUaGUgY3VycmVudCBfY29kZV8gd29ya3MgZmlu
ZSBmb3IgbXVsdGlwbGUgY29udHJvbGxlcnMuIEl0J3MganVzdA0KPiA+PiB0aGF0DQo+ID4+Pj4g
eW91IG11c3QgZGVmaW5lIHRoZSBidXMgcmFuZ2UgcHJvcGVydHkgaW4gdGhlIERUQiBpZiB5b3Ug
d2FudCB0bw0KPiA+PiBlbmFibGUNCj4gPj4+PiBtdWx0aXBsZSBpbnN0YW5jZXMgb2Ygb25lIGNv
bnRyb2xsZXIgYW5kIHN1cHBvcnQgYSBrZXJuZWwgd2l0aG91dA0KPiA+PiBQQ0kNCj4gPj4+PiBk
b21haW5zIHN1cHBvcnQuIEFzIGFsbCBjdXJyZW50IGltcGxlbWVudGF0aW9ucyBoYXZlIG9ubHkg
YSBzaW5nbGUNCj4gPj4+PiBpbnN0YW5jZSBvZiB0aGUgY29udHJvbGxlciBwZXIgU29DLCBvciBk
ZXBlbmQgb24gUENJIGRvbWFpbg0KPiBzdXBwb3J0LA0KPiA+Pj4+IGl0J3MgdG90YWxseSBmaW5l
IGZvciB0aGVtIHRvIG5vdCBkZWZpbmUgdGhlIGJ1cyByYW5nZXMgcHJvcGVydHksDQo+ID4+IGFz
DQo+ID4+Pj4gaXQncyBhbiBvcHRpb25hbCBwcm9wZXJ0eSBhbmQgaXQgaXMgd2VsbCBkZWZpbmVk
IGhvdyB0aGluZ3MgYmVoYXZlDQo+ID4+IGlmDQo+ID4+Pj4gaXQNCj4gPj4+PiBpcyBhYnNlbnQu
IFdlIGFic29sdXRlbHkgbmVlZCB0byBrZWVwIHRoYXQgc3BlY2lmaWVkIGJlaGF2aW9yLg0KPiA+
Pj4+DQo+ID4+Pj4+IElmIHRoYXQgaXMgdGhlIGNhc2UgaW4gb3JkZXIgdG8gZml4IHRoaXMgaW4g
dGhlIHdheSB5b3Ugc2F5IEkNCj4gPj4gd291bGQNCj4gPj4+PiBuZWVkDQo+ID4+Pj4+IHRvIGFz
c2lnbiAiYnVzLXJhbmdlIiBmb3IgYWxsIHRoZSBQQ0llIGRyaXZlcnMgd2l0aCBtdWx0aXBsZQ0K
PiA+Pj4+IGNvbnRyb2xsZXJzOg0KPiA+Pj4+PiBpbiB0aGlzIGNhc2UgSSB3b3VsZCBzcGxpdCB0
aGUgZGVmYXVsdCByYW5nZSBldmVubHkgKHRoYXQgaXMsIGlmDQo+ID4+IHdlDQo+ID4+Pj4gaGF2
ZQ0KPiA+Pj4+PiB0d28gY29udHJvbGxlcnMgSSB3b3VsZCBkZWZpbmUgImJ1cy1yYW5nZSIgIDAt
MTI3IGFuZCAxMjgtMjU1KQ0KPiA+Pj4+Pg0KPiA+Pj4+PiBJZiB5b3UgdGhpbmsgdGhpcyBzb2x1
dGlvbiBpcyBvayBJIGNhbiBnbyBmb3IgaXQuIE15IG9ubHkgZG91YnQNCj4gPj4gd2FzDQo+ID4+
Pj4gYWJvdXQNCj4gPj4+Pj4gdG91Y2hpbmcgb3RoZXIgdmVuZG9ycyBEVEJzLi4uLg0KPiA+Pj4+
Pg0KPiA+Pj4+IFlvdSBkb24ndCBuZWVkIHRvIHRvdWNoIGFueSBvZiB0aGUgY3VycmVudCBEVEJz
LCBhcyB0aGV5IGFyZSBmaW5lDQo+ID4+IHdpdGgNCj4gPj4+PiB0aGUgZGVmYXVsdCBidXMgcmFu
Z2UgYmVoYXZpb3IuIFlvdSBuZWVkIHRvIGtlZXAgdGhlIHNwZWNpZmllZA0KPiA+PiBiZWhhdmlv
cg0KPiA+Pj4+IG9mIHRoZSBidXMgcmFuZ2UgcHJvcGVydHkgd2l0aCB0aGUgbmV3IGNvZGUuDQo+
ID4+Pj4NCj4gPj4+PiBSZWdhcmRzLA0KPiA+Pj4+IEx1Y2FzDQo+ID4+Pj4+DQo+ID4+Pj4+Pg0K
PiA+Pj4+Pj4gSXQgaXMgcGVyZmVjdGx5IHZhbGlkIHRvIGhhdmUgYSBidXMgcmFuZ2Ugb2YgMHgw
MC0weDEwIGFzc2lnbmVkDQo+ID4+IHRvDQo+ID4+Pj4gb25lDQo+ID4+Pj4+PiBpbnN0YW5jZSBh
bmQgMHg1MC0weGZmIHRvIHRoZSBuZXh0IGluc3RhbmNlLiBBZGRpdGlvbmFsIHdpdGgNCj4gPj4g
UENJZQ0KPiA+Pj4+Pj4gaG90cGx1ZyB5b3UgbWF5IG5vdCB1c2UgdGhlIGZ1bGwgcmFuZ2Ugb2Yg
dGhlIGJ1cyBudW1iZXJzIG9uDQo+ID4+IG9uZQ0KPiA+Pj4+Pj4gaW5zdGFuY2UgYXQgdGhlIGZp
cnN0IHNjYW4sIGJ1dCBvbmx5IGxhdGVyIHBvcHVsYXRlIG1vcmUgYnVzZXMNCj4gPj4gd2hlbg0K
PiA+Pj4+Pj4gbW9yZQ0KPiA+Pj4+Pj4gYnJpZGdlcyBhcmUgYWRkZWQgdG8gdGhlIHRyZWUuDQo+
ID4+Pj4+Pg0KPiA+Pj4+Pj4+IERyaXZlcnMgdGhhdCBkbyBub3Qgc3BlY2lmeSB0aGUgYnVzIHJh
bmdlIGluIHRoZSBEVEIgc2V0IHBwLQ0KPiA+Pj4+Pj4+IHJvb3RfYnVzX25yID0gRFdfUk9PVF9O
Ul9VTkRFRklORUQuDQo+ID4+Pj4+Pj4gRGVzaWdud2FyZSB3aWxsIGNoZWNrIGlmIHRoZSBmbGFn
IGlzIHNldCBhbmQgd2lsbCB1c2UgdGhlDQo+ID4+Pj4gYXV0b21hdGljDQo+ID4+Pj4+PiBidXMg
cmFuZ2UNCj4gPj4+Pj4+PiBhc3NpZ25tZW50Lg0KPiA+Pj4+Pj4NCj4gPj4+Pj4+IE5vLCBwbGVh
c2UgbGV0cyBnZXQgcmlkIG9mIHRoaXMgYXNzaWdubWVudCBhbHRvZ2V0aGVyLiBUaGUgZ2x1ZQ0K
PiA+Pj4+IGRyaXZlcnMNCj4gPj4+Pj4+IGhhdmUgbm8gYnVzaW5lc3MgaW4gYXNzaWduaW5nIHRo
ZSBidXMgcmFuZ2UuIFBsZWFzZSByZW1vdmUgdGhlDQo+ID4+Pj4+PiBwcC0+cm9vdF9idXNfbnIg
YXNzaWdubWVudCBmcm9tIGFsbCB0aGUgZ2x1ZSBkcml2ZXJzLg0KPiA+Pj4+Pj4NCj4gPj4+Pj4+
ICJidXMgcmFuZ2UiIGlzIGEgZ2VuZXJpYyBEVyBQQ0llIHByb3BlcnR5LCBzbyBqdXN0IHBhcnNl
IHRoZQ0KPiA+PiByb290DQo+ID4+Pj4gYnVzDQo+ID4+Pj4+PiBudW1iZXIgZnJvbSB0aGUgRFQs
IGl0IGlzIGhhbmRsZWQgdGhlIHNhbWUgd2F5IGZvciBhbGwgdGhlIERXDQo+ID4+IGJhc2VkDQo+
ID4+Pj4+PiBQQ0llDQo+ID4+Pj4+PiBkcml2ZXJzLiBUaGUgYmluZGluZ3Mgc3BlY2lmaWVzIHRo
YXQgaWYgdGhlIGJ1cyByYW5nZSBwcm9wZXJ0eQ0KPiA+PiBpcw0KPiA+Pj4+Pj4gbWlzc2luZyB0
aGUgcmFuZ2UgaXMgMHgwMC0weGZmLCBzbyB5b3UgY2FuIGRlZmF1bHQgdG8gMCBhcyB0aGUNCj4g
Pj4gcm9vdA0KPiA+Pj4+IGJ1cw0KPiA+Pj4+Pj4gbnVtYmVyIGluIHRoYXQgY2FzZS4NCj4gPj4+
Pj4+DQo+ID4+Pj4+PiBBbHNvIEkgd291bGQgdGhpbmsgdGhpcyBjb252ZXJzaW9uIHdhcnJhbnRz
IGEgcGF0Y2ggb24gaXRzIG93bg0KPiA+PiBhbmQNCj4gPj4+Pj4+IHNob3VsZCBub3QgYmUgbWl4
ZWQgaW4gdGhlIEFSTTY0IHN1cHBvcnQgcGF0Y2guDQo+ID4+Pj4+Pg0KPiA+Pj4+Pj4gUmVnYXJk
cywNCj4gPj4+Pj4+IEx1Y2FzDQo+ID4+Pj4+Pg0KPiA+Pj4+DQo+ID4+Pj4gLS0NCj4gPj4+PiBQ
ZW5ndXRyb25peCBlLksuICAgICAgICAgICAgIHwgTHVjYXMgU3RhY2ggICAgICAgICAgICAgICAg
IHwNCj4gPj4+PiBJbmR1c3RyaWFsIExpbnV4IFNvbHV0aW9ucyAgIHwgaHR0cDovL3d3dy5wZW5n
dXRyb25peC5kZS8gIHwNCj4gPj4+DQo+ID4+DQo+ID4+IC0tDQo+ID4+ID09PT09PT09PT09PT09
PT09PT09DQo+ID4+IHwgSSB3b3VsZCBsaWtlIHRvIHwNCj4gPj4gfCBmaXggdGhlIHdvcmxkLCAg
fA0KPiA+PiB8IGJ1dCB0aGV5J3JlIG5vdCB8DQo+ID4+IHwgZ2l2aW5nIG1lIHRoZSAgIHwNCj4g
Pj4gIFwgc291cmNlIGNvZGUhICAvDQo+ID4+ICAgLS0tLS0tLS0tLS0tLS0tDQo+ID4+ICAgICDC
r1xfKOODhClfL8KvDQo+ID4+DQo+ID4+IC0tDQo+ID4+IFRvIHVuc3Vic2NyaWJlIGZyb20gdGhp
cyBsaXN0OiBzZW5kIHRoZSBsaW5lICJ1bnN1YnNjcmliZSBsaW51eC1wY2kiDQo+IGluDQo+ID4+
IHRoZSBib2R5IG9mIGEgbWVzc2FnZSB0byBtYWpvcmRvbW9Admdlci5rZXJuZWwub3JnDQo+ID4+
IE1vcmUgbWFqb3Jkb21vIGluZm8gYXQgIGh0dHA6Ly92Z2VyLmtlcm5lbC5vcmcvbWFqb3Jkb21v
LWluZm8uaHRtbA0KPiANCg0K

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

* [PATCH v7 3/6] PCI: designware: Add ARM64 support
@ 2015-08-24  8:28                       ` Gabriele Paoloni
  0 siblings, 0 replies; 53+ messages in thread
From: Gabriele Paoloni @ 2015-08-24  8:28 UTC (permalink / raw)
  To: linux-arm-kernel



> -----Original Message-----
> From: Wangzhou (B)
> Sent: Monday, August 24, 2015 7:26 AM
> To: Gabriele Paoloni
> Cc: Liviu Dudau; Lucas Stach; Bjorn Helgaas; jingoohan1 at gmail.com;
> Pratyush Anand; Arnd Bergmann; linux at arm.linux.org.uk;
> thomas.petazzoni at free-electrons.com; Lorenzo Pieralisi; James Morse;
> jason at lakedaemon.net; robh at kernel.org; linux-pci at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.org;
> Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; liudongdong (C);
> qiujiang; xuwei (O); Liguozhu (Kenneth)
> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> 
> On 2015/8/21 22:19, Gabriele Paoloni wrote:
> > Hi Liviu
> >
> > Many Thanks for reviewing
> >
> >> -----Original Message-----
> >> From: linux-pci-owner at vger.kernel.org [mailto:linux-pci-
> >> owner at vger.kernel.org] On Behalf Of Liviu Dudau
> >> Sent: Friday, August 21, 2015 2:43 PM
> >> To: Gabriele Paoloni
> >> Cc: Lucas Stach; Wangzhou (B); Bjorn Helgaas; jingoohan1 at gmail.com;
> >> Pratyush Anand; Arnd Bergmann; linux at arm.linux.org.uk;
> >> thomas.petazzoni at free-electrons.com; Lorenzo Pieralisi; James Morse;
> >> jason at lakedaemon.net; robh at kernel.org; linux-pci at vger.kernel.org;
> >> linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.org;
> >> Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; liudongdong (C);
> >> qiujiang; xuwei (O); Liguozhu (Kenneth)
> >> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> >>
> >> On Thu, Aug 20, 2015 at 12:10:24PM +0100, Gabriele Paoloni wrote:
> >>> Hi Lucas
> >>>
> >>> Again many thanks for explaining and for your time.
> >>>
> >>> I got your point now and I have dug a bit better in the PCI_DOMAINS
> >> code.
> >>>
> >>> However I have a question...see inline below
> >>>
> >>>> -----Original Message-----
> >>>> From: Lucas Stach [mailto:l.stach at pengutronix.de]
> >>>> Sent: Thursday, August 20, 2015 9:27 AM
> >>>> To: Gabriele Paoloni
> >>>> Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1 at gmail.com; Pratyush
> >> Anand;
> >>>> Arnd Bergmann; linux at arm.linux.org.uk; thomas.petazzoni at free-
> >>>> electrons.com; lorenzo.pieralisi at arm.com; james.morse at arm.com;
> >>>> Liviu.Dudau at arm.com; jason at lakedaemon.net; robh at kernel.org; linux-
> >>>> pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> >>>> devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> >>>> qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu (Kenneth)
> >>>> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> >>>>
> >>>> Hi Gab,
> >>>>
> >>>> Am Mittwoch, den 19.08.2015, 16:34 +0000 schrieb Gabriele Paoloni:
> >>>>> Hi Lucas
> >>>>>
> >>>>> First of all many thanks for the quick reply, really appreciated
> >>>>>
> >>>>>> -----Original Message-----
> >>>>>> From: Lucas Stach [mailto:l.stach at pengutronix.de]
> >>>>>> Sent: Wednesday, August 19, 2015 4:37 PM
> >>>>>> To: Gabriele Paoloni
> >>>>>> Cc: Wangzhou (B); Bjorn Helgaas; jingoohan1 at gmail.com; Pratyush
> >>>> Anand;
> >>>>>> Arnd Bergmann; linux at arm.linux.org.uk; thomas.petazzoni at free-
> >>>>>> electrons.com; lorenzo.pieralisi at arm.com; james.morse at arm.com;
> >>>>>> Liviu.Dudau at arm.com; jason at lakedaemon.net; robh at kernel.org;
> >> linux-
> >>>>>> pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> >>>>>> devicetree at vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> >>>>>> qiuzhenfa; liudongdong (C); qiujiang; xuwei (O); Liguozhu
> >> (Kenneth)
> >>>>>> Subject: Re: [PATCH v7 3/6] PCI: designware: Add ARM64 support
> >>>>>>
> >>>>>> Hi Gab,
> >>>>>>
> >>>>>> Am Mittwoch, den 19.08.2015, 15:16 +0000 schrieb Gabriele
> >> Paoloni:
> >>>>>>> Hi Lucas
> >>>>>>>
> >>>>>>> I have rewritten the patch to take into account multiple
> >>>> controllers.
> >>>>>>>
> >>>>>>> As you can see now there is a static var in
> >> dw_pcie_host_init()
> >>>> that
> >>>>>> tracks
> >>>>>>> the bus numbers used.
> >>>>>>
> >>>>>> This is wrong. The DT specifies the valid bus number range. You
> >> can
> >>>> not
> >>>>>> just assign the next free bus number to the root bus.
> >>>>>
> >>>>> I think this is what is being done in
> >>>>> http://lxr.free-
> >> electrons.com/source/arch/arm/kernel/bios32.c#L495
> >>>>> and currently designware assigns the root bus number in
> >>>>> http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
> >>>> designware.c#L730
> >>>>>
> >>>> You found the right spot. It works a bit different than I remember,
> >> but
> >>>> is less broken than your current code. :)
> >>>>
> >>>> It actually assigns the next instance a root bus number behind the
> >>>> current instances bus range. Please note the difference to your
> >> code
> >>>> which assigns the next free bus number, which may still lay within
> >> the
> >>>> current instances bus range.
> >>
> >> Hi Gabriele,
> >>
> >>>
> >>> Mmmm here I have done a mistake: in the current designware the
> number
> >> of hw
> >>> controllers is always 1
> >>> http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
> >> designware.c#L510
> >>> So the loop in bios32.c does not work on multiple PCIe ports...
> >>
> >> Bios32.c is broken for multiple PCIe hosts for multiple reasons,
> this
> >> is just
> >> one of them. Hence the effort to get rid of it for maintained
> drivers.
> >
> > As you can see we're pushing hard for this :)
> >
> 
> How about we pass pp->busn->start to pci_create_root_bus as root bus
> number?
> We get pp->busn->start from resource list(res) whose elements come from
> of_pci_get_host_bridge_resources.
> 
> If there is a bus-range item in dts, root bus number will get from it.
> Oppositely, root bus number will be default value(0x0).
> 
> Thanks,
> Zhou

Sounds good to me. So we can remove root_bus_nr

> 
> >>
> >>> However your comment about PCI_DOMAINS enlightened my mind and now
> I
> >> see
> >>> that when CONFIG_PCI_DOMAINS is defined we have the domains numbers
> >>> (tracked by __domain_nr).
> >>
> >> CONFIG_PCI_DOMAINS in itself doesn't do much without adding code to
> >> your driver.
> >> You could request a new domain for each controller with a special
> >> property to
> >> disable that behaviour in the dts, or you could enable
> >> CONFIG_PCI_DOMAINS_GENERIC
> >> which will give you a new domain automatically.
> >
> > So far I see that for ARM and ARM64 CONFIG_PCI_DOMAINS_GENERIC
> defaults to
> > the same value as CONFIG_PCI_DOMAINS (see arch/arm/Kconfig,
> arch/arm64/Kconfig).
> > So I think this is how current designware based drivers get multiple
> PCIe
> > controller to work (they just enable CONFIG_PCI_DOMAINS)...
> >
> >
> >
> >>
> >>> So (correct me if I am wrong) if we have 2 PCIe ports that do not
> >> specify
> >>> the "bus-range" property, both root ports will enumerate starting
> >> from
> >>> root_bus_nr = 0 and everything will still work ok.
> >>
> >> Correct.
> >>
> >> Best regards,
> >> Liviu
> >>
> >>>
> >>> So if my assumption is correct, I do not see why the orginal patch
> >> from Wang
> >>> Zhou is wrong.
> >>> The only point can be that assigning pp->root_bus_nr = 0 is not
> >> required
> >>> as pp memory is kzalloc'ed (an therefore init to zero).
> >>>
> >>>
> >>>>
> >>>>>
> >>>>> In general I agree with you but if you look at all the current
> >>>> drivers
> >>>>> based on designware none of them define the "bus-range" dtb
> >> property.
> >>>>> Therefore doing as you say would break the current driver when we
> >>>> have
> >>>>> multiple controllers...am I right?
> >>>>>
> >>>> The current _code_ works fine for multiple controllers. It's just
> >> that
> >>>> you must define the bus range property in the DTB if you want to
> >> enable
> >>>> multiple instances of one controller and support a kernel without
> >> PCI
> >>>> domains support. As all current implementations have only a single
> >>>> instance of the controller per SoC, or depend on PCI domain
> support,
> >>>> it's totally fine for them to not define the bus ranges property,
> >> as
> >>>> it's an optional property and it is well defined how things behave
> >> if
> >>>> it
> >>>> is absent. We absolutely need to keep that specified behavior.
> >>>>
> >>>>> If that is the case in order to fix this in the way you say I
> >> would
> >>>> need
> >>>>> to assign "bus-range" for all the PCIe drivers with multiple
> >>>> controllers:
> >>>>> in this case I would split the default range evenly (that is, if
> >> we
> >>>> have
> >>>>> two controllers I would define "bus-range"  0-127 and 128-255)
> >>>>>
> >>>>> If you think this solution is ok I can go for it. My only doubt
> >> was
> >>>> about
> >>>>> touching other vendors DTBs....
> >>>>>
> >>>> You don't need to touch any of the current DTBs, as they are fine
> >> with
> >>>> the default bus range behavior. You need to keep the specified
> >> behavior
> >>>> of the bus range property with the new code.
> >>>>
> >>>> Regards,
> >>>> Lucas
> >>>>>
> >>>>>>
> >>>>>> It is perfectly valid to have a bus range of 0x00-0x10 assigned
> >> to
> >>>> one
> >>>>>> instance and 0x50-0xff to the next instance. Additional with
> >> PCIe
> >>>>>> hotplug you may not use the full range of the bus numbers on
> >> one
> >>>>>> instance at the first scan, but only later populate more buses
> >> when
> >>>>>> more
> >>>>>> bridges are added to the tree.
> >>>>>>
> >>>>>>> Drivers that do not specify the bus range in the DTB set pp-
> >>>>>>> root_bus_nr = DW_ROOT_NR_UNDEFINED.
> >>>>>>> Designware will check if the flag is set and will use the
> >>>> automatic
> >>>>>> bus range
> >>>>>>> assignment.
> >>>>>>
> >>>>>> No, please lets get rid of this assignment altogether. The glue
> >>>> drivers
> >>>>>> have no business in assigning the bus range. Please remove the
> >>>>>> pp->root_bus_nr assignment from all the glue drivers.
> >>>>>>
> >>>>>> "bus range" is a generic DW PCIe property, so just parse the
> >> root
> >>>> bus
> >>>>>> number from the DT, it is handled the same way for all the DW
> >> based
> >>>>>> PCIe
> >>>>>> drivers. The bindings specifies that if the bus range property
> >> is
> >>>>>> missing the range is 0x00-0xff, so you can default to 0 as the
> >> root
> >>>> bus
> >>>>>> number in that case.
> >>>>>>
> >>>>>> Also I would think this conversion warrants a patch on its own
> >> and
> >>>>>> should not be mixed in the ARM64 support patch.
> >>>>>>
> >>>>>> Regards,
> >>>>>> Lucas
> >>>>>>
> >>>>
> >>>> --
> >>>> Pengutronix e.K.             | Lucas Stach                 |
> >>>> Industrial Linux Solutions   | http://www.pengutronix.de/  |
> >>>
> >>
> >> --
> >> ====================
> >> | I would like to |
> >> | fix the world,  |
> >> | but they're not |
> >> | giving me the   |
> >>  \ source code!  /
> >>   ---------------
> >>     ?\_(?)_/?
> >>
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-pci"
> in
> >> the body of a message to majordomo at vger.kernel.org
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

end of thread, other threads:[~2015-08-24  8:29 UTC | newest]

Thread overview: 53+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-08-17 11:55 [PATCH v7 0/6] PCI: hisi: Add PCIe host support for HiSilicon SoC Hip05 Zhou Wang
2015-08-17 11:55 ` Zhou Wang
2015-08-17 11:55 ` Zhou Wang
     [not found] ` <1439812554-180426-1-git-send-email-wangzhou1-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
2015-08-17 11:55   ` [PATCH v7 1/6] PCI: designware: move calculation of bus addresses to DRA7xx Zhou Wang
2015-08-17 11:55     ` Zhou Wang
2015-08-17 11:55     ` Zhou Wang
2015-08-17 11:55 ` [PATCH v7 2/6] ARM/PCI: remove align_resource in pci_sys_data Zhou Wang
2015-08-17 11:55   ` Zhou Wang
2015-08-17 11:55   ` Zhou Wang
2015-08-17 11:55 ` [PATCH v7 3/6] PCI: designware: Add ARM64 support Zhou Wang
2015-08-17 11:55   ` Zhou Wang
2015-08-17 11:55   ` Zhou Wang
2015-08-19 12:20   ` Zhou Wang
2015-08-19 12:20     ` Zhou Wang
2015-08-19 12:20     ` Zhou Wang
2015-08-19 12:54   ` Lucas Stach
2015-08-19 12:54     ` Lucas Stach
2015-08-19 15:16     ` Gabriele Paoloni
2015-08-19 15:16       ` Gabriele Paoloni
2015-08-19 15:16       ` Gabriele Paoloni
2015-08-19 15:37       ` Lucas Stach
2015-08-19 15:37         ` Lucas Stach
2015-08-19 15:37         ` Lucas Stach
2015-08-19 16:34         ` Gabriele Paoloni
2015-08-19 16:34           ` Gabriele Paoloni
2015-08-19 16:34           ` Gabriele Paoloni
2015-08-20  8:27           ` Lucas Stach
2015-08-20  8:27             ` Lucas Stach
2015-08-20  8:27             ` Lucas Stach
2015-08-20 11:10             ` Gabriele Paoloni
2015-08-20 11:10               ` Gabriele Paoloni
2015-08-20 11:10               ` Gabriele Paoloni
2015-08-21 13:42               ` Liviu Dudau
2015-08-21 13:42                 ` Liviu Dudau
2015-08-21 13:42                 ` Liviu Dudau
2015-08-21 14:19                 ` Gabriele Paoloni
2015-08-21 14:19                   ` Gabriele Paoloni
2015-08-21 14:19                   ` Gabriele Paoloni
2015-08-24  6:26                   ` Zhou Wang
2015-08-24  6:26                     ` Zhou Wang
2015-08-24  6:26                     ` Zhou Wang
2015-08-24  8:28                     ` Gabriele Paoloni
2015-08-24  8:28                       ` Gabriele Paoloni
2015-08-24  8:28                       ` Gabriele Paoloni
2015-08-17 11:55 ` [PATCH v7 4/6] PCI: hisi: Add PCIe host support for HiSilicon SoC Hip05 Zhou Wang
2015-08-17 11:55   ` Zhou Wang
2015-08-17 11:55   ` Zhou Wang
2015-08-17 11:55 ` [PATCH v7 5/6] Documentation: DT: Add HiSilicon PCIe host binding Zhou Wang
2015-08-17 11:55   ` Zhou Wang
2015-08-17 11:55   ` Zhou Wang
2015-08-17 11:55 ` [PATCH v7 6/6] MAINTAINERS: Add pcie-hisi maintainer Zhou Wang
2015-08-17 11:55   ` Zhou Wang
2015-08-17 11:55   ` Zhou Wang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.