All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v11 00/10] Support for creating generic PCI host bridges from DT
@ 2014-09-18  1:30 ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij
  Cc: Tanmay Inamdar, Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML

This is my version 11 of the attempt at adding support for generic PCI host
bridge controllers that make use of device tree information to
configure themselves. It contains minor cleanups compared with v10 to address
the existing comments.

I'm going to ask for this series to be included in -next.

Example on how a host bridge driver can use the series:

static int foohb_probe(struct platform_device *pdev)
{
	struct device_node *dn = pdev->dev.of_node;
	struct foohb_drv *drv;
	resource_size_t io_base = 0;  /* phys address for start of IO */
	struct pci_bus *bus;
	int err = 0;
	LIST_HEAD(res);

	.....
	err = of_pci_get_host_bridge_resources(dn, 0, 255, &res, &io_base);
	if (err)
		goto err_handling;
	err = foohb_setup(drv, ...., &res, &io_base);
	if (err)
		goto err_handling;
	.....
	pci_add_flags(....);
	bus = pci_scan_root_bus(&pdev->dev, 0, &foohb_ops, drv, &res);
	if (!bus)
		goto err_handling;
	....
	return 0;

err_handling:
	......
	return err;
}

Changes from v10:
 - Addressed Lorenzo's comments wrt io_base not being initialised inside the
   function that is supposed to modify it and also updated the comments to
   explain the values returned by the function
 - Updated pci_domain_nr helper function to split the allocation of the domain
   number from the parsing of the device tree to find maximum defined domain
   value
 - Fixed up the commit author for commit 6/10

Changes from v9:
 - Moved the DT parsing and assigning of IRQ patch from this series into arm64
   specific patch. This keeps existing pcibios_add_device() unchanged and adds
   an arch-specific version that can later be expanded to cater for dma_ops.
 - Incorporated the fix for users of of_pci_range_to_resources() into the patch
   that changes the behaviour for easier bisection.
 - Added fixes for tegra and rcar host drivers in their usage of
   of_pci_range_to_resources()
 - Broke up of_create_pci_host_bridge() to remove the callback function. The
   function left has been renamed into of_pci_get_host_bridge_resources(). The
   added benefit of that is that the architectural hook for fixing up host bridge
   resources now dissappears.
 - Reshuffled the way pgprot_device gets introduced. It is now part of the patch
   that adds pci_remap_iospace() function. The arm64 specific override is moved
   into the arm64 patchset.
 - Added a patch to pci_scan_root_bus() to assign unassigned resources if PCI
   flags are not PCI_PROBE_ONLY

v10 thread here: https://lkml.org/lkml/2014/9/8/333
v9 thread here, with links to previous threads: https://lkml.org/lkml/2014/8/12/361

Best regards,
Liviu

Catalin Marinas (1):
  PCI: Introduce generic domain handling for PCI busses.

Liviu Dudau (9):
  Fix ioport_map() for !CONFIG_GENERIC_IOMAP cases.
  PCI: Introduce helper functions to deal with PCI I/O ranges.
  ARM: Define PCI_IOBASE as the base of virtual PCI IO space.
  PCI: OF: Fix the conversion of IO ranges into IO resources.
  PCI: Create pci_host_bridge before its associated bus in
    pci_create_root_bus.
  OF: Introduce helper function for getting PCI domain_nr
  OF: PCI: Add support for parsing PCI host bridge resources from DT
  PCI: Assign unassigned bus resources in pci_scan_root_bus()
  PCI: Introduce pci_remap_iospace() for remapping PCI I/O bus resources
    into CPU space

 arch/arm/include/asm/io.h         |   1 +
 arch/arm/mach-integrator/pci_v3.c |  23 +++---
 drivers/of/address.c              | 146 ++++++++++++++++++++++++++++++++
 drivers/of/of_pci.c               | 170 ++++++++++++++++++++++++++++++++++++++
 drivers/pci/host/pci-tegra.c      |  10 ++-
 drivers/pci/host/pcie-rcar.c      |  21 +++--
 drivers/pci/pci.c                 |  33 ++++++++
 drivers/pci/probe.c               |  46 +++++++----
 include/asm-generic/io.h          |   2 +-
 include/asm-generic/pgtable.h     |   4 +
 include/linux/of_address.h        |  15 +---
 include/linux/of_pci.h            |  18 ++++
 include/linux/pci.h               |  24 ++++++
 13 files changed, 463 insertions(+), 50 deletions(-)

-- 
2.1.0


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

* [PATCH v11 00/10] Support for creating generic PCI host bridges from DT
@ 2014-09-18  1:30 ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij
  Cc: linux-arch, Sinan Kaya, Kukjin Kim, Device Tree ML, Jingoo Han,
	LKML, Grant Likely, Tanmay Inamdar, Suravee Suthikulanit, LAKML

This is my version 11 of the attempt at adding support for generic PCI host
bridge controllers that make use of device tree information to
configure themselves. It contains minor cleanups compared with v10 to address
the existing comments.

I'm going to ask for this series to be included in -next.

Example on how a host bridge driver can use the series:

static int foohb_probe(struct platform_device *pdev)
{
	struct device_node *dn = pdev->dev.of_node;
	struct foohb_drv *drv;
	resource_size_t io_base = 0;  /* phys address for start of IO */
	struct pci_bus *bus;
	int err = 0;
	LIST_HEAD(res);

	.....
	err = of_pci_get_host_bridge_resources(dn, 0, 255, &res, &io_base);
	if (err)
		goto err_handling;
	err = foohb_setup(drv, ...., &res, &io_base);
	if (err)
		goto err_handling;
	.....
	pci_add_flags(....);
	bus = pci_scan_root_bus(&pdev->dev, 0, &foohb_ops, drv, &res);
	if (!bus)
		goto err_handling;
	....
	return 0;

err_handling:
	......
	return err;
}

Changes from v10:
 - Addressed Lorenzo's comments wrt io_base not being initialised inside the
   function that is supposed to modify it and also updated the comments to
   explain the values returned by the function
 - Updated pci_domain_nr helper function to split the allocation of the domain
   number from the parsing of the device tree to find maximum defined domain
   value
 - Fixed up the commit author for commit 6/10

Changes from v9:
 - Moved the DT parsing and assigning of IRQ patch from this series into arm64
   specific patch. This keeps existing pcibios_add_device() unchanged and adds
   an arch-specific version that can later be expanded to cater for dma_ops.
 - Incorporated the fix for users of of_pci_range_to_resources() into the patch
   that changes the behaviour for easier bisection.
 - Added fixes for tegra and rcar host drivers in their usage of
   of_pci_range_to_resources()
 - Broke up of_create_pci_host_bridge() to remove the callback function. The
   function left has been renamed into of_pci_get_host_bridge_resources(). The
   added benefit of that is that the architectural hook for fixing up host bridge
   resources now dissappears.
 - Reshuffled the way pgprot_device gets introduced. It is now part of the patch
   that adds pci_remap_iospace() function. The arm64 specific override is moved
   into the arm64 patchset.
 - Added a patch to pci_scan_root_bus() to assign unassigned resources if PCI
   flags are not PCI_PROBE_ONLY

v10 thread here: https://lkml.org/lkml/2014/9/8/333
v9 thread here, with links to previous threads: https://lkml.org/lkml/2014/8/12/361

Best regards,
Liviu

Catalin Marinas (1):
  PCI: Introduce generic domain handling for PCI busses.

Liviu Dudau (9):
  Fix ioport_map() for !CONFIG_GENERIC_IOMAP cases.
  PCI: Introduce helper functions to deal with PCI I/O ranges.
  ARM: Define PCI_IOBASE as the base of virtual PCI IO space.
  PCI: OF: Fix the conversion of IO ranges into IO resources.
  PCI: Create pci_host_bridge before its associated bus in
    pci_create_root_bus.
  OF: Introduce helper function for getting PCI domain_nr
  OF: PCI: Add support for parsing PCI host bridge resources from DT
  PCI: Assign unassigned bus resources in pci_scan_root_bus()
  PCI: Introduce pci_remap_iospace() for remapping PCI I/O bus resources
    into CPU space

 arch/arm/include/asm/io.h         |   1 +
 arch/arm/mach-integrator/pci_v3.c |  23 +++---
 drivers/of/address.c              | 146 ++++++++++++++++++++++++++++++++
 drivers/of/of_pci.c               | 170 ++++++++++++++++++++++++++++++++++++++
 drivers/pci/host/pci-tegra.c      |  10 ++-
 drivers/pci/host/pcie-rcar.c      |  21 +++--
 drivers/pci/pci.c                 |  33 ++++++++
 drivers/pci/probe.c               |  46 +++++++----
 include/asm-generic/io.h          |   2 +-
 include/asm-generic/pgtable.h     |   4 +
 include/linux/of_address.h        |  15 +---
 include/linux/of_pci.h            |  18 ++++
 include/linux/pci.h               |  24 ++++++
 13 files changed, 463 insertions(+), 50 deletions(-)

-- 
2.1.0

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

* [PATCH v11 00/10] Support for creating generic PCI host bridges from DT
@ 2014-09-18  1:30 ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: linux-arm-kernel

This is my version 11 of the attempt at adding support for generic PCI host
bridge controllers that make use of device tree information to
configure themselves. It contains minor cleanups compared with v10 to address
the existing comments.

I'm going to ask for this series to be included in -next.

Example on how a host bridge driver can use the series:

static int foohb_probe(struct platform_device *pdev)
{
	struct device_node *dn = pdev->dev.of_node;
	struct foohb_drv *drv;
	resource_size_t io_base = 0;  /* phys address for start of IO */
	struct pci_bus *bus;
	int err = 0;
	LIST_HEAD(res);

	.....
	err = of_pci_get_host_bridge_resources(dn, 0, 255, &res, &io_base);
	if (err)
		goto err_handling;
	err = foohb_setup(drv, ...., &res, &io_base);
	if (err)
		goto err_handling;
	.....
	pci_add_flags(....);
	bus = pci_scan_root_bus(&pdev->dev, 0, &foohb_ops, drv, &res);
	if (!bus)
		goto err_handling;
	....
	return 0;

err_handling:
	......
	return err;
}

Changes from v10:
 - Addressed Lorenzo's comments wrt io_base not being initialised inside the
   function that is supposed to modify it and also updated the comments to
   explain the values returned by the function
 - Updated pci_domain_nr helper function to split the allocation of the domain
   number from the parsing of the device tree to find maximum defined domain
   value
 - Fixed up the commit author for commit 6/10

Changes from v9:
 - Moved the DT parsing and assigning of IRQ patch from this series into arm64
   specific patch. This keeps existing pcibios_add_device() unchanged and adds
   an arch-specific version that can later be expanded to cater for dma_ops.
 - Incorporated the fix for users of of_pci_range_to_resources() into the patch
   that changes the behaviour for easier bisection.
 - Added fixes for tegra and rcar host drivers in their usage of
   of_pci_range_to_resources()
 - Broke up of_create_pci_host_bridge() to remove the callback function. The
   function left has been renamed into of_pci_get_host_bridge_resources(). The
   added benefit of that is that the architectural hook for fixing up host bridge
   resources now dissappears.
 - Reshuffled the way pgprot_device gets introduced. It is now part of the patch
   that adds pci_remap_iospace() function. The arm64 specific override is moved
   into the arm64 patchset.
 - Added a patch to pci_scan_root_bus() to assign unassigned resources if PCI
   flags are not PCI_PROBE_ONLY

v10 thread here: https://lkml.org/lkml/2014/9/8/333
v9 thread here, with links to previous threads: https://lkml.org/lkml/2014/8/12/361

Best regards,
Liviu

Catalin Marinas (1):
  PCI: Introduce generic domain handling for PCI busses.

Liviu Dudau (9):
  Fix ioport_map() for !CONFIG_GENERIC_IOMAP cases.
  PCI: Introduce helper functions to deal with PCI I/O ranges.
  ARM: Define PCI_IOBASE as the base of virtual PCI IO space.
  PCI: OF: Fix the conversion of IO ranges into IO resources.
  PCI: Create pci_host_bridge before its associated bus in
    pci_create_root_bus.
  OF: Introduce helper function for getting PCI domain_nr
  OF: PCI: Add support for parsing PCI host bridge resources from DT
  PCI: Assign unassigned bus resources in pci_scan_root_bus()
  PCI: Introduce pci_remap_iospace() for remapping PCI I/O bus resources
    into CPU space

 arch/arm/include/asm/io.h         |   1 +
 arch/arm/mach-integrator/pci_v3.c |  23 +++---
 drivers/of/address.c              | 146 ++++++++++++++++++++++++++++++++
 drivers/of/of_pci.c               | 170 ++++++++++++++++++++++++++++++++++++++
 drivers/pci/host/pci-tegra.c      |  10 ++-
 drivers/pci/host/pcie-rcar.c      |  21 +++--
 drivers/pci/pci.c                 |  33 ++++++++
 drivers/pci/probe.c               |  46 +++++++----
 include/asm-generic/io.h          |   2 +-
 include/asm-generic/pgtable.h     |   4 +
 include/linux/of_address.h        |  15 +---
 include/linux/of_pci.h            |  18 ++++
 include/linux/pci.h               |  24 ++++++
 13 files changed, 463 insertions(+), 50 deletions(-)

-- 
2.1.0

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

* [PATCH v11 01/10] Fix ioport_map() for !CONFIG_GENERIC_IOMAP cases.
  2014-09-18  1:30 ` Liviu Dudau
  (?)
@ 2014-09-18  1:30   ` Liviu Dudau
  -1 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij
  Cc: Tanmay Inamdar, Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML

The inline version of ioport_map() that gets used when !CONFIG_GENERIC_IOMAP
is wrong. It returns a mapped (i.e. virtual) address that can start from
zero and completely ignores the PCI_IOBASE and IO_SPACE_LIMIT that most
architectures that use !CONFIG_GENERIC_MAP define.

Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Tested-by: Tanmay Inamdar <tinamdar@apm.com>
---
 include/asm-generic/io.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index 975e1cc..2e2161b 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -331,7 +331,7 @@ static inline void iounmap(void __iomem *addr)
 #ifndef CONFIG_GENERIC_IOMAP
 static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
 {
-	return (void __iomem *) port;
+	return (void __iomem *)(PCI_IOBASE + (port & IO_SPACE_LIMIT));
 }
 
 static inline void ioport_unmap(void __iomem *p)
-- 
2.1.0


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

* [PATCH v11 01/10] Fix ioport_map() for !CONFIG_GENERIC_IOMAP cases.
@ 2014-09-18  1:30   ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij
  Cc: linux-arch, Sinan Kaya, Kukjin Kim, Device Tree ML, Jingoo Han,
	LKML, Grant Likely, Tanmay Inamdar, Suravee Suthikulanit, LAKML

The inline version of ioport_map() that gets used when !CONFIG_GENERIC_IOMAP
is wrong. It returns a mapped (i.e. virtual) address that can start from
zero and completely ignores the PCI_IOBASE and IO_SPACE_LIMIT that most
architectures that use !CONFIG_GENERIC_MAP define.

Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Tested-by: Tanmay Inamdar <tinamdar@apm.com>
---
 include/asm-generic/io.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index 975e1cc..2e2161b 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -331,7 +331,7 @@ static inline void iounmap(void __iomem *addr)
 #ifndef CONFIG_GENERIC_IOMAP
 static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
 {
-	return (void __iomem *) port;
+	return (void __iomem *)(PCI_IOBASE + (port & IO_SPACE_LIMIT));
 }
 
 static inline void ioport_unmap(void __iomem *p)
-- 
2.1.0

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

* [PATCH v11 01/10] Fix ioport_map() for !CONFIG_GENERIC_IOMAP cases.
@ 2014-09-18  1:30   ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: linux-arm-kernel

The inline version of ioport_map() that gets used when !CONFIG_GENERIC_IOMAP
is wrong. It returns a mapped (i.e. virtual) address that can start from
zero and completely ignores the PCI_IOBASE and IO_SPACE_LIMIT that most
architectures that use !CONFIG_GENERIC_MAP define.

Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Tested-by: Tanmay Inamdar <tinamdar@apm.com>
---
 include/asm-generic/io.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index 975e1cc..2e2161b 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -331,7 +331,7 @@ static inline void iounmap(void __iomem *addr)
 #ifndef CONFIG_GENERIC_IOMAP
 static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
 {
-	return (void __iomem *) port;
+	return (void __iomem *)(PCI_IOBASE + (port & IO_SPACE_LIMIT));
 }
 
 static inline void ioport_unmap(void __iomem *p)
-- 
2.1.0

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

* [PATCH v11 02/10] PCI: Introduce helper functions to deal with PCI I/O ranges.
  2014-09-18  1:30 ` Liviu Dudau
@ 2014-09-18  1:30   ` Liviu Dudau
  -1 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij
  Cc: Tanmay Inamdar, Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	Grant Likely

Some architectures do not have a simple view of the PCI I/O space
and instead use a range of CPU addresses that map to bus addresses.
For some architectures these ranges will be expressed by OF bindings
in a device tree file.

This patch introduces a pci_register_io_range() helper function with
a generic implementation that can be used by such architectures to
keep track of the I/O ranges described by the PCI bindings. If the
PCI_IOBASE macro is not defined that signals lack of support for PCI
and we return an error.

In order to retrieve the CPU address associated with an I/O port, a
new helper function pci_pio_to_address() is introduced. This will
search in the list of ranges registered with pci_register_io_range()
and return the CPU address that corresponds to the given port.

Cc: Grant Likely <grant.likely@linaro.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 drivers/of/address.c       | 100 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/of_address.h |   2 +
 2 files changed, 102 insertions(+)

diff --git a/drivers/of/address.c b/drivers/of/address.c
index e371825..2373a92 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -5,6 +5,7 @@
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/pci_regs.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 
 /* Max address size we deal with */
@@ -601,12 +602,111 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
 }
 EXPORT_SYMBOL(of_get_address);
 
+#ifdef PCI_IOBASE
+struct io_range {
+	struct list_head list;
+	phys_addr_t start;
+	resource_size_t size;
+};
+
+static LIST_HEAD(io_range_list);
+static DEFINE_SPINLOCK(io_range_lock);
+#endif
+
+/*
+ * Record the PCI IO range (expressed as CPU physical address + size).
+ * Return a negative value if an error has occured, zero otherwise
+ */
+int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
+{
+#ifdef PCI_IOBASE
+	struct io_range *range;
+	resource_size_t allocated_size = 0;
+
+	/* check if the range hasn't been previously recorded */
+	spin_lock(&io_range_lock);
+	list_for_each_entry(range, &io_range_list, list) {
+		if (addr >= range->start && addr + size <= range->start + size)
+			return 0;
+		allocated_size += range->size;
+	}
+	spin_unlock(&io_range_lock);
+
+	/* range not registed yet, check for available space */
+	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
+		/* if it's too big check if 64K space can be reserved */
+		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT)
+			return -E2BIG;
+
+		size = SZ_64K;
+		pr_warn("Requested IO range too big, new size set to 64K\n");
+	}
+
+	/* add the range to the list */
+	range = kzalloc(sizeof(*range), GFP_KERNEL);
+	if (!range)
+		return -ENOMEM;
+
+	range->start = addr;
+	range->size = size;
+
+	spin_lock(&io_range_lock);
+	list_add_tail(&range->list, &io_range_list);
+	spin_unlock(&io_range_lock);
+#endif
+
+	return 0;
+}
+
+phys_addr_t pci_pio_to_address(unsigned long pio)
+{
+	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
+
+#ifdef PCI_IOBASE
+	struct io_range *range;
+	resource_size_t allocated_size = 0;
+
+	if (pio > IO_SPACE_LIMIT)
+		return address;
+
+	spin_lock(&io_range_lock);
+	list_for_each_entry(range, &io_range_list, list) {
+		if (pio >= allocated_size && pio < allocated_size + range->size) {
+			address = range->start + pio - allocated_size;
+			break;
+		}
+		allocated_size += range->size;
+	}
+	spin_unlock(&io_range_lock);
+#endif
+
+	return address;
+}
+
 unsigned long __weak pci_address_to_pio(phys_addr_t address)
 {
+#ifdef PCI_IOBASE
+	struct io_range *res;
+	resource_size_t offset = 0;
+	unsigned long addr = -1;
+
+	spin_lock(&io_range_lock);
+	list_for_each_entry(res, &io_range_list, list) {
+		if (address >= res->start && address < res->start + res->size) {
+			addr = res->start - address + offset;
+			break;
+		}
+		offset += res->size;
+	}
+	spin_unlock(&io_range_lock);
+
+	return addr;
+#else
 	if (address > IO_SPACE_LIMIT)
 		return (unsigned long)-1;
 
 	return (unsigned long) address;
+#endif
 }
 
 static int __of_address_to_resource(struct device_node *dev,
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index fb7b722..f8cc7da 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -55,7 +55,9 @@ extern void __iomem *of_iomap(struct device_node *device, int index);
 extern const __be32 *of_get_address(struct device_node *dev, int index,
 			   u64 *size, unsigned int *flags);
 
+extern int pci_register_io_range(phys_addr_t addr, resource_size_t size);
 extern unsigned long pci_address_to_pio(phys_addr_t addr);
+extern phys_addr_t pci_pio_to_address(unsigned long pio);
 
 extern int of_pci_range_parser_init(struct of_pci_range_parser *parser,
 			struct device_node *node);
-- 
2.1.0


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

* [PATCH v11 02/10] PCI: Introduce helper functions to deal with PCI I/O ranges.
@ 2014-09-18  1:30   ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: linux-arm-kernel

Some architectures do not have a simple view of the PCI I/O space
and instead use a range of CPU addresses that map to bus addresses.
For some architectures these ranges will be expressed by OF bindings
in a device tree file.

This patch introduces a pci_register_io_range() helper function with
a generic implementation that can be used by such architectures to
keep track of the I/O ranges described by the PCI bindings. If the
PCI_IOBASE macro is not defined that signals lack of support for PCI
and we return an error.

In order to retrieve the CPU address associated with an I/O port, a
new helper function pci_pio_to_address() is introduced. This will
search in the list of ranges registered with pci_register_io_range()
and return the CPU address that corresponds to the given port.

Cc: Grant Likely <grant.likely@linaro.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 drivers/of/address.c       | 100 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/of_address.h |   2 +
 2 files changed, 102 insertions(+)

diff --git a/drivers/of/address.c b/drivers/of/address.c
index e371825..2373a92 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -5,6 +5,7 @@
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/pci_regs.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 
 /* Max address size we deal with */
@@ -601,12 +602,111 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
 }
 EXPORT_SYMBOL(of_get_address);
 
+#ifdef PCI_IOBASE
+struct io_range {
+	struct list_head list;
+	phys_addr_t start;
+	resource_size_t size;
+};
+
+static LIST_HEAD(io_range_list);
+static DEFINE_SPINLOCK(io_range_lock);
+#endif
+
+/*
+ * Record the PCI IO range (expressed as CPU physical address + size).
+ * Return a negative value if an error has occured, zero otherwise
+ */
+int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
+{
+#ifdef PCI_IOBASE
+	struct io_range *range;
+	resource_size_t allocated_size = 0;
+
+	/* check if the range hasn't been previously recorded */
+	spin_lock(&io_range_lock);
+	list_for_each_entry(range, &io_range_list, list) {
+		if (addr >= range->start && addr + size <= range->start + size)
+			return 0;
+		allocated_size += range->size;
+	}
+	spin_unlock(&io_range_lock);
+
+	/* range not registed yet, check for available space */
+	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
+		/* if it's too big check if 64K space can be reserved */
+		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT)
+			return -E2BIG;
+
+		size = SZ_64K;
+		pr_warn("Requested IO range too big, new size set to 64K\n");
+	}
+
+	/* add the range to the list */
+	range = kzalloc(sizeof(*range), GFP_KERNEL);
+	if (!range)
+		return -ENOMEM;
+
+	range->start = addr;
+	range->size = size;
+
+	spin_lock(&io_range_lock);
+	list_add_tail(&range->list, &io_range_list);
+	spin_unlock(&io_range_lock);
+#endif
+
+	return 0;
+}
+
+phys_addr_t pci_pio_to_address(unsigned long pio)
+{
+	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
+
+#ifdef PCI_IOBASE
+	struct io_range *range;
+	resource_size_t allocated_size = 0;
+
+	if (pio > IO_SPACE_LIMIT)
+		return address;
+
+	spin_lock(&io_range_lock);
+	list_for_each_entry(range, &io_range_list, list) {
+		if (pio >= allocated_size && pio < allocated_size + range->size) {
+			address = range->start + pio - allocated_size;
+			break;
+		}
+		allocated_size += range->size;
+	}
+	spin_unlock(&io_range_lock);
+#endif
+
+	return address;
+}
+
 unsigned long __weak pci_address_to_pio(phys_addr_t address)
 {
+#ifdef PCI_IOBASE
+	struct io_range *res;
+	resource_size_t offset = 0;
+	unsigned long addr = -1;
+
+	spin_lock(&io_range_lock);
+	list_for_each_entry(res, &io_range_list, list) {
+		if (address >= res->start && address < res->start + res->size) {
+			addr = res->start - address + offset;
+			break;
+		}
+		offset += res->size;
+	}
+	spin_unlock(&io_range_lock);
+
+	return addr;
+#else
 	if (address > IO_SPACE_LIMIT)
 		return (unsigned long)-1;
 
 	return (unsigned long) address;
+#endif
 }
 
 static int __of_address_to_resource(struct device_node *dev,
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index fb7b722..f8cc7da 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -55,7 +55,9 @@ extern void __iomem *of_iomap(struct device_node *device, int index);
 extern const __be32 *of_get_address(struct device_node *dev, int index,
 			   u64 *size, unsigned int *flags);
 
+extern int pci_register_io_range(phys_addr_t addr, resource_size_t size);
 extern unsigned long pci_address_to_pio(phys_addr_t addr);
+extern phys_addr_t pci_pio_to_address(unsigned long pio);
 
 extern int of_pci_range_parser_init(struct of_pci_range_parser *parser,
 			struct device_node *node);
-- 
2.1.0

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

* [PATCH v11 03/10] ARM: Define PCI_IOBASE as the base of virtual PCI IO space.
  2014-09-18  1:30 ` Liviu Dudau
@ 2014-09-18  1:30   ` Liviu Dudau
  -1 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij
  Cc: Tanmay Inamdar, Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML

This is needed for calls into OF code that parses PCI ranges.
It signals support for memory mapped PCI I/O accesses that
are described be device trees.

Cc: Russell King <linux@arm.linux.org.uk>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Rob Herring <robh+dt@kernel.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 arch/arm/include/asm/io.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 3d23418..22b7529 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -178,6 +178,7 @@ static inline void __iomem *__typesafe_io(unsigned long addr)
 
 /* PCI fixed i/o mapping */
 #define PCI_IO_VIRT_BASE	0xfee00000
+#define PCI_IOBASE		PCI_IO_VIRT_BASE
 
 #if defined(CONFIG_PCI)
 void pci_ioremap_set_mem_type(int mem_type);
-- 
2.1.0


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

* [PATCH v11 03/10] ARM: Define PCI_IOBASE as the base of virtual PCI IO space.
@ 2014-09-18  1:30   ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: linux-arm-kernel

This is needed for calls into OF code that parses PCI ranges.
It signals support for memory mapped PCI I/O accesses that
are described be device trees.

Cc: Russell King <linux@arm.linux.org.uk>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Rob Herring <robh+dt@kernel.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 arch/arm/include/asm/io.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 3d23418..22b7529 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -178,6 +178,7 @@ static inline void __iomem *__typesafe_io(unsigned long addr)
 
 /* PCI fixed i/o mapping */
 #define PCI_IO_VIRT_BASE	0xfee00000
+#define PCI_IOBASE		PCI_IO_VIRT_BASE
 
 #if defined(CONFIG_PCI)
 void pci_ioremap_set_mem_type(int mem_type);
-- 
2.1.0

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

* [PATCH v11 04/10] PCI: OF: Fix the conversion of IO ranges into IO resources.
  2014-09-18  1:30 ` Liviu Dudau
@ 2014-09-18  1:30   ` Liviu Dudau
  -1 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij
  Cc: Tanmay Inamdar, Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	Grant Likely, Thierry Reding, Simon Horman

The ranges property for a host bridge controller in DT describes
the mapping between the PCI bus address and the CPU physical address.
The resources framework however expects that the IO resources start
at a pseudo "port" address 0 (zero) and have a maximum size of IO_SPACE_LIMIT.
The conversion from pci ranges to resources failed to take that into account.

In the process move the function into drivers/of/address.c as it now
depends on pci_address_to_pio() code and make it return an error code.
Also fix all the drivers that depend on the old behaviour by fetching
the CPU physical address based on the port number.

Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: Simon Horman <horms@verge.net.au>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 arch/arm/mach-integrator/pci_v3.c | 23 ++++++++++----------
 drivers/of/address.c              | 46 +++++++++++++++++++++++++++++++++++++++
 drivers/pci/host/pci-tegra.c      | 10 ++++++---
 drivers/pci/host/pcie-rcar.c      | 21 +++++++++++++-----
 include/linux/of_address.h        | 13 ++---------
 5 files changed, 82 insertions(+), 31 deletions(-)

diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index 05e1f73..3321e1b 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -660,6 +660,7 @@ static void __init pci_v3_preinit(void)
 {
 	unsigned long flags;
 	unsigned int temp;
+	phys_addr_t io_address = pci_pio_to_address(io_mem.start);
 
 	pcibios_min_mem = 0x00100000;
 
@@ -701,7 +702,7 @@ static void __init pci_v3_preinit(void)
 	/*
 	 * Setup window 2 - PCI IO
 	 */
-	v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_mem.start) |
+	v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_address) |
 			V3_LB_BASE_ENABLE);
 	v3_writew(V3_LB_MAP2, v3_addr_to_lb_map2(0));
 
@@ -742,6 +743,7 @@ static void __init pci_v3_preinit(void)
 static void __init pci_v3_postinit(void)
 {
 	unsigned int pci_cmd;
+	phys_addr_t io_address = pci_pio_to_address(io_mem.start);
 
 	pci_cmd = PCI_COMMAND_MEMORY |
 		  PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
@@ -758,7 +760,7 @@ static void __init pci_v3_postinit(void)
 		       "interrupt: %d\n", ret);
 #endif
 
-	register_isa_ports(non_mem.start, io_mem.start, 0);
+	register_isa_ports(non_mem.start, io_address, 0);
 }
 
 /*
@@ -867,33 +869,32 @@ static int __init pci_v3_probe(struct platform_device *pdev)
 
 	for_each_of_pci_range(&parser, &range) {
 		if (!range.flags) {
-			of_pci_range_to_resource(&range, np, &conf_mem);
+			ret = of_pci_range_to_resource(&range, np, &conf_mem);
 			conf_mem.name = "PCIv3 config";
 		}
 		if (range.flags & IORESOURCE_IO) {
-			of_pci_range_to_resource(&range, np, &io_mem);
+			ret = of_pci_range_to_resource(&range, np, &io_mem);
 			io_mem.name = "PCIv3 I/O";
 		}
 		if ((range.flags & IORESOURCE_MEM) &&
 			!(range.flags & IORESOURCE_PREFETCH)) {
 			non_mem_pci = range.pci_addr;
 			non_mem_pci_sz = range.size;
-			of_pci_range_to_resource(&range, np, &non_mem);
+			ret = of_pci_range_to_resource(&range, np, &non_mem);
 			non_mem.name = "PCIv3 non-prefetched mem";
 		}
 		if ((range.flags & IORESOURCE_MEM) &&
 			(range.flags & IORESOURCE_PREFETCH)) {
 			pre_mem_pci = range.pci_addr;
 			pre_mem_pci_sz = range.size;
-			of_pci_range_to_resource(&range, np, &pre_mem);
+			ret = of_pci_range_to_resource(&range, np, &pre_mem);
 			pre_mem.name = "PCIv3 prefetched mem";
 		}
-	}
 
-	if (!conf_mem.start || !io_mem.start ||
-	    !non_mem.start || !pre_mem.start) {
-		dev_err(&pdev->dev, "missing ranges in device node\n");
-		return -EINVAL;
+		if (ret < 0) {
+			dev_err(&pdev->dev, "missing ranges in device node\n");
+			return -EINVAL;
+		}
 	}
 
 	pci_v3.map_irq = of_irq_parse_and_map_pci;
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 2373a92..ff10b64 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -947,3 +947,49 @@ bool of_dma_is_coherent(struct device_node *np)
 	return false;
 }
 EXPORT_SYMBOL_GPL(of_dma_is_coherent);
+
+/*
+ * of_pci_range_to_resource - Create a resource from an of_pci_range
+ * @range:	the PCI range that describes the resource
+ * @np:		device node where the range belongs to
+ * @res:	pointer to a valid resource that will be updated to
+ *              reflect the values contained in the range.
+ *
+ * Returns EINVAL if the range cannot be converted to resource.
+ *
+ * Note that if the range is an IO range, the resource will be converted
+ * using pci_address_to_pio() which can fail if it is called too early or
+ * if the range cannot be matched to any host bridge IO space (our case here).
+ * To guard against that we try to register the IO range first.
+ * If that fails we know that pci_address_to_pio() will do too.
+ */
+int of_pci_range_to_resource(struct of_pci_range *range,
+	struct device_node *np, struct resource *res)
+{
+	int err;
+	res->flags = range->flags;
+	res->parent = res->child = res->sibling = NULL;
+	res->name = np->full_name;
+
+	if (res->flags & IORESOURCE_IO) {
+		unsigned long port = -1;
+		err = pci_register_io_range(range->cpu_addr, range->size);
+		if (err)
+			goto invalid_range;
+		port = pci_address_to_pio(range->cpu_addr);
+		if (port == (unsigned long)-1) {
+			err = -EINVAL;
+			goto invalid_range;
+		}
+		res->start = port;
+	} else {
+		res->start = range->cpu_addr;
+	}
+	res->end = res->start + range->size - 1;
+	return 0;
+
+invalid_range:
+	res->start = (resource_size_t)OF_BAD_ADDR;
+	res->end = (resource_size_t)OF_BAD_ADDR;
+	return err;
+}
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 0fb0fdb..946935d 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -626,13 +626,14 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable);
 static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
 {
 	struct tegra_pcie *pcie = sys_to_pcie(sys);
+	phys_addr_t io_start = pci_pio_to_address(pcie->io.start);
 
 	pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
 	pci_add_resource_offset(&sys->resources, &pcie->prefetch,
 				sys->mem_offset);
 	pci_add_resource(&sys->resources, &pcie->busn);
 
-	pci_ioremap_io(nr * SZ_64K, pcie->io.start);
+	pci_ioremap_io(nr * SZ_64K, io_start);
 
 	return 1;
 }
@@ -737,6 +738,7 @@ static irqreturn_t tegra_pcie_isr(int irq, void *arg)
 static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
 {
 	u32 fpci_bar, size, axi_address;
+	phys_addr_t io_start = pci_pio_to_address(pcie->io.start);
 
 	/* Bar 0: type 1 extended configuration space */
 	fpci_bar = 0xfe100000;
@@ -749,7 +751,7 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
 	/* Bar 1: downstream IO bar */
 	fpci_bar = 0xfdfc0000;
 	size = resource_size(&pcie->io);
-	axi_address = pcie->io.start;
+	axi_address = io_start;
 	afi_writel(pcie, axi_address, AFI_AXI_BAR1_START);
 	afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ);
 	afi_writel(pcie, fpci_bar, AFI_FPCI_BAR1);
@@ -1520,7 +1522,9 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
 	}
 
 	for_each_of_pci_range(&parser, &range) {
-		of_pci_range_to_resource(&range, np, &res);
+		err = of_pci_range_to_resource(&range, np, &res);
+		if (err < 0)
+			return err;
 
 		switch (res.flags & IORESOURCE_TYPE_BITS) {
 		case IORESOURCE_IO:
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index 4884ee5..61158e0 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -323,6 +323,7 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
 
 	/* Setup PCIe address space mappings for each resource */
 	resource_size_t size;
+	resource_size_t res_start;
 	u32 mask;
 
 	rcar_pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
@@ -335,8 +336,13 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
 	mask = (roundup_pow_of_two(size) / SZ_128) - 1;
 	rcar_pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
 
-	rcar_pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win));
-	rcar_pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win));
+	if (res->flags & IORESOURCE_IO)
+		res_start = pci_pio_to_address(res->start);
+	else
+		res_start = res->start;
+
+	rcar_pci_write_reg(pcie, upper_32_bits(res_start), PCIEPARH(win));
+	rcar_pci_write_reg(pcie, lower_32_bits(res_start), PCIEPARL(win));
 
 	/* First resource is for IO */
 	mask = PAR_ENABLE;
@@ -363,9 +369,10 @@ static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
 
 		rcar_pcie_setup_window(i, pcie);
 
-		if (res->flags & IORESOURCE_IO)
-			pci_ioremap_io(nr * SZ_64K, res->start);
-		else
+		if (res->flags & IORESOURCE_IO) {
+			phys_addr_t io_start = pci_pio_to_address(res->start);
+			pci_ioremap_io(nr * SZ_64K, io_start);
+		} else
 			pci_add_resource(&sys->resources, res);
 	}
 	pci_add_resource(&sys->resources, &pcie->busn);
@@ -935,8 +942,10 @@ static int rcar_pcie_probe(struct platform_device *pdev)
 	}
 
 	for_each_of_pci_range(&parser, &range) {
-		of_pci_range_to_resource(&range, pdev->dev.of_node,
+		err = of_pci_range_to_resource(&range, pdev->dev.of_node,
 						&pcie->res[win++]);
+		if (err < 0)
+			return err;
 
 		if (win > RCAR_PCI_MAX_RESOURCES)
 			break;
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index f8cc7da..c9d70deb 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -23,17 +23,8 @@ struct of_pci_range {
 #define for_each_of_pci_range(parser, range) \
 	for (; of_pci_range_parser_one(parser, range);)
 
-static inline void of_pci_range_to_resource(struct of_pci_range *range,
-					    struct device_node *np,
-					    struct resource *res)
-{
-	res->flags = range->flags;
-	res->start = range->cpu_addr;
-	res->end = range->cpu_addr + range->size - 1;
-	res->parent = res->child = res->sibling = NULL;
-	res->name = np->full_name;
-}
-
+extern int of_pci_range_to_resource(struct of_pci_range *range,
+		struct device_node *np, struct resource *res);
 /* Translate a DMA address from device space to CPU space */
 extern u64 of_translate_dma_address(struct device_node *dev,
 				    const __be32 *in_addr);
-- 
2.1.0


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

* [PATCH v11 04/10] PCI: OF: Fix the conversion of IO ranges into IO resources.
@ 2014-09-18  1:30   ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: linux-arm-kernel

The ranges property for a host bridge controller in DT describes
the mapping between the PCI bus address and the CPU physical address.
The resources framework however expects that the IO resources start
at a pseudo "port" address 0 (zero) and have a maximum size of IO_SPACE_LIMIT.
The conversion from pci ranges to resources failed to take that into account.

In the process move the function into drivers/of/address.c as it now
depends on pci_address_to_pio() code and make it return an error code.
Also fix all the drivers that depend on the old behaviour by fetching
the CPU physical address based on the port number.

Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: Simon Horman <horms@verge.net.au>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 arch/arm/mach-integrator/pci_v3.c | 23 ++++++++++----------
 drivers/of/address.c              | 46 +++++++++++++++++++++++++++++++++++++++
 drivers/pci/host/pci-tegra.c      | 10 ++++++---
 drivers/pci/host/pcie-rcar.c      | 21 +++++++++++++-----
 include/linux/of_address.h        | 13 ++---------
 5 files changed, 82 insertions(+), 31 deletions(-)

diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index 05e1f73..3321e1b 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -660,6 +660,7 @@ static void __init pci_v3_preinit(void)
 {
 	unsigned long flags;
 	unsigned int temp;
+	phys_addr_t io_address = pci_pio_to_address(io_mem.start);
 
 	pcibios_min_mem = 0x00100000;
 
@@ -701,7 +702,7 @@ static void __init pci_v3_preinit(void)
 	/*
 	 * Setup window 2 - PCI IO
 	 */
-	v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_mem.start) |
+	v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_address) |
 			V3_LB_BASE_ENABLE);
 	v3_writew(V3_LB_MAP2, v3_addr_to_lb_map2(0));
 
@@ -742,6 +743,7 @@ static void __init pci_v3_preinit(void)
 static void __init pci_v3_postinit(void)
 {
 	unsigned int pci_cmd;
+	phys_addr_t io_address = pci_pio_to_address(io_mem.start);
 
 	pci_cmd = PCI_COMMAND_MEMORY |
 		  PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
@@ -758,7 +760,7 @@ static void __init pci_v3_postinit(void)
 		       "interrupt: %d\n", ret);
 #endif
 
-	register_isa_ports(non_mem.start, io_mem.start, 0);
+	register_isa_ports(non_mem.start, io_address, 0);
 }
 
 /*
@@ -867,33 +869,32 @@ static int __init pci_v3_probe(struct platform_device *pdev)
 
 	for_each_of_pci_range(&parser, &range) {
 		if (!range.flags) {
-			of_pci_range_to_resource(&range, np, &conf_mem);
+			ret = of_pci_range_to_resource(&range, np, &conf_mem);
 			conf_mem.name = "PCIv3 config";
 		}
 		if (range.flags & IORESOURCE_IO) {
-			of_pci_range_to_resource(&range, np, &io_mem);
+			ret = of_pci_range_to_resource(&range, np, &io_mem);
 			io_mem.name = "PCIv3 I/O";
 		}
 		if ((range.flags & IORESOURCE_MEM) &&
 			!(range.flags & IORESOURCE_PREFETCH)) {
 			non_mem_pci = range.pci_addr;
 			non_mem_pci_sz = range.size;
-			of_pci_range_to_resource(&range, np, &non_mem);
+			ret = of_pci_range_to_resource(&range, np, &non_mem);
 			non_mem.name = "PCIv3 non-prefetched mem";
 		}
 		if ((range.flags & IORESOURCE_MEM) &&
 			(range.flags & IORESOURCE_PREFETCH)) {
 			pre_mem_pci = range.pci_addr;
 			pre_mem_pci_sz = range.size;
-			of_pci_range_to_resource(&range, np, &pre_mem);
+			ret = of_pci_range_to_resource(&range, np, &pre_mem);
 			pre_mem.name = "PCIv3 prefetched mem";
 		}
-	}
 
-	if (!conf_mem.start || !io_mem.start ||
-	    !non_mem.start || !pre_mem.start) {
-		dev_err(&pdev->dev, "missing ranges in device node\n");
-		return -EINVAL;
+		if (ret < 0) {
+			dev_err(&pdev->dev, "missing ranges in device node\n");
+			return -EINVAL;
+		}
 	}
 
 	pci_v3.map_irq = of_irq_parse_and_map_pci;
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 2373a92..ff10b64 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -947,3 +947,49 @@ bool of_dma_is_coherent(struct device_node *np)
 	return false;
 }
 EXPORT_SYMBOL_GPL(of_dma_is_coherent);
+
+/*
+ * of_pci_range_to_resource - Create a resource from an of_pci_range
+ * @range:	the PCI range that describes the resource
+ * @np:		device node where the range belongs to
+ * @res:	pointer to a valid resource that will be updated to
+ *              reflect the values contained in the range.
+ *
+ * Returns EINVAL if the range cannot be converted to resource.
+ *
+ * Note that if the range is an IO range, the resource will be converted
+ * using pci_address_to_pio() which can fail if it is called too early or
+ * if the range cannot be matched to any host bridge IO space (our case here).
+ * To guard against that we try to register the IO range first.
+ * If that fails we know that pci_address_to_pio() will do too.
+ */
+int of_pci_range_to_resource(struct of_pci_range *range,
+	struct device_node *np, struct resource *res)
+{
+	int err;
+	res->flags = range->flags;
+	res->parent = res->child = res->sibling = NULL;
+	res->name = np->full_name;
+
+	if (res->flags & IORESOURCE_IO) {
+		unsigned long port = -1;
+		err = pci_register_io_range(range->cpu_addr, range->size);
+		if (err)
+			goto invalid_range;
+		port = pci_address_to_pio(range->cpu_addr);
+		if (port == (unsigned long)-1) {
+			err = -EINVAL;
+			goto invalid_range;
+		}
+		res->start = port;
+	} else {
+		res->start = range->cpu_addr;
+	}
+	res->end = res->start + range->size - 1;
+	return 0;
+
+invalid_range:
+	res->start = (resource_size_t)OF_BAD_ADDR;
+	res->end = (resource_size_t)OF_BAD_ADDR;
+	return err;
+}
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 0fb0fdb..946935d 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -626,13 +626,14 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable);
 static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
 {
 	struct tegra_pcie *pcie = sys_to_pcie(sys);
+	phys_addr_t io_start = pci_pio_to_address(pcie->io.start);
 
 	pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
 	pci_add_resource_offset(&sys->resources, &pcie->prefetch,
 				sys->mem_offset);
 	pci_add_resource(&sys->resources, &pcie->busn);
 
-	pci_ioremap_io(nr * SZ_64K, pcie->io.start);
+	pci_ioremap_io(nr * SZ_64K, io_start);
 
 	return 1;
 }
@@ -737,6 +738,7 @@ static irqreturn_t tegra_pcie_isr(int irq, void *arg)
 static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
 {
 	u32 fpci_bar, size, axi_address;
+	phys_addr_t io_start = pci_pio_to_address(pcie->io.start);
 
 	/* Bar 0: type 1 extended configuration space */
 	fpci_bar = 0xfe100000;
@@ -749,7 +751,7 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
 	/* Bar 1: downstream IO bar */
 	fpci_bar = 0xfdfc0000;
 	size = resource_size(&pcie->io);
-	axi_address = pcie->io.start;
+	axi_address = io_start;
 	afi_writel(pcie, axi_address, AFI_AXI_BAR1_START);
 	afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ);
 	afi_writel(pcie, fpci_bar, AFI_FPCI_BAR1);
@@ -1520,7 +1522,9 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
 	}
 
 	for_each_of_pci_range(&parser, &range) {
-		of_pci_range_to_resource(&range, np, &res);
+		err = of_pci_range_to_resource(&range, np, &res);
+		if (err < 0)
+			return err;
 
 		switch (res.flags & IORESOURCE_TYPE_BITS) {
 		case IORESOURCE_IO:
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index 4884ee5..61158e0 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -323,6 +323,7 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
 
 	/* Setup PCIe address space mappings for each resource */
 	resource_size_t size;
+	resource_size_t res_start;
 	u32 mask;
 
 	rcar_pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
@@ -335,8 +336,13 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
 	mask = (roundup_pow_of_two(size) / SZ_128) - 1;
 	rcar_pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
 
-	rcar_pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win));
-	rcar_pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win));
+	if (res->flags & IORESOURCE_IO)
+		res_start = pci_pio_to_address(res->start);
+	else
+		res_start = res->start;
+
+	rcar_pci_write_reg(pcie, upper_32_bits(res_start), PCIEPARH(win));
+	rcar_pci_write_reg(pcie, lower_32_bits(res_start), PCIEPARL(win));
 
 	/* First resource is for IO */
 	mask = PAR_ENABLE;
@@ -363,9 +369,10 @@ static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
 
 		rcar_pcie_setup_window(i, pcie);
 
-		if (res->flags & IORESOURCE_IO)
-			pci_ioremap_io(nr * SZ_64K, res->start);
-		else
+		if (res->flags & IORESOURCE_IO) {
+			phys_addr_t io_start = pci_pio_to_address(res->start);
+			pci_ioremap_io(nr * SZ_64K, io_start);
+		} else
 			pci_add_resource(&sys->resources, res);
 	}
 	pci_add_resource(&sys->resources, &pcie->busn);
@@ -935,8 +942,10 @@ static int rcar_pcie_probe(struct platform_device *pdev)
 	}
 
 	for_each_of_pci_range(&parser, &range) {
-		of_pci_range_to_resource(&range, pdev->dev.of_node,
+		err = of_pci_range_to_resource(&range, pdev->dev.of_node,
 						&pcie->res[win++]);
+		if (err < 0)
+			return err;
 
 		if (win > RCAR_PCI_MAX_RESOURCES)
 			break;
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index f8cc7da..c9d70deb 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -23,17 +23,8 @@ struct of_pci_range {
 #define for_each_of_pci_range(parser, range) \
 	for (; of_pci_range_parser_one(parser, range);)
 
-static inline void of_pci_range_to_resource(struct of_pci_range *range,
-					    struct device_node *np,
-					    struct resource *res)
-{
-	res->flags = range->flags;
-	res->start = range->cpu_addr;
-	res->end = range->cpu_addr + range->size - 1;
-	res->parent = res->child = res->sibling = NULL;
-	res->name = np->full_name;
-}
-
+extern int of_pci_range_to_resource(struct of_pci_range *range,
+		struct device_node *np, struct resource *res);
 /* Translate a DMA address from device space to CPU space */
 extern u64 of_translate_dma_address(struct device_node *dev,
 				    const __be32 *in_addr);
-- 
2.1.0

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

* [PATCH v11 05/10] PCI: Create pci_host_bridge before its associated bus in pci_create_root_bus.
  2014-09-18  1:30 ` Liviu Dudau
  (?)
@ 2014-09-18  1:30   ` Liviu Dudau
  -1 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij
  Cc: Tanmay Inamdar, Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML

Before commit 7b5436635800 the pci_host_bridge was created before the root bus.
As that commit has added a needless dependency on the bus for pci_alloc_host_bridge()
the creation order has been changed for no good reason. Revert the order of
creation as we are going to depend on the pci_host_bridge structure to retrieve the
domain number of the root bus.

Cc: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
Acked-by: Grant Likely <grant.likely@linaro.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Tanmay Inamdar <tinamdar@apm.com>
---
 drivers/pci/probe.c | 32 +++++++++++++++++---------------
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index e3cf8a2..5ff72ec 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -515,7 +515,7 @@ static void pci_release_host_bridge_dev(struct device *dev)
 	kfree(bridge);
 }
 
-static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
+static struct pci_host_bridge *pci_alloc_host_bridge(void)
 {
 	struct pci_host_bridge *bridge;
 
@@ -524,7 +524,8 @@ static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
 		return NULL;
 
 	INIT_LIST_HEAD(&bridge->windows);
-	bridge->bus = b;
+	bridge->dev.release = pci_release_host_bridge_dev;
+
 	return bridge;
 }
 
@@ -1761,9 +1762,15 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 	char bus_addr[64];
 	char *fmt;
 
+	bridge = pci_alloc_host_bridge();
+	if (!bridge)
+		return NULL;
+
+	bridge->dev.parent = parent;
+
 	b = pci_alloc_bus();
 	if (!b)
-		return NULL;
+		goto err_out;
 
 	b->sysdata = sysdata;
 	b->ops = ops;
@@ -1772,26 +1779,19 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 	if (b2) {
 		/* If we already got to this bus through a different bridge, ignore it */
 		dev_dbg(&b2->dev, "bus already known\n");
-		goto err_out;
+		goto err_bus_out;
 	}
 
-	bridge = pci_alloc_host_bridge(b);
-	if (!bridge)
-		goto err_out;
-
-	bridge->dev.parent = parent;
-	bridge->dev.release = pci_release_host_bridge_dev;
+	bridge->bus = b;
 	dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
 	error = pcibios_root_bridge_prepare(bridge);
-	if (error) {
-		kfree(bridge);
+	if (error)
 		goto err_out;
-	}
 
 	error = device_register(&bridge->dev);
 	if (error) {
 		put_device(&bridge->dev);
-		goto err_out;
+		goto err_bus_out;
 	}
 	b->bridge = get_device(&bridge->dev);
 	device_enable_async_suspend(b->bridge);
@@ -1848,8 +1848,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 class_dev_reg_err:
 	put_device(&bridge->dev);
 	device_unregister(&bridge->dev);
-err_out:
+err_bus_out:
 	kfree(b);
+err_out:
+	kfree(bridge);
 	return NULL;
 }
 
-- 
2.1.0


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

* [PATCH v11 05/10] PCI: Create pci_host_bridge before its associated bus in pci_create_root_bus.
@ 2014-09-18  1:30   ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij
  Cc: linux-arch, Sinan Kaya, Kukjin Kim, Device Tree ML, Jingoo Han,
	LKML, Grant Likely, Tanmay Inamdar, Suravee Suthikulanit, LAKML

Before commit 7b5436635800 the pci_host_bridge was created before the root bus.
As that commit has added a needless dependency on the bus for pci_alloc_host_bridge()
the creation order has been changed for no good reason. Revert the order of
creation as we are going to depend on the pci_host_bridge structure to retrieve the
domain number of the root bus.

Cc: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
Acked-by: Grant Likely <grant.likely@linaro.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Tanmay Inamdar <tinamdar@apm.com>
---
 drivers/pci/probe.c | 32 +++++++++++++++++---------------
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index e3cf8a2..5ff72ec 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -515,7 +515,7 @@ static void pci_release_host_bridge_dev(struct device *dev)
 	kfree(bridge);
 }
 
-static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
+static struct pci_host_bridge *pci_alloc_host_bridge(void)
 {
 	struct pci_host_bridge *bridge;
 
@@ -524,7 +524,8 @@ static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
 		return NULL;
 
 	INIT_LIST_HEAD(&bridge->windows);
-	bridge->bus = b;
+	bridge->dev.release = pci_release_host_bridge_dev;
+
 	return bridge;
 }
 
@@ -1761,9 +1762,15 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 	char bus_addr[64];
 	char *fmt;
 
+	bridge = pci_alloc_host_bridge();
+	if (!bridge)
+		return NULL;
+
+	bridge->dev.parent = parent;
+
 	b = pci_alloc_bus();
 	if (!b)
-		return NULL;
+		goto err_out;
 
 	b->sysdata = sysdata;
 	b->ops = ops;
@@ -1772,26 +1779,19 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 	if (b2) {
 		/* If we already got to this bus through a different bridge, ignore it */
 		dev_dbg(&b2->dev, "bus already known\n");
-		goto err_out;
+		goto err_bus_out;
 	}
 
-	bridge = pci_alloc_host_bridge(b);
-	if (!bridge)
-		goto err_out;
-
-	bridge->dev.parent = parent;
-	bridge->dev.release = pci_release_host_bridge_dev;
+	bridge->bus = b;
 	dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
 	error = pcibios_root_bridge_prepare(bridge);
-	if (error) {
-		kfree(bridge);
+	if (error)
 		goto err_out;
-	}
 
 	error = device_register(&bridge->dev);
 	if (error) {
 		put_device(&bridge->dev);
-		goto err_out;
+		goto err_bus_out;
 	}
 	b->bridge = get_device(&bridge->dev);
 	device_enable_async_suspend(b->bridge);
@@ -1848,8 +1848,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 class_dev_reg_err:
 	put_device(&bridge->dev);
 	device_unregister(&bridge->dev);
-err_out:
+err_bus_out:
 	kfree(b);
+err_out:
+	kfree(bridge);
 	return NULL;
 }
 
-- 
2.1.0

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

* [PATCH v11 05/10] PCI: Create pci_host_bridge before its associated bus in pci_create_root_bus.
@ 2014-09-18  1:30   ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: linux-arm-kernel

Before commit 7b5436635800 the pci_host_bridge was created before the root bus.
As that commit has added a needless dependency on the bus for pci_alloc_host_bridge()
the creation order has been changed for no good reason. Revert the order of
creation as we are going to depend on the pci_host_bridge structure to retrieve the
domain number of the root bus.

Cc: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
Acked-by: Grant Likely <grant.likely@linaro.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Tanmay Inamdar <tinamdar@apm.com>
---
 drivers/pci/probe.c | 32 +++++++++++++++++---------------
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index e3cf8a2..5ff72ec 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -515,7 +515,7 @@ static void pci_release_host_bridge_dev(struct device *dev)
 	kfree(bridge);
 }
 
-static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
+static struct pci_host_bridge *pci_alloc_host_bridge(void)
 {
 	struct pci_host_bridge *bridge;
 
@@ -524,7 +524,8 @@ static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)
 		return NULL;
 
 	INIT_LIST_HEAD(&bridge->windows);
-	bridge->bus = b;
+	bridge->dev.release = pci_release_host_bridge_dev;
+
 	return bridge;
 }
 
@@ -1761,9 +1762,15 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 	char bus_addr[64];
 	char *fmt;
 
+	bridge = pci_alloc_host_bridge();
+	if (!bridge)
+		return NULL;
+
+	bridge->dev.parent = parent;
+
 	b = pci_alloc_bus();
 	if (!b)
-		return NULL;
+		goto err_out;
 
 	b->sysdata = sysdata;
 	b->ops = ops;
@@ -1772,26 +1779,19 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 	if (b2) {
 		/* If we already got to this bus through a different bridge, ignore it */
 		dev_dbg(&b2->dev, "bus already known\n");
-		goto err_out;
+		goto err_bus_out;
 	}
 
-	bridge = pci_alloc_host_bridge(b);
-	if (!bridge)
-		goto err_out;
-
-	bridge->dev.parent = parent;
-	bridge->dev.release = pci_release_host_bridge_dev;
+	bridge->bus = b;
 	dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
 	error = pcibios_root_bridge_prepare(bridge);
-	if (error) {
-		kfree(bridge);
+	if (error)
 		goto err_out;
-	}
 
 	error = device_register(&bridge->dev);
 	if (error) {
 		put_device(&bridge->dev);
-		goto err_out;
+		goto err_bus_out;
 	}
 	b->bridge = get_device(&bridge->dev);
 	device_enable_async_suspend(b->bridge);
@@ -1848,8 +1848,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 class_dev_reg_err:
 	put_device(&bridge->dev);
 	device_unregister(&bridge->dev);
-err_out:
+err_bus_out:
 	kfree(b);
+err_out:
+	kfree(bridge);
 	return NULL;
 }
 
-- 
2.1.0

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

* [PATCH v11 06/10] PCI: Introduce generic domain handling for PCI busses.
  2014-09-18  1:30 ` Liviu Dudau
  (?)
@ 2014-09-18  1:30   ` Liviu Dudau
  -1 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij
  Cc: Tanmay Inamdar, Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	Catalin Marinas

From: Catalin Marinas <catalin.marinas@arm.com>

The handling of PCI domains (or PCI segments in ACPI speak) is
usually a straightforward affair but its implementation is
currently left to the architectural code, with pci_domain_nr(b)
querying the value of the domain associated with bus b.

This patch introduces CONFIG_PCI_DOMAINS_GENERIC as an
option that can be selected if an architecture want a
simple implementation where the value of the domain
associated with a bus is stored in struct pci_bus.

The architectures that select CONFIG_PCI_DOMAINS_GENERIC will
then have to implement pci_bus_assign_domain_nr() as a way
of setting the domain number associated with a root bus.
All child busses except the root bus will inherit the domain_nr
value from their parent.

Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Catalin Marinas <Catalin.Marinas@arm.com>
[Renamed pci_set_domain_nr() to pci_bus_assign_domain_nr()]
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 drivers/pci/probe.c | 11 ++++++++---
 include/linux/pci.h | 21 +++++++++++++++++++++
 2 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 5ff72ec..ef891d2 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -485,7 +485,7 @@ void pci_read_bridge_bases(struct pci_bus *child)
 	}
 }
 
-static struct pci_bus *pci_alloc_bus(void)
+static struct pci_bus *pci_alloc_bus(struct pci_bus *parent)
 {
 	struct pci_bus *b;
 
@@ -500,6 +500,10 @@ static struct pci_bus *pci_alloc_bus(void)
 	INIT_LIST_HEAD(&b->resources);
 	b->max_bus_speed = PCI_SPEED_UNKNOWN;
 	b->cur_bus_speed = PCI_SPEED_UNKNOWN;
+#ifdef CONFIG_PCI_DOMAINS_GENERIC
+	if (parent)
+		b->domain_nr = parent->domain_nr;
+#endif
 	return b;
 }
 
@@ -672,7 +676,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
 	/*
 	 * Allocate a new bus, and inherit stuff from the parent..
 	 */
-	child = pci_alloc_bus();
+	child = pci_alloc_bus(parent);
 	if (!child)
 		return NULL;
 
@@ -1768,13 +1772,14 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 
 	bridge->dev.parent = parent;
 
-	b = pci_alloc_bus();
+	b = pci_alloc_bus(NULL);
 	if (!b)
 		goto err_out;
 
 	b->sysdata = sysdata;
 	b->ops = ops;
 	b->number = b->busn_res.start = bus;
+	pci_bus_assign_domain_nr(b, parent);
 	b2 = pci_find_bus(pci_domain_nr(b), bus);
 	if (b2) {
 		/* If we already got to this bus through a different bridge, ignore it */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 61978a4..a494e5d 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -456,6 +456,9 @@ struct pci_bus {
 	unsigned char	primary;	/* number of primary bridge */
 	unsigned char	max_bus_speed;	/* enum pci_bus_speed */
 	unsigned char	cur_bus_speed;	/* enum pci_bus_speed */
+#ifdef CONFIG_PCI_DOMAINS_GENERIC
+	int		domain_nr;
+#endif
 
 	char		name[48];
 
@@ -1288,6 +1291,24 @@ static inline int pci_domain_nr(struct pci_bus *bus) { return 0; }
 static inline int pci_proc_domain(struct pci_bus *bus) { return 0; }
 #endif /* CONFIG_PCI_DOMAINS */
 
+/*
+ * Generic implementation for PCI domain support. If your
+ * architecture does not need custom management of PCI
+ * domains then this implementation will be used
+ */
+#ifdef CONFIG_PCI_DOMAINS_GENERIC
+static inline int pci_domain_nr(struct pci_bus *bus)
+{
+	return bus->domain_nr;
+}
+void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent);
+#else
+static inline void pci_bus_assign_domain_nr(struct pci_bus *bus,
+					struct device *parent)
+{
+}
+#endif
+
 /* some architectures require additional setup to direct VGA traffic */
 typedef int (*arch_set_vga_state_t)(struct pci_dev *pdev, bool decode,
 		      unsigned int command_bits, u32 flags);
-- 
2.1.0


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

* [PATCH v11 06/10] PCI: Introduce generic domain handling for PCI busses.
@ 2014-09-18  1:30   ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij
  Cc: linux-arch, Sinan Kaya, Kukjin Kim, Device Tree ML,
	Catalin Marinas, Jingoo Han, LKML, Grant Likely, Tanmay Inamdar,
	Suravee Suthikulanit, LAKML

From: Catalin Marinas <catalin.marinas@arm.com>

The handling of PCI domains (or PCI segments in ACPI speak) is
usually a straightforward affair but its implementation is
currently left to the architectural code, with pci_domain_nr(b)
querying the value of the domain associated with bus b.

This patch introduces CONFIG_PCI_DOMAINS_GENERIC as an
option that can be selected if an architecture want a
simple implementation where the value of the domain
associated with a bus is stored in struct pci_bus.

The architectures that select CONFIG_PCI_DOMAINS_GENERIC will
then have to implement pci_bus_assign_domain_nr() as a way
of setting the domain number associated with a root bus.
All child busses except the root bus will inherit the domain_nr
value from their parent.

Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Catalin Marinas <Catalin.Marinas@arm.com>
[Renamed pci_set_domain_nr() to pci_bus_assign_domain_nr()]
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 drivers/pci/probe.c | 11 ++++++++---
 include/linux/pci.h | 21 +++++++++++++++++++++
 2 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 5ff72ec..ef891d2 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -485,7 +485,7 @@ void pci_read_bridge_bases(struct pci_bus *child)
 	}
 }
 
-static struct pci_bus *pci_alloc_bus(void)
+static struct pci_bus *pci_alloc_bus(struct pci_bus *parent)
 {
 	struct pci_bus *b;
 
@@ -500,6 +500,10 @@ static struct pci_bus *pci_alloc_bus(void)
 	INIT_LIST_HEAD(&b->resources);
 	b->max_bus_speed = PCI_SPEED_UNKNOWN;
 	b->cur_bus_speed = PCI_SPEED_UNKNOWN;
+#ifdef CONFIG_PCI_DOMAINS_GENERIC
+	if (parent)
+		b->domain_nr = parent->domain_nr;
+#endif
 	return b;
 }
 
@@ -672,7 +676,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
 	/*
 	 * Allocate a new bus, and inherit stuff from the parent..
 	 */
-	child = pci_alloc_bus();
+	child = pci_alloc_bus(parent);
 	if (!child)
 		return NULL;
 
@@ -1768,13 +1772,14 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 
 	bridge->dev.parent = parent;
 
-	b = pci_alloc_bus();
+	b = pci_alloc_bus(NULL);
 	if (!b)
 		goto err_out;
 
 	b->sysdata = sysdata;
 	b->ops = ops;
 	b->number = b->busn_res.start = bus;
+	pci_bus_assign_domain_nr(b, parent);
 	b2 = pci_find_bus(pci_domain_nr(b), bus);
 	if (b2) {
 		/* If we already got to this bus through a different bridge, ignore it */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 61978a4..a494e5d 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -456,6 +456,9 @@ struct pci_bus {
 	unsigned char	primary;	/* number of primary bridge */
 	unsigned char	max_bus_speed;	/* enum pci_bus_speed */
 	unsigned char	cur_bus_speed;	/* enum pci_bus_speed */
+#ifdef CONFIG_PCI_DOMAINS_GENERIC
+	int		domain_nr;
+#endif
 
 	char		name[48];
 
@@ -1288,6 +1291,24 @@ static inline int pci_domain_nr(struct pci_bus *bus) { return 0; }
 static inline int pci_proc_domain(struct pci_bus *bus) { return 0; }
 #endif /* CONFIG_PCI_DOMAINS */
 
+/*
+ * Generic implementation for PCI domain support. If your
+ * architecture does not need custom management of PCI
+ * domains then this implementation will be used
+ */
+#ifdef CONFIG_PCI_DOMAINS_GENERIC
+static inline int pci_domain_nr(struct pci_bus *bus)
+{
+	return bus->domain_nr;
+}
+void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent);
+#else
+static inline void pci_bus_assign_domain_nr(struct pci_bus *bus,
+					struct device *parent)
+{
+}
+#endif
+
 /* some architectures require additional setup to direct VGA traffic */
 typedef int (*arch_set_vga_state_t)(struct pci_dev *pdev, bool decode,
 		      unsigned int command_bits, u32 flags);
-- 
2.1.0

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

* [PATCH v11 06/10] PCI: Introduce generic domain handling for PCI busses.
@ 2014-09-18  1:30   ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Catalin Marinas <catalin.marinas@arm.com>

The handling of PCI domains (or PCI segments in ACPI speak) is
usually a straightforward affair but its implementation is
currently left to the architectural code, with pci_domain_nr(b)
querying the value of the domain associated with bus b.

This patch introduces CONFIG_PCI_DOMAINS_GENERIC as an
option that can be selected if an architecture want a
simple implementation where the value of the domain
associated with a bus is stored in struct pci_bus.

The architectures that select CONFIG_PCI_DOMAINS_GENERIC will
then have to implement pci_bus_assign_domain_nr() as a way
of setting the domain number associated with a root bus.
All child busses except the root bus will inherit the domain_nr
value from their parent.

Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Catalin Marinas <Catalin.Marinas@arm.com>
[Renamed pci_set_domain_nr() to pci_bus_assign_domain_nr()]
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 drivers/pci/probe.c | 11 ++++++++---
 include/linux/pci.h | 21 +++++++++++++++++++++
 2 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 5ff72ec..ef891d2 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -485,7 +485,7 @@ void pci_read_bridge_bases(struct pci_bus *child)
 	}
 }
 
-static struct pci_bus *pci_alloc_bus(void)
+static struct pci_bus *pci_alloc_bus(struct pci_bus *parent)
 {
 	struct pci_bus *b;
 
@@ -500,6 +500,10 @@ static struct pci_bus *pci_alloc_bus(void)
 	INIT_LIST_HEAD(&b->resources);
 	b->max_bus_speed = PCI_SPEED_UNKNOWN;
 	b->cur_bus_speed = PCI_SPEED_UNKNOWN;
+#ifdef CONFIG_PCI_DOMAINS_GENERIC
+	if (parent)
+		b->domain_nr = parent->domain_nr;
+#endif
 	return b;
 }
 
@@ -672,7 +676,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
 	/*
 	 * Allocate a new bus, and inherit stuff from the parent..
 	 */
-	child = pci_alloc_bus();
+	child = pci_alloc_bus(parent);
 	if (!child)
 		return NULL;
 
@@ -1768,13 +1772,14 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 
 	bridge->dev.parent = parent;
 
-	b = pci_alloc_bus();
+	b = pci_alloc_bus(NULL);
 	if (!b)
 		goto err_out;
 
 	b->sysdata = sysdata;
 	b->ops = ops;
 	b->number = b->busn_res.start = bus;
+	pci_bus_assign_domain_nr(b, parent);
 	b2 = pci_find_bus(pci_domain_nr(b), bus);
 	if (b2) {
 		/* If we already got to this bus through a different bridge, ignore it */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 61978a4..a494e5d 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -456,6 +456,9 @@ struct pci_bus {
 	unsigned char	primary;	/* number of primary bridge */
 	unsigned char	max_bus_speed;	/* enum pci_bus_speed */
 	unsigned char	cur_bus_speed;	/* enum pci_bus_speed */
+#ifdef CONFIG_PCI_DOMAINS_GENERIC
+	int		domain_nr;
+#endif
 
 	char		name[48];
 
@@ -1288,6 +1291,24 @@ static inline int pci_domain_nr(struct pci_bus *bus) { return 0; }
 static inline int pci_proc_domain(struct pci_bus *bus) { return 0; }
 #endif /* CONFIG_PCI_DOMAINS */
 
+/*
+ * Generic implementation for PCI domain support. If your
+ * architecture does not need custom management of PCI
+ * domains then this implementation will be used
+ */
+#ifdef CONFIG_PCI_DOMAINS_GENERIC
+static inline int pci_domain_nr(struct pci_bus *bus)
+{
+	return bus->domain_nr;
+}
+void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent);
+#else
+static inline void pci_bus_assign_domain_nr(struct pci_bus *bus,
+					struct device *parent)
+{
+}
+#endif
+
 /* some architectures require additional setup to direct VGA traffic */
 typedef int (*arch_set_vga_state_t)(struct pci_dev *pdev, bool decode,
 		      unsigned int command_bits, u32 flags);
-- 
2.1.0

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

* [PATCH v11 07/10] OF: Introduce helper function for getting PCI domain_nr
  2014-09-18  1:30 ` Liviu Dudau
  (?)
@ 2014-09-18  1:30   ` Liviu Dudau
  -1 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij
  Cc: Tanmay Inamdar, Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	Grant Likely

Add of_pci_get_domain_nr() to retrieve the PCI domain number
of a given device from DT. If the information is not present,
the function can be requested to allocate a new domain number.

Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 drivers/of/of_pci.c    | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/of_pci.h |  7 ++++++
 2 files changed, 69 insertions(+)

diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index 8481996..7eaeac2 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -3,6 +3,8 @@
 #include <linux/of.h>
 #include <linux/of_pci.h>
 
+#include "of_private.h"
+
 static inline int __of_pci_pci_compare(struct device_node *node,
 				       unsigned int data)
 {
@@ -89,6 +91,66 @@ int of_pci_parse_bus_range(struct device_node *node, struct resource *res)
 }
 EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
 
+static atomic_t of_domain_nr = ATOMIC_INIT(-1);
+
+/*
+ * Get the maximum value for a domain number from the device tree
+ */
+static int of_get_max_pci_domain_nr(void)
+{
+	struct alias_prop *app;
+	int max_domain = -1;
+
+	mutex_lock(&of_mutex);
+	list_for_each_entry(app, &aliases_lookup, link) {
+		if (strncmp(app->stem, "pci-domain", 10) != 0)
+			continue;
+
+		max_domain = max(max_domain, app->id);
+	}
+	mutex_unlock(&of_mutex);
+
+	return max_domain;
+}
+
+/**
+ * This function will try to obtain the host bridge domain number by
+ * using of_alias_get_id() call with "pci-domain" as a stem. If that
+ * fails, a local allocator will be used. The local allocator can
+ * be requested to return a new domain_nr if the information is missing
+ * from the device tree.
+ *
+ * @node: device tree node with the domain information
+ * @allocate_if_missing: if DT lacks information about the domain nr,
+ * allocate a new number.
+ *
+ * Returns the associated domain number from DT, or a new domain number
+ * if DT information is missing and @allocate_if_missing is true. If
+ * @allocate_if_missing is false then the last allocated domain number
+ * will be returned.
+ */
+int of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing)
+{
+	int domain;
+
+	domain = atomic_read(&of_domain_nr);
+	if (domain == -1) {
+		/* first run, get max defined domain nr in device tree */
+		domain = of_get_max_pci_domain_nr();
+		/* then set the start value for allocator to be max + 1 */
+		atomic_set(&of_domain_nr, domain + 1);
+	}
+	domain = of_alias_get_id(node, "pci-domain");
+	if (domain == -ENODEV) {
+		domain = atomic_read(&of_domain_nr);
+		if (allocate_if_missing)
+			atomic_inc(&of_domain_nr);
+	}
+
+	return domain;
+}
+EXPORT_SYMBOL_GPL(of_pci_get_domain_nr);
+
 #ifdef CONFIG_PCI_MSI
 
 static LIST_HEAD(of_pci_msi_chip_list);
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
index dde3a4a..3a3824c 100644
--- a/include/linux/of_pci.h
+++ b/include/linux/of_pci.h
@@ -15,6 +15,7 @@ struct device_node *of_pci_find_child_device(struct device_node *parent,
 int of_pci_get_devfn(struct device_node *np);
 int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin);
 int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
+int of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing);
 #else
 static inline int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq)
 {
@@ -43,6 +44,12 @@ of_pci_parse_bus_range(struct device_node *node, struct resource *res)
 {
 	return -EINVAL;
 }
+
+static inline int
+of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing)
+{
+	return -1;
+}
 #endif
 
 #if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
-- 
2.1.0


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

* [PATCH v11 07/10] OF: Introduce helper function for getting PCI domain_nr
@ 2014-09-18  1:30   ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij
  Cc: linux-arch, Sinan Kaya, Kukjin Kim, Device Tree ML, Jingoo Han,
	LKML, Grant Likely, Tanmay Inamdar, Suravee Suthikulanit,
	Grant Likely, LAKML

Add of_pci_get_domain_nr() to retrieve the PCI domain number
of a given device from DT. If the information is not present,
the function can be requested to allocate a new domain number.

Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 drivers/of/of_pci.c    | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/of_pci.h |  7 ++++++
 2 files changed, 69 insertions(+)

diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index 8481996..7eaeac2 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -3,6 +3,8 @@
 #include <linux/of.h>
 #include <linux/of_pci.h>
 
+#include "of_private.h"
+
 static inline int __of_pci_pci_compare(struct device_node *node,
 				       unsigned int data)
 {
@@ -89,6 +91,66 @@ int of_pci_parse_bus_range(struct device_node *node, struct resource *res)
 }
 EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
 
+static atomic_t of_domain_nr = ATOMIC_INIT(-1);
+
+/*
+ * Get the maximum value for a domain number from the device tree
+ */
+static int of_get_max_pci_domain_nr(void)
+{
+	struct alias_prop *app;
+	int max_domain = -1;
+
+	mutex_lock(&of_mutex);
+	list_for_each_entry(app, &aliases_lookup, link) {
+		if (strncmp(app->stem, "pci-domain", 10) != 0)
+			continue;
+
+		max_domain = max(max_domain, app->id);
+	}
+	mutex_unlock(&of_mutex);
+
+	return max_domain;
+}
+
+/**
+ * This function will try to obtain the host bridge domain number by
+ * using of_alias_get_id() call with "pci-domain" as a stem. If that
+ * fails, a local allocator will be used. The local allocator can
+ * be requested to return a new domain_nr if the information is missing
+ * from the device tree.
+ *
+ * @node: device tree node with the domain information
+ * @allocate_if_missing: if DT lacks information about the domain nr,
+ * allocate a new number.
+ *
+ * Returns the associated domain number from DT, or a new domain number
+ * if DT information is missing and @allocate_if_missing is true. If
+ * @allocate_if_missing is false then the last allocated domain number
+ * will be returned.
+ */
+int of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing)
+{
+	int domain;
+
+	domain = atomic_read(&of_domain_nr);
+	if (domain == -1) {
+		/* first run, get max defined domain nr in device tree */
+		domain = of_get_max_pci_domain_nr();
+		/* then set the start value for allocator to be max + 1 */
+		atomic_set(&of_domain_nr, domain + 1);
+	}
+	domain = of_alias_get_id(node, "pci-domain");
+	if (domain == -ENODEV) {
+		domain = atomic_read(&of_domain_nr);
+		if (allocate_if_missing)
+			atomic_inc(&of_domain_nr);
+	}
+
+	return domain;
+}
+EXPORT_SYMBOL_GPL(of_pci_get_domain_nr);
+
 #ifdef CONFIG_PCI_MSI
 
 static LIST_HEAD(of_pci_msi_chip_list);
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
index dde3a4a..3a3824c 100644
--- a/include/linux/of_pci.h
+++ b/include/linux/of_pci.h
@@ -15,6 +15,7 @@ struct device_node *of_pci_find_child_device(struct device_node *parent,
 int of_pci_get_devfn(struct device_node *np);
 int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin);
 int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
+int of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing);
 #else
 static inline int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq)
 {
@@ -43,6 +44,12 @@ of_pci_parse_bus_range(struct device_node *node, struct resource *res)
 {
 	return -EINVAL;
 }
+
+static inline int
+of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing)
+{
+	return -1;
+}
 #endif
 
 #if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
-- 
2.1.0

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

* [PATCH v11 07/10] OF: Introduce helper function for getting PCI domain_nr
@ 2014-09-18  1:30   ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: linux-arm-kernel

Add of_pci_get_domain_nr() to retrieve the PCI domain number
of a given device from DT. If the information is not present,
the function can be requested to allocate a new domain number.

Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 drivers/of/of_pci.c    | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/of_pci.h |  7 ++++++
 2 files changed, 69 insertions(+)

diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index 8481996..7eaeac2 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -3,6 +3,8 @@
 #include <linux/of.h>
 #include <linux/of_pci.h>
 
+#include "of_private.h"
+
 static inline int __of_pci_pci_compare(struct device_node *node,
 				       unsigned int data)
 {
@@ -89,6 +91,66 @@ int of_pci_parse_bus_range(struct device_node *node, struct resource *res)
 }
 EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
 
+static atomic_t of_domain_nr = ATOMIC_INIT(-1);
+
+/*
+ * Get the maximum value for a domain number from the device tree
+ */
+static int of_get_max_pci_domain_nr(void)
+{
+	struct alias_prop *app;
+	int max_domain = -1;
+
+	mutex_lock(&of_mutex);
+	list_for_each_entry(app, &aliases_lookup, link) {
+		if (strncmp(app->stem, "pci-domain", 10) != 0)
+			continue;
+
+		max_domain = max(max_domain, app->id);
+	}
+	mutex_unlock(&of_mutex);
+
+	return max_domain;
+}
+
+/**
+ * This function will try to obtain the host bridge domain number by
+ * using of_alias_get_id() call with "pci-domain" as a stem. If that
+ * fails, a local allocator will be used. The local allocator can
+ * be requested to return a new domain_nr if the information is missing
+ * from the device tree.
+ *
+ * @node: device tree node with the domain information
+ * @allocate_if_missing: if DT lacks information about the domain nr,
+ * allocate a new number.
+ *
+ * Returns the associated domain number from DT, or a new domain number
+ * if DT information is missing and @allocate_if_missing is true. If
+ * @allocate_if_missing is false then the last allocated domain number
+ * will be returned.
+ */
+int of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing)
+{
+	int domain;
+
+	domain = atomic_read(&of_domain_nr);
+	if (domain == -1) {
+		/* first run, get max defined domain nr in device tree */
+		domain = of_get_max_pci_domain_nr();
+		/* then set the start value for allocator to be max + 1 */
+		atomic_set(&of_domain_nr, domain + 1);
+	}
+	domain = of_alias_get_id(node, "pci-domain");
+	if (domain == -ENODEV) {
+		domain = atomic_read(&of_domain_nr);
+		if (allocate_if_missing)
+			atomic_inc(&of_domain_nr);
+	}
+
+	return domain;
+}
+EXPORT_SYMBOL_GPL(of_pci_get_domain_nr);
+
 #ifdef CONFIG_PCI_MSI
 
 static LIST_HEAD(of_pci_msi_chip_list);
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
index dde3a4a..3a3824c 100644
--- a/include/linux/of_pci.h
+++ b/include/linux/of_pci.h
@@ -15,6 +15,7 @@ struct device_node *of_pci_find_child_device(struct device_node *parent,
 int of_pci_get_devfn(struct device_node *np);
 int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin);
 int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
+int of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing);
 #else
 static inline int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq)
 {
@@ -43,6 +44,12 @@ of_pci_parse_bus_range(struct device_node *node, struct resource *res)
 {
 	return -EINVAL;
 }
+
+static inline int
+of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing)
+{
+	return -1;
+}
 #endif
 
 #if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
-- 
2.1.0

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

* [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
  2014-09-18  1:30 ` Liviu Dudau
@ 2014-09-18  1:30   ` Liviu Dudau
  -1 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij
  Cc: Tanmay Inamdar, Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	Grant Likely

Provide a function to parse the PCI DT ranges that can be used to
create a pci_host_bridge structure together with its associated
bus.

Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 drivers/of/of_pci.c    | 108 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/of_pci.h |  11 +++++
 2 files changed, 119 insertions(+)

diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index 7eaeac2..c18b8da 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -1,7 +1,9 @@
 #include <linux/kernel.h>
 #include <linux/export.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_pci.h>
+#include <linux/slab.h>
 
 #include "of_private.h"
 
@@ -151,6 +153,112 @@ int of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing)
 }
 EXPORT_SYMBOL_GPL(of_pci_get_domain_nr);
 
+/**
+ * of_pci_get_host_bridge_resources - Parse PCI host bridge resources from DT
+ * @dev: device node of the host bridge having the range property
+ * @busno: bus number associated with the bridge root bus
+ * @bus_max: maximum number of busses for this bridge
+ * @resources: list where the range of resources will be added after DT parsing
+ * @io_base: pointer to a variable that will contain on return the physical
+ * address for the start of the I/O range.
+ *
+ * It is the callers job to free the @resources list.
+ *
+ * This function will parse the "ranges" property of a PCI host bridge device
+ * node and setup the resource mapping based on its content. It is expected
+ * that the property conforms with the Power ePAPR document.
+ *
+ * It returns zero if the range parsing has been successful or a standard error
+ * value if it failed.
+ */
+int of_pci_get_host_bridge_resources(struct device_node *dev,
+			unsigned char busno, unsigned char bus_max,
+			struct list_head *resources, resource_size_t *io_base)
+{
+	struct resource *res;
+	struct resource *bus_range;
+	struct of_pci_range range;
+	struct of_pci_range_parser parser;
+	char range_type[4];
+	int err;
+
+	if (!io_base)
+		return -EINVAL;
+	*io_base = OF_BAD_ADDR;
+
+	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
+	if (!bus_range)
+		return -ENOMEM;
+
+	pr_info("PCI host bridge %s ranges:\n", dev->full_name);
+
+	err = of_pci_parse_bus_range(dev, bus_range);
+	if (err) {
+		bus_range->start = busno;
+		bus_range->end = bus_max;
+		bus_range->flags = IORESOURCE_BUS;
+		pr_info("  No bus range found for %s, using %pR\n",
+			dev->full_name, &bus_range);
+	} else {
+		if (bus_range->end > bus_range->start + bus_max)
+			bus_range->end = bus_range->start + bus_max;
+	}
+	pci_add_resource(resources, bus_range);
+
+	/* Check for ranges property */
+	err = of_pci_range_parser_init(&parser, dev);
+	if (err)
+		goto parse_failed;
+
+	pr_debug("Parsing ranges property...\n");
+	for_each_of_pci_range(&parser, &range) {
+		/* Read next ranges element */
+		if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
+			snprintf(range_type, 4, " IO");
+		else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM)
+			snprintf(range_type, 4, "MEM");
+		else
+			snprintf(range_type, 4, "err");
+		pr_info("  %s %#010llx..%#010llx -> %#010llx\n", range_type,
+			range.cpu_addr, range.cpu_addr + range.size - 1,
+			range.pci_addr);
+
+		/*
+		 * If we failed translation or got a zero-sized region
+		 * then skip this range
+		 */
+		if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
+			continue;
+
+		res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+		if (!res) {
+			err = -ENOMEM;
+			goto parse_failed;
+		}
+
+		err = of_pci_range_to_resource(&range, dev, res);
+		if (err) {
+			kfree(res);
+			goto parse_failed;
+		}
+
+		if (resource_type(res) == IORESOURCE_IO) {
+			if (*io_base != OF_BAD_ADDR)
+				pr_warn("More than one I/O resource converted. CPU offset for old range lost!\n");
+			*io_base = range.cpu_addr;
+		}
+
+		pci_add_resource_offset(resources, res,	res->start - range.pci_addr);
+	}
+
+	return 0;
+
+parse_failed:
+	pci_free_resource_list(resources);
+	return err;
+}
+EXPORT_SYMBOL_GPL(of_pci_get_host_bridge_resources);
+
 #ifdef CONFIG_PCI_MSI
 
 static LIST_HEAD(of_pci_msi_chip_list);
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
index 3a3824c..a4b8a85 100644
--- a/include/linux/of_pci.h
+++ b/include/linux/of_pci.h
@@ -16,6 +16,10 @@ int of_pci_get_devfn(struct device_node *np);
 int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin);
 int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
 int of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing);
+int of_pci_get_host_bridge_resources(struct device_node *dev,
+			unsigned char busno, unsigned char bus_max,
+			struct list_head *resources, resource_size_t *io_base);
+
 #else
 static inline int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq)
 {
@@ -50,6 +54,13 @@ of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing)
 {
 	return -1;
 }
+
+int of_pci_get_host_bridge_resources(struct device_node *dev,
+			unsigned char busno, unsigned char bus_max,
+			struct list_head *resources, resource_size_t *io_base);
+{
+	return -EINVAL;
+}
 #endif
 
 #if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
-- 
2.1.0


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

* [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-18  1:30   ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: linux-arm-kernel

Provide a function to parse the PCI DT ranges that can be used to
create a pci_host_bridge structure together with its associated
bus.

Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 drivers/of/of_pci.c    | 108 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/of_pci.h |  11 +++++
 2 files changed, 119 insertions(+)

diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index 7eaeac2..c18b8da 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -1,7 +1,9 @@
 #include <linux/kernel.h>
 #include <linux/export.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_pci.h>
+#include <linux/slab.h>
 
 #include "of_private.h"
 
@@ -151,6 +153,112 @@ int of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing)
 }
 EXPORT_SYMBOL_GPL(of_pci_get_domain_nr);
 
+/**
+ * of_pci_get_host_bridge_resources - Parse PCI host bridge resources from DT
+ * @dev: device node of the host bridge having the range property
+ * @busno: bus number associated with the bridge root bus
+ * @bus_max: maximum number of busses for this bridge
+ * @resources: list where the range of resources will be added after DT parsing
+ * @io_base: pointer to a variable that will contain on return the physical
+ * address for the start of the I/O range.
+ *
+ * It is the callers job to free the @resources list.
+ *
+ * This function will parse the "ranges" property of a PCI host bridge device
+ * node and setup the resource mapping based on its content. It is expected
+ * that the property conforms with the Power ePAPR document.
+ *
+ * It returns zero if the range parsing has been successful or a standard error
+ * value if it failed.
+ */
+int of_pci_get_host_bridge_resources(struct device_node *dev,
+			unsigned char busno, unsigned char bus_max,
+			struct list_head *resources, resource_size_t *io_base)
+{
+	struct resource *res;
+	struct resource *bus_range;
+	struct of_pci_range range;
+	struct of_pci_range_parser parser;
+	char range_type[4];
+	int err;
+
+	if (!io_base)
+		return -EINVAL;
+	*io_base = OF_BAD_ADDR;
+
+	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
+	if (!bus_range)
+		return -ENOMEM;
+
+	pr_info("PCI host bridge %s ranges:\n", dev->full_name);
+
+	err = of_pci_parse_bus_range(dev, bus_range);
+	if (err) {
+		bus_range->start = busno;
+		bus_range->end = bus_max;
+		bus_range->flags = IORESOURCE_BUS;
+		pr_info("  No bus range found for %s, using %pR\n",
+			dev->full_name, &bus_range);
+	} else {
+		if (bus_range->end > bus_range->start + bus_max)
+			bus_range->end = bus_range->start + bus_max;
+	}
+	pci_add_resource(resources, bus_range);
+
+	/* Check for ranges property */
+	err = of_pci_range_parser_init(&parser, dev);
+	if (err)
+		goto parse_failed;
+
+	pr_debug("Parsing ranges property...\n");
+	for_each_of_pci_range(&parser, &range) {
+		/* Read next ranges element */
+		if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
+			snprintf(range_type, 4, " IO");
+		else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM)
+			snprintf(range_type, 4, "MEM");
+		else
+			snprintf(range_type, 4, "err");
+		pr_info("  %s %#010llx..%#010llx -> %#010llx\n", range_type,
+			range.cpu_addr, range.cpu_addr + range.size - 1,
+			range.pci_addr);
+
+		/*
+		 * If we failed translation or got a zero-sized region
+		 * then skip this range
+		 */
+		if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
+			continue;
+
+		res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+		if (!res) {
+			err = -ENOMEM;
+			goto parse_failed;
+		}
+
+		err = of_pci_range_to_resource(&range, dev, res);
+		if (err) {
+			kfree(res);
+			goto parse_failed;
+		}
+
+		if (resource_type(res) == IORESOURCE_IO) {
+			if (*io_base != OF_BAD_ADDR)
+				pr_warn("More than one I/O resource converted. CPU offset for old range lost!\n");
+			*io_base = range.cpu_addr;
+		}
+
+		pci_add_resource_offset(resources, res,	res->start - range.pci_addr);
+	}
+
+	return 0;
+
+parse_failed:
+	pci_free_resource_list(resources);
+	return err;
+}
+EXPORT_SYMBOL_GPL(of_pci_get_host_bridge_resources);
+
 #ifdef CONFIG_PCI_MSI
 
 static LIST_HEAD(of_pci_msi_chip_list);
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
index 3a3824c..a4b8a85 100644
--- a/include/linux/of_pci.h
+++ b/include/linux/of_pci.h
@@ -16,6 +16,10 @@ int of_pci_get_devfn(struct device_node *np);
 int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin);
 int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
 int of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing);
+int of_pci_get_host_bridge_resources(struct device_node *dev,
+			unsigned char busno, unsigned char bus_max,
+			struct list_head *resources, resource_size_t *io_base);
+
 #else
 static inline int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq)
 {
@@ -50,6 +54,13 @@ of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing)
 {
 	return -1;
 }
+
+int of_pci_get_host_bridge_resources(struct device_node *dev,
+			unsigned char busno, unsigned char bus_max,
+			struct list_head *resources, resource_size_t *io_base);
+{
+	return -EINVAL;
+}
 #endif
 
 #if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
-- 
2.1.0

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

* [PATCH v11 09/10] PCI: Assign unassigned bus resources in pci_scan_root_bus()
  2014-09-18  1:30 ` Liviu Dudau
  (?)
@ 2014-09-18  1:30   ` Liviu Dudau
  -1 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij
  Cc: Tanmay Inamdar, Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML

If the firmware has not assigned all the bus resources and
we are not just probing the PCIe busses, it makes sense to
assign the unassigned resources in pci_scan_root_bus().

Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Rob Herring <robh+dt@kernel.org>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 drivers/pci/probe.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ef891d2..508cf61 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1953,6 +1953,9 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
 	if (!found)
 		pci_bus_update_busn_res_end(b, max);
 
+	if (!pci_has_flag(PCI_PROBE_ONLY))
+		pci_assign_unassigned_bus_resources(b);
+
 	pci_bus_add_devices(b);
 	return b;
 }
-- 
2.1.0


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

* [PATCH v11 09/10] PCI: Assign unassigned bus resources in pci_scan_root_bus()
@ 2014-09-18  1:30   ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij
  Cc: linux-arch, Sinan Kaya, Kukjin Kim, Device Tree ML, Jingoo Han,
	LKML, Grant Likely, Tanmay Inamdar, Suravee Suthikulanit, LAKML

If the firmware has not assigned all the bus resources and
we are not just probing the PCIe busses, it makes sense to
assign the unassigned resources in pci_scan_root_bus().

Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Rob Herring <robh+dt@kernel.org>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 drivers/pci/probe.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ef891d2..508cf61 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1953,6 +1953,9 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
 	if (!found)
 		pci_bus_update_busn_res_end(b, max);
 
+	if (!pci_has_flag(PCI_PROBE_ONLY))
+		pci_assign_unassigned_bus_resources(b);
+
 	pci_bus_add_devices(b);
 	return b;
 }
-- 
2.1.0

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

* [PATCH v11 09/10] PCI: Assign unassigned bus resources in pci_scan_root_bus()
@ 2014-09-18  1:30   ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: linux-arm-kernel

If the firmware has not assigned all the bus resources and
we are not just probing the PCIe busses, it makes sense to
assign the unassigned resources in pci_scan_root_bus().

Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Rob Herring <robh+dt@kernel.org>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 drivers/pci/probe.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ef891d2..508cf61 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1953,6 +1953,9 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
 	if (!found)
 		pci_bus_update_busn_res_end(b, max);
 
+	if (!pci_has_flag(PCI_PROBE_ONLY))
+		pci_assign_unassigned_bus_resources(b);
+
 	pci_bus_add_devices(b);
 	return b;
 }
-- 
2.1.0

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

* [PATCH v11 10/10] PCI: Introduce pci_remap_iospace() for remapping PCI I/O bus resources into CPU space
  2014-09-18  1:30 ` Liviu Dudau
  (?)
@ 2014-09-18  1:30   ` Liviu Dudau
  -1 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij
  Cc: Tanmay Inamdar, Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML

Introduce a default implementation for remapping PCI bus I/O resources
onto the CPU address space. Architectures with special needs may
provide their own version, but most should be able to use this one.

Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Rob Herring <robh+dt@kernel.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 drivers/pci/pci.c             | 33 +++++++++++++++++++++++++++++++++
 include/asm-generic/pgtable.h |  4 ++++
 include/linux/pci.h           |  3 +++
 3 files changed, 40 insertions(+)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 2c9ac70..654b44c 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2704,6 +2704,39 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
 }
 EXPORT_SYMBOL(pci_request_regions_exclusive);
 
+/**
+ *	pci_remap_iospace - Remap the memory mapped I/O space
+ *	@res: Resource describing the I/O space
+ *	@phys_addr: physical address where the range will be mapped.
+ *
+ *	Remap the memory mapped I/O space described by the @res
+ *	into the CPU physical address space. Only architectures
+ *	that have memory mapped IO defined (and hence PCI_IOBASE)
+ *	should call this function.
+ */
+int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
+{
+	int err = -ENODEV;
+
+#ifdef PCI_IOBASE
+	if (!(res->flags & IORESOURCE_IO))
+		return -EINVAL;
+
+	if (res->end > IO_SPACE_LIMIT)
+		return -EINVAL;
+
+	err = ioremap_page_range(res->start + (unsigned long)PCI_IOBASE,
+				res->end + 1 + (unsigned long)PCI_IOBASE,
+				phys_addr, pgprot_device(PAGE_KERNEL));
+#else
+	/* this architecture does not have memory mapped I/O space,
+	   so this function should never be called */
+	WARN_ON(1);
+#endif
+
+	return err;
+}
+
 static void __pci_set_master(struct pci_dev *dev, bool enable)
 {
 	u16 old_cmd, cmd;
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 53b2acc..977e545 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -249,6 +249,10 @@ static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
 #define pgprot_writecombine pgprot_noncached
 #endif
 
+#ifndef pgprot_device
+#define pgprot_device pgprot_noncached
+#endif
+
 /*
  * When walking page tables, get the address of the next boundary,
  * or the end address of the range if that comes earlier.  Although no
diff --git a/include/linux/pci.h b/include/linux/pci.h
index a494e5d..fc8c529 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1100,6 +1100,9 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
 						  resource_size_t),
 			void *alignf_data);
 
+
+int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
+
 static inline dma_addr_t pci_bus_address(struct pci_dev *pdev, int bar)
 {
 	struct pci_bus_region region;
-- 
2.1.0


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

* [PATCH v11 10/10] PCI: Introduce pci_remap_iospace() for remapping PCI I/O bus resources into CPU space
@ 2014-09-18  1:30   ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij
  Cc: linux-arch, Sinan Kaya, Kukjin Kim, Device Tree ML, Jingoo Han,
	LKML, Grant Likely, Tanmay Inamdar, Suravee Suthikulanit, LAKML

Introduce a default implementation for remapping PCI bus I/O resources
onto the CPU address space. Architectures with special needs may
provide their own version, but most should be able to use this one.

Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Rob Herring <robh+dt@kernel.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 drivers/pci/pci.c             | 33 +++++++++++++++++++++++++++++++++
 include/asm-generic/pgtable.h |  4 ++++
 include/linux/pci.h           |  3 +++
 3 files changed, 40 insertions(+)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 2c9ac70..654b44c 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2704,6 +2704,39 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
 }
 EXPORT_SYMBOL(pci_request_regions_exclusive);
 
+/**
+ *	pci_remap_iospace - Remap the memory mapped I/O space
+ *	@res: Resource describing the I/O space
+ *	@phys_addr: physical address where the range will be mapped.
+ *
+ *	Remap the memory mapped I/O space described by the @res
+ *	into the CPU physical address space. Only architectures
+ *	that have memory mapped IO defined (and hence PCI_IOBASE)
+ *	should call this function.
+ */
+int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
+{
+	int err = -ENODEV;
+
+#ifdef PCI_IOBASE
+	if (!(res->flags & IORESOURCE_IO))
+		return -EINVAL;
+
+	if (res->end > IO_SPACE_LIMIT)
+		return -EINVAL;
+
+	err = ioremap_page_range(res->start + (unsigned long)PCI_IOBASE,
+				res->end + 1 + (unsigned long)PCI_IOBASE,
+				phys_addr, pgprot_device(PAGE_KERNEL));
+#else
+	/* this architecture does not have memory mapped I/O space,
+	   so this function should never be called */
+	WARN_ON(1);
+#endif
+
+	return err;
+}
+
 static void __pci_set_master(struct pci_dev *dev, bool enable)
 {
 	u16 old_cmd, cmd;
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 53b2acc..977e545 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -249,6 +249,10 @@ static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
 #define pgprot_writecombine pgprot_noncached
 #endif
 
+#ifndef pgprot_device
+#define pgprot_device pgprot_noncached
+#endif
+
 /*
  * When walking page tables, get the address of the next boundary,
  * or the end address of the range if that comes earlier.  Although no
diff --git a/include/linux/pci.h b/include/linux/pci.h
index a494e5d..fc8c529 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1100,6 +1100,9 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
 						  resource_size_t),
 			void *alignf_data);
 
+
+int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
+
 static inline dma_addr_t pci_bus_address(struct pci_dev *pdev, int bar)
 {
 	struct pci_bus_region region;
-- 
2.1.0

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

* [PATCH v11 10/10] PCI: Introduce pci_remap_iospace() for remapping PCI I/O bus resources into CPU space
@ 2014-09-18  1:30   ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-18  1:30 UTC (permalink / raw)
  To: linux-arm-kernel

Introduce a default implementation for remapping PCI bus I/O resources
onto the CPU address space. Architectures with special needs may
provide their own version, but most should be able to use this one.

Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Rob Herring <robh+dt@kernel.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 drivers/pci/pci.c             | 33 +++++++++++++++++++++++++++++++++
 include/asm-generic/pgtable.h |  4 ++++
 include/linux/pci.h           |  3 +++
 3 files changed, 40 insertions(+)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 2c9ac70..654b44c 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2704,6 +2704,39 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
 }
 EXPORT_SYMBOL(pci_request_regions_exclusive);
 
+/**
+ *	pci_remap_iospace - Remap the memory mapped I/O space
+ *	@res: Resource describing the I/O space
+ *	@phys_addr: physical address where the range will be mapped.
+ *
+ *	Remap the memory mapped I/O space described by the @res
+ *	into the CPU physical address space. Only architectures
+ *	that have memory mapped IO defined (and hence PCI_IOBASE)
+ *	should call this function.
+ */
+int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
+{
+	int err = -ENODEV;
+
+#ifdef PCI_IOBASE
+	if (!(res->flags & IORESOURCE_IO))
+		return -EINVAL;
+
+	if (res->end > IO_SPACE_LIMIT)
+		return -EINVAL;
+
+	err = ioremap_page_range(res->start + (unsigned long)PCI_IOBASE,
+				res->end + 1 + (unsigned long)PCI_IOBASE,
+				phys_addr, pgprot_device(PAGE_KERNEL));
+#else
+	/* this architecture does not have memory mapped I/O space,
+	   so this function should never be called */
+	WARN_ON(1);
+#endif
+
+	return err;
+}
+
 static void __pci_set_master(struct pci_dev *dev, bool enable)
 {
 	u16 old_cmd, cmd;
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 53b2acc..977e545 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -249,6 +249,10 @@ static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
 #define pgprot_writecombine pgprot_noncached
 #endif
 
+#ifndef pgprot_device
+#define pgprot_device pgprot_noncached
+#endif
+
 /*
  * When walking page tables, get the address of the next boundary,
  * or the end address of the range if that comes earlier.  Although no
diff --git a/include/linux/pci.h b/include/linux/pci.h
index a494e5d..fc8c529 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1100,6 +1100,9 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
 						  resource_size_t),
 			void *alignf_data);
 
+
+int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
+
 static inline dma_addr_t pci_bus_address(struct pci_dev *pdev, int bar)
 {
 	struct pci_bus_region region;
-- 
2.1.0

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

* Re: [PATCH v11 02/10] PCI: Introduce helper functions to deal with PCI I/O ranges.
@ 2014-09-19 20:48     ` Bjorn Helgaas
  0 siblings, 0 replies; 105+ messages in thread
From: Bjorn Helgaas @ 2014-09-19 20:48 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	Grant Likely

On Thu, Sep 18, 2014 at 02:30:17AM +0100, Liviu Dudau wrote:
> Some architectures do not have a simple view of the PCI I/O space
> and instead use a range of CPU addresses that map to bus addresses.
> For some architectures these ranges will be expressed by OF bindings
> in a device tree file.
> 
> This patch introduces a pci_register_io_range() helper function with
> a generic implementation that can be used by such architectures to
> keep track of the I/O ranges described by the PCI bindings. If the
> PCI_IOBASE macro is not defined that signals lack of support for PCI
> and we return an error.
> 
> In order to retrieve the CPU address associated with an I/O port, a
> new helper function pci_pio_to_address() is introduced. This will
> search in the list of ranges registered with pci_register_io_range()
> and return the CPU address that corresponds to the given port.
> 
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
> Acked-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
> ---
>  drivers/of/address.c       | 100 +++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/of_address.h |   2 +
>  2 files changed, 102 insertions(+)
> 
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index e371825..2373a92 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -5,6 +5,7 @@
>  #include <linux/module.h>
>  #include <linux/of_address.h>
>  #include <linux/pci_regs.h>
> +#include <linux/slab.h>
>  #include <linux/string.h>
>  
>  /* Max address size we deal with */
> @@ -601,12 +602,111 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
>  }
>  EXPORT_SYMBOL(of_get_address);
>  
> +#ifdef PCI_IOBASE
> +struct io_range {
> +	struct list_head list;
> +	phys_addr_t start;
> +	resource_size_t size;
> +};
> +
> +static LIST_HEAD(io_range_list);
> +static DEFINE_SPINLOCK(io_range_lock);
> +#endif
> +
> +/*
> + * Record the PCI IO range (expressed as CPU physical address + size).
> + * Return a negative value if an error has occured, zero otherwise
> + */
> +int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
> +{
> +#ifdef PCI_IOBASE
> +	struct io_range *range;
> +	resource_size_t allocated_size = 0;
> +
> +	/* check if the range hasn't been previously recorded */
> +	spin_lock(&io_range_lock);
> +	list_for_each_entry(range, &io_range_list, list) {
> +		if (addr >= range->start && addr + size <= range->start + size)
> +			return 0;

This returns while holding io_range_lock.

> +		allocated_size += range->size;
> +	}
> +	spin_unlock(&io_range_lock);

I think this is racy; because you drop the lock between (1) checking
whether the range is already recorded and (2) adding the range to the list,
it's still possible for two callers to add the same range.

> +	/* range not registed yet, check for available space */
> +	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
> +		/* if it's too big check if 64K space can be reserved */
> +		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT)
> +			return -E2BIG;
> +
> +		size = SZ_64K;
> +		pr_warn("Requested IO range too big, new size set to 64K\n");
> +	}
> +
> +	/* add the range to the list */
> +	range = kzalloc(sizeof(*range), GFP_KERNEL);
> +	if (!range)
> +		return -ENOMEM;
> +
> +	range->start = addr;
> +	range->size = size;
> +
> +	spin_lock(&io_range_lock);
> +	list_add_tail(&range->list, &io_range_list);
> +	spin_unlock(&io_range_lock);
> +#endif
> +
> +	return 0;
> +}

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

* Re: [PATCH v11 02/10] PCI: Introduce helper functions to deal with PCI I/O ranges.
@ 2014-09-19 20:48     ` Bjorn Helgaas
  0 siblings, 0 replies; 105+ messages in thread
From: Bjorn Helgaas @ 2014-09-19 20:48 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	Grant Likely

On Thu, Sep 18, 2014 at 02:30:17AM +0100, Liviu Dudau wrote:
> Some architectures do not have a simple view of the PCI I/O space
> and instead use a range of CPU addresses that map to bus addresses.
> For some architectures these ranges will be expressed by OF bindings
> in a device tree file.
> 
> This patch introduces a pci_register_io_range() helper function with
> a generic implementation that can be used by such architectures to
> keep track of the I/O ranges described by the PCI bindings. If the
> PCI_IOBASE macro is not defined that signals lack of support for PCI
> and we return an error.
> 
> In order to retrieve the CPU address associated with an I/O port, a
> new helper function pci_pio_to_address() is introduced. This will
> search in the list of ranges registered with pci_register_io_range()
> and return the CPU address that corresponds to the given port.
> 
> Cc: Grant Likely <grant.likely-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Cc: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
> Reviewed-by: Catalin Marinas <catalin.marinas-5wv7dgnIgG8@public.gmane.org>
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Signed-off-by: Liviu Dudau <Liviu.Dudau-5wv7dgnIgG8@public.gmane.org>
> ---
>  drivers/of/address.c       | 100 +++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/of_address.h |   2 +
>  2 files changed, 102 insertions(+)
> 
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index e371825..2373a92 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -5,6 +5,7 @@
>  #include <linux/module.h>
>  #include <linux/of_address.h>
>  #include <linux/pci_regs.h>
> +#include <linux/slab.h>
>  #include <linux/string.h>
>  
>  /* Max address size we deal with */
> @@ -601,12 +602,111 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
>  }
>  EXPORT_SYMBOL(of_get_address);
>  
> +#ifdef PCI_IOBASE
> +struct io_range {
> +	struct list_head list;
> +	phys_addr_t start;
> +	resource_size_t size;
> +};
> +
> +static LIST_HEAD(io_range_list);
> +static DEFINE_SPINLOCK(io_range_lock);
> +#endif
> +
> +/*
> + * Record the PCI IO range (expressed as CPU physical address + size).
> + * Return a negative value if an error has occured, zero otherwise
> + */
> +int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
> +{
> +#ifdef PCI_IOBASE
> +	struct io_range *range;
> +	resource_size_t allocated_size = 0;
> +
> +	/* check if the range hasn't been previously recorded */
> +	spin_lock(&io_range_lock);
> +	list_for_each_entry(range, &io_range_list, list) {
> +		if (addr >= range->start && addr + size <= range->start + size)
> +			return 0;

This returns while holding io_range_lock.

> +		allocated_size += range->size;
> +	}
> +	spin_unlock(&io_range_lock);

I think this is racy; because you drop the lock between (1) checking
whether the range is already recorded and (2) adding the range to the list,
it's still possible for two callers to add the same range.

> +	/* range not registed yet, check for available space */
> +	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
> +		/* if it's too big check if 64K space can be reserved */
> +		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT)
> +			return -E2BIG;
> +
> +		size = SZ_64K;
> +		pr_warn("Requested IO range too big, new size set to 64K\n");
> +	}
> +
> +	/* add the range to the list */
> +	range = kzalloc(sizeof(*range), GFP_KERNEL);
> +	if (!range)
> +		return -ENOMEM;
> +
> +	range->start = addr;
> +	range->size = size;
> +
> +	spin_lock(&io_range_lock);
> +	list_add_tail(&range->list, &io_range_list);
> +	spin_unlock(&io_range_lock);
> +#endif
> +
> +	return 0;
> +}
--
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] 105+ messages in thread

* [PATCH v11 02/10] PCI: Introduce helper functions to deal with PCI I/O ranges.
@ 2014-09-19 20:48     ` Bjorn Helgaas
  0 siblings, 0 replies; 105+ messages in thread
From: Bjorn Helgaas @ 2014-09-19 20:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 18, 2014 at 02:30:17AM +0100, Liviu Dudau wrote:
> Some architectures do not have a simple view of the PCI I/O space
> and instead use a range of CPU addresses that map to bus addresses.
> For some architectures these ranges will be expressed by OF bindings
> in a device tree file.
> 
> This patch introduces a pci_register_io_range() helper function with
> a generic implementation that can be used by such architectures to
> keep track of the I/O ranges described by the PCI bindings. If the
> PCI_IOBASE macro is not defined that signals lack of support for PCI
> and we return an error.
> 
> In order to retrieve the CPU address associated with an I/O port, a
> new helper function pci_pio_to_address() is introduced. This will
> search in the list of ranges registered with pci_register_io_range()
> and return the CPU address that corresponds to the given port.
> 
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
> Acked-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
> ---
>  drivers/of/address.c       | 100 +++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/of_address.h |   2 +
>  2 files changed, 102 insertions(+)
> 
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index e371825..2373a92 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -5,6 +5,7 @@
>  #include <linux/module.h>
>  #include <linux/of_address.h>
>  #include <linux/pci_regs.h>
> +#include <linux/slab.h>
>  #include <linux/string.h>
>  
>  /* Max address size we deal with */
> @@ -601,12 +602,111 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
>  }
>  EXPORT_SYMBOL(of_get_address);
>  
> +#ifdef PCI_IOBASE
> +struct io_range {
> +	struct list_head list;
> +	phys_addr_t start;
> +	resource_size_t size;
> +};
> +
> +static LIST_HEAD(io_range_list);
> +static DEFINE_SPINLOCK(io_range_lock);
> +#endif
> +
> +/*
> + * Record the PCI IO range (expressed as CPU physical address + size).
> + * Return a negative value if an error has occured, zero otherwise
> + */
> +int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
> +{
> +#ifdef PCI_IOBASE
> +	struct io_range *range;
> +	resource_size_t allocated_size = 0;
> +
> +	/* check if the range hasn't been previously recorded */
> +	spin_lock(&io_range_lock);
> +	list_for_each_entry(range, &io_range_list, list) {
> +		if (addr >= range->start && addr + size <= range->start + size)
> +			return 0;

This returns while holding io_range_lock.

> +		allocated_size += range->size;
> +	}
> +	spin_unlock(&io_range_lock);

I think this is racy; because you drop the lock between (1) checking
whether the range is already recorded and (2) adding the range to the list,
it's still possible for two callers to add the same range.

> +	/* range not registed yet, check for available space */
> +	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
> +		/* if it's too big check if 64K space can be reserved */
> +		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT)
> +			return -E2BIG;
> +
> +		size = SZ_64K;
> +		pr_warn("Requested IO range too big, new size set to 64K\n");
> +	}
> +
> +	/* add the range to the list */
> +	range = kzalloc(sizeof(*range), GFP_KERNEL);
> +	if (!range)
> +		return -ENOMEM;
> +
> +	range->start = addr;
> +	range->size = size;
> +
> +	spin_lock(&io_range_lock);
> +	list_add_tail(&range->list, &io_range_list);
> +	spin_unlock(&io_range_lock);
> +#endif
> +
> +	return 0;
> +}

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

* Re: [PATCH v11 04/10] PCI: OF: Fix the conversion of IO ranges into IO resources.
  2014-09-18  1:30   ` Liviu Dudau
  (?)
@ 2014-09-19 20:56     ` Bjorn Helgaas
  -1 siblings, 0 replies; 105+ messages in thread
From: Bjorn Helgaas @ 2014-09-19 20:56 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	Grant Likely, Thierry Reding, Simon Horman

On Thu, Sep 18, 2014 at 02:30:19AM +0100, Liviu Dudau wrote:
> The ranges property for a host bridge controller in DT describes
> the mapping between the PCI bus address and the CPU physical address.
> The resources framework however expects that the IO resources start
> at a pseudo "port" address 0 (zero) and have a maximum size of IO_SPACE_LIMIT.
> The conversion from pci ranges to resources failed to take that into account.
> 
> In the process move the function into drivers/of/address.c as it now
> depends on pci_address_to_pio() code and make it return an error code.

I think you're talking about of_pci_range_to_resource().  Can you split
this into one patch that moves it from of_address.h to of/address.c without
changing its functionality, and a second one that does the actual change?

Bjorn

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

* Re: [PATCH v11 04/10] PCI: OF: Fix the conversion of IO ranges into IO resources.
@ 2014-09-19 20:56     ` Bjorn Helgaas
  0 siblings, 0 replies; 105+ messages in thread
From: Bjorn Helgaas @ 2014-09-19 20:56 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	Grant Likely, Thierry Reding, Simon Horman

On Thu, Sep 18, 2014 at 02:30:19AM +0100, Liviu Dudau wrote:
> The ranges property for a host bridge controller in DT describes
> the mapping between the PCI bus address and the CPU physical address.
> The resources framework however expects that the IO resources start
> at a pseudo "port" address 0 (zero) and have a maximum size of IO_SPACE_LIMIT.
> The conversion from pci ranges to resources failed to take that into account.
> 
> In the process move the function into drivers/of/address.c as it now
> depends on pci_address_to_pio() code and make it return an error code.

I think you're talking about of_pci_range_to_resource().  Can you split
this into one patch that moves it from of_address.h to of/address.c without
changing its functionality, and a second one that does the actual change?

Bjorn

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

* [PATCH v11 04/10] PCI: OF: Fix the conversion of IO ranges into IO resources.
@ 2014-09-19 20:56     ` Bjorn Helgaas
  0 siblings, 0 replies; 105+ messages in thread
From: Bjorn Helgaas @ 2014-09-19 20:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 18, 2014 at 02:30:19AM +0100, Liviu Dudau wrote:
> The ranges property for a host bridge controller in DT describes
> the mapping between the PCI bus address and the CPU physical address.
> The resources framework however expects that the IO resources start
> at a pseudo "port" address 0 (zero) and have a maximum size of IO_SPACE_LIMIT.
> The conversion from pci ranges to resources failed to take that into account.
> 
> In the process move the function into drivers/of/address.c as it now
> depends on pci_address_to_pio() code and make it return an error code.

I think you're talking about of_pci_range_to_resource().  Can you split
this into one patch that moves it from of_address.h to of/address.c without
changing its functionality, and a second one that does the actual change?

Bjorn

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

* Re: [PATCH v11 07/10] OF: Introduce helper function for getting PCI domain_nr
  2014-09-18  1:30   ` Liviu Dudau
@ 2014-09-19 21:03     ` Bjorn Helgaas
  -1 siblings, 0 replies; 105+ messages in thread
From: Bjorn Helgaas @ 2014-09-19 21:03 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	Grant Likely

On Thu, Sep 18, 2014 at 02:30:22AM +0100, Liviu Dudau wrote:
> Add of_pci_get_domain_nr() to retrieve the PCI domain number
> of a given device from DT. If the information is not present,
> the function can be requested to allocate a new domain number.

Is of_pci_get_domain_nr() used somewhere?  If the use is in some future
series, please mention it explicitly.  I'm just trying to avoid merging
unused code.

Bjorn

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

* [PATCH v11 07/10] OF: Introduce helper function for getting PCI domain_nr
@ 2014-09-19 21:03     ` Bjorn Helgaas
  0 siblings, 0 replies; 105+ messages in thread
From: Bjorn Helgaas @ 2014-09-19 21:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 18, 2014 at 02:30:22AM +0100, Liviu Dudau wrote:
> Add of_pci_get_domain_nr() to retrieve the PCI domain number
> of a given device from DT. If the information is not present,
> the function can be requested to allocate a new domain number.

Is of_pci_get_domain_nr() used somewhere?  If the use is in some future
series, please mention it explicitly.  I'm just trying to avoid merging
unused code.

Bjorn

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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
  2014-09-18  1:30   ` Liviu Dudau
@ 2014-09-19 21:06     ` Bjorn Helgaas
  -1 siblings, 0 replies; 105+ messages in thread
From: Bjorn Helgaas @ 2014-09-19 21:06 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	Grant Likely

On Thu, Sep 18, 2014 at 02:30:23AM +0100, Liviu Dudau wrote:
> Provide a function to parse the PCI DT ranges that can be used to
> create a pci_host_bridge structure together with its associated
> bus.
> 
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
> ---
>  drivers/of/of_pci.c    | 108 +++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/of_pci.h |  11 +++++
>  2 files changed, 119 insertions(+)
> 
> diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
> index 7eaeac2..c18b8da 100644
> --- a/drivers/of/of_pci.c
> +++ b/drivers/of/of_pci.c
> @@ -1,7 +1,9 @@
>  #include <linux/kernel.h>
>  #include <linux/export.h>
>  #include <linux/of.h>
> +#include <linux/of_address.h>
>  #include <linux/of_pci.h>
> +#include <linux/slab.h>
>  
>  #include "of_private.h"
>  
> @@ -151,6 +153,112 @@ int of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing)
>  }
>  EXPORT_SYMBOL_GPL(of_pci_get_domain_nr);
>  
> +/**
> + * of_pci_get_host_bridge_resources - Parse PCI host bridge resources from DT
> + * @dev: device node of the host bridge having the range property
> + * @busno: bus number associated with the bridge root bus
> + * @bus_max: maximum number of busses for this bridge
> + * @resources: list where the range of resources will be added after DT parsing
> + * @io_base: pointer to a variable that will contain on return the physical
> + * address for the start of the I/O range.
> + *
> + * It is the callers job to free the @resources list.
> + *
> + * This function will parse the "ranges" property of a PCI host bridge device
> + * node and setup the resource mapping based on its content. It is expected
> + * that the property conforms with the Power ePAPR document.
> + *
> + * It returns zero if the range parsing has been successful or a standard error
> + * value if it failed.
> + */
> +int of_pci_get_host_bridge_resources(struct device_node *dev,
> +			unsigned char busno, unsigned char bus_max,
> +			struct list_head *resources, resource_size_t *io_base)
> +{
> +	struct resource *res;
> +	struct resource *bus_range;
> +	struct of_pci_range range;
> +	struct of_pci_range_parser parser;
> +	char range_type[4];
> +	int err;
> +
> +	if (!io_base)
> +		return -EINVAL;
> +	*io_base = OF_BAD_ADDR;
> +
> +	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
> +	if (!bus_range)
> +		return -ENOMEM;
> +
> +	pr_info("PCI host bridge %s ranges:\n", dev->full_name);
> +
> +	err = of_pci_parse_bus_range(dev, bus_range);
> +	if (err) {
> +		bus_range->start = busno;
> +		bus_range->end = bus_max;
> +		bus_range->flags = IORESOURCE_BUS;
> +		pr_info("  No bus range found for %s, using %pR\n",
> +			dev->full_name, &bus_range);
> +	} else {
> +		if (bus_range->end > bus_range->start + bus_max)
> +			bus_range->end = bus_range->start + bus_max;
> +	}
> +	pci_add_resource(resources, bus_range);
> +
> +	/* Check for ranges property */
> +	err = of_pci_range_parser_init(&parser, dev);
> +	if (err)
> +		goto parse_failed;
> +
> +	pr_debug("Parsing ranges property...\n");
> +	for_each_of_pci_range(&parser, &range) {
> +		/* Read next ranges element */
> +		if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
> +			snprintf(range_type, 4, " IO");
> +		else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM)
> +			snprintf(range_type, 4, "MEM");
> +		else
> +			snprintf(range_type, 4, "err");
> +		pr_info("  %s %#010llx..%#010llx -> %#010llx\n", range_type,
> +			range.cpu_addr, range.cpu_addr + range.size - 1,
> +			range.pci_addr);
> +
> +		/*
> +		 * If we failed translation or got a zero-sized region
> +		 * then skip this range
> +		 */
> +		if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
> +			continue;
> +
> +		res = kzalloc(sizeof(struct resource), GFP_KERNEL);
> +		if (!res) {
> +			err = -ENOMEM;
> +			goto parse_failed;
> +		}
> +
> +		err = of_pci_range_to_resource(&range, dev, res);
> +		if (err) {
> +			kfree(res);
> +			goto parse_failed;
> +		}
> +
> +		if (resource_type(res) == IORESOURCE_IO) {
> +			if (*io_base != OF_BAD_ADDR)
> +				pr_warn("More than one I/O resource converted. CPU offset for old range lost!\n");

It'd be nice if the output included a hint about which device this warning
applies to.

> +			*io_base = range.cpu_addr;
> +		}
> +
> +		pci_add_resource_offset(resources, res,	res->start - range.pci_addr);
> +	}
> +
> +	return 0;
> +
> +parse_failed:
> +	pci_free_resource_list(resources);
> +	return err;
> +}
> +EXPORT_SYMBOL_GPL(of_pci_get_host_bridge_resources);
> +
>  #ifdef CONFIG_PCI_MSI
>  
>  static LIST_HEAD(of_pci_msi_chip_list);
> diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
> index 3a3824c..a4b8a85 100644
> --- a/include/linux/of_pci.h
> +++ b/include/linux/of_pci.h
> @@ -16,6 +16,10 @@ int of_pci_get_devfn(struct device_node *np);
>  int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin);
>  int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
>  int of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing);
> +int of_pci_get_host_bridge_resources(struct device_node *dev,
> +			unsigned char busno, unsigned char bus_max,
> +			struct list_head *resources, resource_size_t *io_base);
> +
>  #else
>  static inline int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq)
>  {
> @@ -50,6 +54,13 @@ of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing)
>  {
>  	return -1;
>  }
> +
> +int of_pci_get_host_bridge_resources(struct device_node *dev,
> +			unsigned char busno, unsigned char bus_max,
> +			struct list_head *resources, resource_size_t *io_base);
> +{
> +	return -EINVAL;
> +}
>  #endif
>  
>  #if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
> -- 
> 2.1.0
> 

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

* [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-19 21:06     ` Bjorn Helgaas
  0 siblings, 0 replies; 105+ messages in thread
From: Bjorn Helgaas @ 2014-09-19 21:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 18, 2014 at 02:30:23AM +0100, Liviu Dudau wrote:
> Provide a function to parse the PCI DT ranges that can be used to
> create a pci_host_bridge structure together with its associated
> bus.
> 
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
> ---
>  drivers/of/of_pci.c    | 108 +++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/of_pci.h |  11 +++++
>  2 files changed, 119 insertions(+)
> 
> diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
> index 7eaeac2..c18b8da 100644
> --- a/drivers/of/of_pci.c
> +++ b/drivers/of/of_pci.c
> @@ -1,7 +1,9 @@
>  #include <linux/kernel.h>
>  #include <linux/export.h>
>  #include <linux/of.h>
> +#include <linux/of_address.h>
>  #include <linux/of_pci.h>
> +#include <linux/slab.h>
>  
>  #include "of_private.h"
>  
> @@ -151,6 +153,112 @@ int of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing)
>  }
>  EXPORT_SYMBOL_GPL(of_pci_get_domain_nr);
>  
> +/**
> + * of_pci_get_host_bridge_resources - Parse PCI host bridge resources from DT
> + * @dev: device node of the host bridge having the range property
> + * @busno: bus number associated with the bridge root bus
> + * @bus_max: maximum number of busses for this bridge
> + * @resources: list where the range of resources will be added after DT parsing
> + * @io_base: pointer to a variable that will contain on return the physical
> + * address for the start of the I/O range.
> + *
> + * It is the callers job to free the @resources list.
> + *
> + * This function will parse the "ranges" property of a PCI host bridge device
> + * node and setup the resource mapping based on its content. It is expected
> + * that the property conforms with the Power ePAPR document.
> + *
> + * It returns zero if the range parsing has been successful or a standard error
> + * value if it failed.
> + */
> +int of_pci_get_host_bridge_resources(struct device_node *dev,
> +			unsigned char busno, unsigned char bus_max,
> +			struct list_head *resources, resource_size_t *io_base)
> +{
> +	struct resource *res;
> +	struct resource *bus_range;
> +	struct of_pci_range range;
> +	struct of_pci_range_parser parser;
> +	char range_type[4];
> +	int err;
> +
> +	if (!io_base)
> +		return -EINVAL;
> +	*io_base = OF_BAD_ADDR;
> +
> +	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
> +	if (!bus_range)
> +		return -ENOMEM;
> +
> +	pr_info("PCI host bridge %s ranges:\n", dev->full_name);
> +
> +	err = of_pci_parse_bus_range(dev, bus_range);
> +	if (err) {
> +		bus_range->start = busno;
> +		bus_range->end = bus_max;
> +		bus_range->flags = IORESOURCE_BUS;
> +		pr_info("  No bus range found for %s, using %pR\n",
> +			dev->full_name, &bus_range);
> +	} else {
> +		if (bus_range->end > bus_range->start + bus_max)
> +			bus_range->end = bus_range->start + bus_max;
> +	}
> +	pci_add_resource(resources, bus_range);
> +
> +	/* Check for ranges property */
> +	err = of_pci_range_parser_init(&parser, dev);
> +	if (err)
> +		goto parse_failed;
> +
> +	pr_debug("Parsing ranges property...\n");
> +	for_each_of_pci_range(&parser, &range) {
> +		/* Read next ranges element */
> +		if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
> +			snprintf(range_type, 4, " IO");
> +		else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM)
> +			snprintf(range_type, 4, "MEM");
> +		else
> +			snprintf(range_type, 4, "err");
> +		pr_info("  %s %#010llx..%#010llx -> %#010llx\n", range_type,
> +			range.cpu_addr, range.cpu_addr + range.size - 1,
> +			range.pci_addr);
> +
> +		/*
> +		 * If we failed translation or got a zero-sized region
> +		 * then skip this range
> +		 */
> +		if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
> +			continue;
> +
> +		res = kzalloc(sizeof(struct resource), GFP_KERNEL);
> +		if (!res) {
> +			err = -ENOMEM;
> +			goto parse_failed;
> +		}
> +
> +		err = of_pci_range_to_resource(&range, dev, res);
> +		if (err) {
> +			kfree(res);
> +			goto parse_failed;
> +		}
> +
> +		if (resource_type(res) == IORESOURCE_IO) {
> +			if (*io_base != OF_BAD_ADDR)
> +				pr_warn("More than one I/O resource converted. CPU offset for old range lost!\n");

It'd be nice if the output included a hint about which device this warning
applies to.

> +			*io_base = range.cpu_addr;
> +		}
> +
> +		pci_add_resource_offset(resources, res,	res->start - range.pci_addr);
> +	}
> +
> +	return 0;
> +
> +parse_failed:
> +	pci_free_resource_list(resources);
> +	return err;
> +}
> +EXPORT_SYMBOL_GPL(of_pci_get_host_bridge_resources);
> +
>  #ifdef CONFIG_PCI_MSI
>  
>  static LIST_HEAD(of_pci_msi_chip_list);
> diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
> index 3a3824c..a4b8a85 100644
> --- a/include/linux/of_pci.h
> +++ b/include/linux/of_pci.h
> @@ -16,6 +16,10 @@ int of_pci_get_devfn(struct device_node *np);
>  int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin);
>  int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
>  int of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing);
> +int of_pci_get_host_bridge_resources(struct device_node *dev,
> +			unsigned char busno, unsigned char bus_max,
> +			struct list_head *resources, resource_size_t *io_base);
> +
>  #else
>  static inline int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq)
>  {
> @@ -50,6 +54,13 @@ of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing)
>  {
>  	return -1;
>  }
> +
> +int of_pci_get_host_bridge_resources(struct device_node *dev,
> +			unsigned char busno, unsigned char bus_max,
> +			struct list_head *resources, resource_size_t *io_base);
> +{
> +	return -EINVAL;
> +}
>  #endif
>  
>  #if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
> -- 
> 2.1.0
> 

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

* Re: [PATCH v11 10/10] PCI: Introduce pci_remap_iospace() for remapping PCI I/O bus resources into CPU space
  2014-09-18  1:30   ` Liviu Dudau
@ 2014-09-19 21:54     ` Bjorn Helgaas
  -1 siblings, 0 replies; 105+ messages in thread
From: Bjorn Helgaas @ 2014-09-19 21:54 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML

On Thu, Sep 18, 2014 at 02:30:25AM +0100, Liviu Dudau wrote:
> Introduce a default implementation for remapping PCI bus I/O resources
> onto the CPU address space. Architectures with special needs may
> provide their own version, but most should be able to use this one.

I see that this is used by Tanmay's APM X-Gene PCIe host controller driver.
Since it's not used in this series, it'd be nice to mention where it *will*
be used.

> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
> ---
>  drivers/pci/pci.c             | 33 +++++++++++++++++++++++++++++++++
>  include/asm-generic/pgtable.h |  4 ++++
>  include/linux/pci.h           |  3 +++
>  3 files changed, 40 insertions(+)
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 2c9ac70..654b44c 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -2704,6 +2704,39 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
>  }
>  EXPORT_SYMBOL(pci_request_regions_exclusive);
>  
> +/**
> + *	pci_remap_iospace - Remap the memory mapped I/O space
> + *	@res: Resource describing the I/O space
> + *	@phys_addr: physical address where the range will be mapped.
> + *
> + *	Remap the memory mapped I/O space described by the @res
> + *	into the CPU physical address space. 

This comment doesn't seem quite right.  I think the space is already in the
CPU physical address space.  ioremap() and friends normally map existing
physical space into the *virtual* address space, i.e., they create mappings
from a virtual address to a physical address.

> Only architectures
> + *	that have memory mapped IO defined (and hence PCI_IOBASE)
> + *	should call this function.
> + */
> +int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
> +{
> +	int err = -ENODEV;
> +
> +#ifdef PCI_IOBASE
> +	if (!(res->flags & IORESOURCE_IO))
> +		return -EINVAL;
> +
> +	if (res->end > IO_SPACE_LIMIT)
> +		return -EINVAL;
> +

PCI_IOBASE is a virtual address.  So PCI_IOBASE + res->start is also a
virtual address (only for IORESOURCE_IO).

Since res->start is normally a *physical* address, I think it would be less
confusing to do something like this:

    vaddr = PCI_IOBASE + res->start;
    ioremap_page_range(vaddr, vaddr + resource_size(res), ...);

so we have a hint that the first two ioremap_page_range() parameters are
virtual addresses.  It's also confusing that it uses "unsigned long" for
the virtual addresses, when we usually use "void *".  But that's out of
scope for this patch.

> +	err = ioremap_page_range(res->start + (unsigned long)PCI_IOBASE,
> +				res->end + 1 + (unsigned long)PCI_IOBASE,
> +				phys_addr, pgprot_device(PAGE_KERNEL));
> +#else
> +	/* this architecture does not have memory mapped I/O space,
> +	   so this function should never be called */
> +	WARN_ON(1);
> +#endif
> +
> +	return err;
> +}
> +
>  static void __pci_set_master(struct pci_dev *dev, bool enable)
>  {
>  	u16 old_cmd, cmd;
> diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
> index 53b2acc..977e545 100644
> --- a/include/asm-generic/pgtable.h
> +++ b/include/asm-generic/pgtable.h
> @@ -249,6 +249,10 @@ static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
>  #define pgprot_writecombine pgprot_noncached
>  #endif
>  
> +#ifndef pgprot_device
> +#define pgprot_device pgprot_noncached
> +#endif
> +
>  /*
>   * When walking page tables, get the address of the next boundary,
>   * or the end address of the range if that comes earlier.  Although no
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index a494e5d..fc8c529 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1100,6 +1100,9 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
>  						  resource_size_t),
>  			void *alignf_data);
>  
> +
> +int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
> +
>  static inline dma_addr_t pci_bus_address(struct pci_dev *pdev, int bar)
>  {
>  	struct pci_bus_region region;
> -- 
> 2.1.0
> 

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

* [PATCH v11 10/10] PCI: Introduce pci_remap_iospace() for remapping PCI I/O bus resources into CPU space
@ 2014-09-19 21:54     ` Bjorn Helgaas
  0 siblings, 0 replies; 105+ messages in thread
From: Bjorn Helgaas @ 2014-09-19 21:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 18, 2014 at 02:30:25AM +0100, Liviu Dudau wrote:
> Introduce a default implementation for remapping PCI bus I/O resources
> onto the CPU address space. Architectures with special needs may
> provide their own version, but most should be able to use this one.

I see that this is used by Tanmay's APM X-Gene PCIe host controller driver.
Since it's not used in this series, it'd be nice to mention where it *will*
be used.

> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
> ---
>  drivers/pci/pci.c             | 33 +++++++++++++++++++++++++++++++++
>  include/asm-generic/pgtable.h |  4 ++++
>  include/linux/pci.h           |  3 +++
>  3 files changed, 40 insertions(+)
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 2c9ac70..654b44c 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -2704,6 +2704,39 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
>  }
>  EXPORT_SYMBOL(pci_request_regions_exclusive);
>  
> +/**
> + *	pci_remap_iospace - Remap the memory mapped I/O space
> + *	@res: Resource describing the I/O space
> + *	@phys_addr: physical address where the range will be mapped.
> + *
> + *	Remap the memory mapped I/O space described by the @res
> + *	into the CPU physical address space. 

This comment doesn't seem quite right.  I think the space is already in the
CPU physical address space.  ioremap() and friends normally map existing
physical space into the *virtual* address space, i.e., they create mappings
from a virtual address to a physical address.

> Only architectures
> + *	that have memory mapped IO defined (and hence PCI_IOBASE)
> + *	should call this function.
> + */
> +int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
> +{
> +	int err = -ENODEV;
> +
> +#ifdef PCI_IOBASE
> +	if (!(res->flags & IORESOURCE_IO))
> +		return -EINVAL;
> +
> +	if (res->end > IO_SPACE_LIMIT)
> +		return -EINVAL;
> +

PCI_IOBASE is a virtual address.  So PCI_IOBASE + res->start is also a
virtual address (only for IORESOURCE_IO).

Since res->start is normally a *physical* address, I think it would be less
confusing to do something like this:

    vaddr = PCI_IOBASE + res->start;
    ioremap_page_range(vaddr, vaddr + resource_size(res), ...);

so we have a hint that the first two ioremap_page_range() parameters are
virtual addresses.  It's also confusing that it uses "unsigned long" for
the virtual addresses, when we usually use "void *".  But that's out of
scope for this patch.

> +	err = ioremap_page_range(res->start + (unsigned long)PCI_IOBASE,
> +				res->end + 1 + (unsigned long)PCI_IOBASE,
> +				phys_addr, pgprot_device(PAGE_KERNEL));
> +#else
> +	/* this architecture does not have memory mapped I/O space,
> +	   so this function should never be called */
> +	WARN_ON(1);
> +#endif
> +
> +	return err;
> +}
> +
>  static void __pci_set_master(struct pci_dev *dev, bool enable)
>  {
>  	u16 old_cmd, cmd;
> diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
> index 53b2acc..977e545 100644
> --- a/include/asm-generic/pgtable.h
> +++ b/include/asm-generic/pgtable.h
> @@ -249,6 +249,10 @@ static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
>  #define pgprot_writecombine pgprot_noncached
>  #endif
>  
> +#ifndef pgprot_device
> +#define pgprot_device pgprot_noncached
> +#endif
> +
>  /*
>   * When walking page tables, get the address of the next boundary,
>   * or the end address of the range if that comes earlier.  Although no
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index a494e5d..fc8c529 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1100,6 +1100,9 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
>  						  resource_size_t),
>  			void *alignf_data);
>  
> +
> +int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
> +
>  static inline dma_addr_t pci_bus_address(struct pci_dev *pdev, int bar)
>  {
>  	struct pci_bus_region region;
> -- 
> 2.1.0
> 

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

* Re: [PATCH v11 00/10] Support for creating generic PCI host bridges from DT
  2014-09-18  1:30 ` Liviu Dudau
@ 2014-09-19 21:59   ` Bjorn Helgaas
  -1 siblings, 0 replies; 105+ messages in thread
From: Bjorn Helgaas @ 2014-09-19 21:59 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML

On Thu, Sep 18, 2014 at 02:30:15AM +0100, Liviu Dudau wrote:
> This is my version 11 of the attempt at adding support for generic PCI host
> bridge controllers that make use of device tree information to
> configure themselves. It contains minor cleanups compared with v10 to address
> the existing comments.
> ...
> Catalin Marinas (1):
>   PCI: Introduce generic domain handling for PCI busses.
> 
> Liviu Dudau (9):
>   Fix ioport_map() for !CONFIG_GENERIC_IOMAP cases.
>   PCI: Introduce helper functions to deal with PCI I/O ranges.
>   ARM: Define PCI_IOBASE as the base of virtual PCI IO space.
>   PCI: OF: Fix the conversion of IO ranges into IO resources.
>   PCI: Create pci_host_bridge before its associated bus in
>     pci_create_root_bus.
>   OF: Introduce helper function for getting PCI domain_nr
>   OF: PCI: Add support for parsing PCI host bridge resources from DT
>   PCI: Assign unassigned bus resources in pci_scan_root_bus()
>   PCI: Introduce pci_remap_iospace() for remapping PCI I/O bus resources
>     into CPU space
> 
>  arch/arm/include/asm/io.h         |   1 +
>  arch/arm/mach-integrator/pci_v3.c |  23 +++---
>  drivers/of/address.c              | 146 ++++++++++++++++++++++++++++++++
>  drivers/of/of_pci.c               | 170 ++++++++++++++++++++++++++++++++++++++
>  drivers/pci/host/pci-tegra.c      |  10 ++-
>  drivers/pci/host/pcie-rcar.c      |  21 +++--
>  drivers/pci/pci.c                 |  33 ++++++++
>  drivers/pci/probe.c               |  46 +++++++----
>  include/asm-generic/io.h          |   2 +-
>  include/asm-generic/pgtable.h     |   4 +
>  include/linux/of_address.h        |  15 +---
>  include/linux/of_pci.h            |  18 ++++
>  include/linux/pci.h               |  24 ++++++
>  13 files changed, 463 insertions(+), 50 deletions(-)

I put this on a pci/liviu-generic-v11 branch.  I mentioned a couple things
in response to the individual patches, so I'm hoping you can send me
incremental patches to address them.  Then I'll update this branch, rename
it, and get it into linux-next.

Bjorn

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

* [PATCH v11 00/10] Support for creating generic PCI host bridges from DT
@ 2014-09-19 21:59   ` Bjorn Helgaas
  0 siblings, 0 replies; 105+ messages in thread
From: Bjorn Helgaas @ 2014-09-19 21:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 18, 2014 at 02:30:15AM +0100, Liviu Dudau wrote:
> This is my version 11 of the attempt at adding support for generic PCI host
> bridge controllers that make use of device tree information to
> configure themselves. It contains minor cleanups compared with v10 to address
> the existing comments.
> ...
> Catalin Marinas (1):
>   PCI: Introduce generic domain handling for PCI busses.
> 
> Liviu Dudau (9):
>   Fix ioport_map() for !CONFIG_GENERIC_IOMAP cases.
>   PCI: Introduce helper functions to deal with PCI I/O ranges.
>   ARM: Define PCI_IOBASE as the base of virtual PCI IO space.
>   PCI: OF: Fix the conversion of IO ranges into IO resources.
>   PCI: Create pci_host_bridge before its associated bus in
>     pci_create_root_bus.
>   OF: Introduce helper function for getting PCI domain_nr
>   OF: PCI: Add support for parsing PCI host bridge resources from DT
>   PCI: Assign unassigned bus resources in pci_scan_root_bus()
>   PCI: Introduce pci_remap_iospace() for remapping PCI I/O bus resources
>     into CPU space
> 
>  arch/arm/include/asm/io.h         |   1 +
>  arch/arm/mach-integrator/pci_v3.c |  23 +++---
>  drivers/of/address.c              | 146 ++++++++++++++++++++++++++++++++
>  drivers/of/of_pci.c               | 170 ++++++++++++++++++++++++++++++++++++++
>  drivers/pci/host/pci-tegra.c      |  10 ++-
>  drivers/pci/host/pcie-rcar.c      |  21 +++--
>  drivers/pci/pci.c                 |  33 ++++++++
>  drivers/pci/probe.c               |  46 +++++++----
>  include/asm-generic/io.h          |   2 +-
>  include/asm-generic/pgtable.h     |   4 +
>  include/linux/of_address.h        |  15 +---
>  include/linux/of_pci.h            |  18 ++++
>  include/linux/pci.h               |  24 ++++++
>  13 files changed, 463 insertions(+), 50 deletions(-)

I put this on a pci/liviu-generic-v11 branch.  I mentioned a couple things
in response to the individual patches, so I'm hoping you can send me
incremental patches to address them.  Then I'll update this branch, rename
it, and get it into linux-next.

Bjorn

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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
  2014-09-19 21:06     ` Bjorn Helgaas
@ 2014-09-20  0:28       ` Rob Herring
  -1 siblings, 0 replies; 105+ messages in thread
From: Rob Herring @ 2014-09-20  0:28 UTC (permalink / raw)
  To: Bjorn Helgaas, Liviu Dudau
  Cc: Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	Grant Likely

On 09/19/2014 04:06 PM, Bjorn Helgaas wrote:
> On Thu, Sep 18, 2014 at 02:30:23AM +0100, Liviu Dudau wrote:
>> Provide a function to parse the PCI DT ranges that can be used to
>> create a pci_host_bridge structure together with its associated
>> bus.
>>
>> Cc: Bjorn Helgaas <bhelgaas@google.com>
>> Cc: Arnd Bergmann <arnd@arndb.de>
>> Cc: Grant Likely <grant.likely@linaro.org>
>> Cc: Rob Herring <robh+dt@kernel.org>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
>> ---

[...]

>> +int of_pci_get_host_bridge_resources(struct device_node *dev,
>> +			unsigned char busno, unsigned char bus_max,
>> +			struct list_head *resources, resource_size_t *io_base)
>> +{
>> +	struct resource *res;
>> +	struct resource *bus_range;
>> +	struct of_pci_range range;
>> +	struct of_pci_range_parser parser;
>> +	char range_type[4];
>> +	int err;
>> +
>> +	if (!io_base)
>> +		return -EINVAL;
>> +	*io_base = OF_BAD_ADDR;
>> +
>> +	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);

This function does a lot of kalloc's but there is not an easy way to
undo those allocations. Hot unplug of a host bridge or probe error
handling would leak memory.

You could pass in struct device and use the devm_ variant (also
addressing Bjorn's comment), but not having an uninit/remove function
make what clean-up drivers have to do error prone. For example, on
uninit a driver needs to call pci_free_resource_list.

Rob

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

* [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-20  0:28       ` Rob Herring
  0 siblings, 0 replies; 105+ messages in thread
From: Rob Herring @ 2014-09-20  0:28 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/19/2014 04:06 PM, Bjorn Helgaas wrote:
> On Thu, Sep 18, 2014 at 02:30:23AM +0100, Liviu Dudau wrote:
>> Provide a function to parse the PCI DT ranges that can be used to
>> create a pci_host_bridge structure together with its associated
>> bus.
>>
>> Cc: Bjorn Helgaas <bhelgaas@google.com>
>> Cc: Arnd Bergmann <arnd@arndb.de>
>> Cc: Grant Likely <grant.likely@linaro.org>
>> Cc: Rob Herring <robh+dt@kernel.org>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
>> ---

[...]

>> +int of_pci_get_host_bridge_resources(struct device_node *dev,
>> +			unsigned char busno, unsigned char bus_max,
>> +			struct list_head *resources, resource_size_t *io_base)
>> +{
>> +	struct resource *res;
>> +	struct resource *bus_range;
>> +	struct of_pci_range range;
>> +	struct of_pci_range_parser parser;
>> +	char range_type[4];
>> +	int err;
>> +
>> +	if (!io_base)
>> +		return -EINVAL;
>> +	*io_base = OF_BAD_ADDR;
>> +
>> +	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);

This function does a lot of kalloc's but there is not an easy way to
undo those allocations. Hot unplug of a host bridge or probe error
handling would leak memory.

You could pass in struct device and use the devm_ variant (also
addressing Bjorn's comment), but not having an uninit/remove function
make what clean-up drivers have to do error prone. For example, on
uninit a driver needs to call pci_free_resource_list.

Rob

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

* Re: [PATCH v11 10/10] PCI: Introduce pci_remap_iospace() for remapping PCI I/O bus resources into CPU space
  2014-09-18  1:30   ` Liviu Dudau
@ 2014-09-20  0:34     ` Rob Herring
  -1 siblings, 0 replies; 105+ messages in thread
From: Rob Herring @ 2014-09-20  0:34 UTC (permalink / raw)
  To: Liviu Dudau, Bjorn Helgaas, Arnd Bergmann, Rob Herring,
	Jason Gunthorpe, Benjamin Herrenschmidt, Catalin Marinas,
	Will Deacon, Russell King, linux-pci, Linus Walleij
  Cc: Tanmay Inamdar, Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML

On 09/17/2014 08:30 PM, Liviu Dudau wrote:
> Introduce a default implementation for remapping PCI bus I/O resources
> onto the CPU address space. Architectures with special needs may
> provide their own version, but most should be able to use this one.
> 
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>

One nit below, otherwise:

Reviewed-by: Rob Herring <robh@kernel.org>

> ---
>  drivers/pci/pci.c             | 33 +++++++++++++++++++++++++++++++++
>  include/asm-generic/pgtable.h |  4 ++++
>  include/linux/pci.h           |  3 +++
>  3 files changed, 40 insertions(+)
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 2c9ac70..654b44c 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -2704,6 +2704,39 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
>  }
>  EXPORT_SYMBOL(pci_request_regions_exclusive);
>  
> +/**
> + *	pci_remap_iospace - Remap the memory mapped I/O space
> + *	@res: Resource describing the I/O space
> + *	@phys_addr: physical address where the range will be mapped.
> + *
> + *	Remap the memory mapped I/O space described by the @res
> + *	into the CPU physical address space. Only architectures
> + *	that have memory mapped IO defined (and hence PCI_IOBASE)
> + *	should call this function.
> + */
> +int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
> +{
> +	int err = -ENODEV;
> +
> +#ifdef PCI_IOBASE
> +	if (!(res->flags & IORESOURCE_IO))
> +		return -EINVAL;
> +
> +	if (res->end > IO_SPACE_LIMIT)
> +		return -EINVAL;
> +
> +	err = ioremap_page_range(res->start + (unsigned long)PCI_IOBASE,
> +				res->end + 1 + (unsigned long)PCI_IOBASE,
> +				phys_addr, pgprot_device(PAGE_KERNEL));
> +#else
> +	/* this architecture does not have memory mapped I/O space,
> +	   so this function should never be called */
> +	WARN_ON(1);

Printing what the comment says in the warning would be better than
making the user look-up why they got a warning.

Rob


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

* [PATCH v11 10/10] PCI: Introduce pci_remap_iospace() for remapping PCI I/O bus resources into CPU space
@ 2014-09-20  0:34     ` Rob Herring
  0 siblings, 0 replies; 105+ messages in thread
From: Rob Herring @ 2014-09-20  0:34 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/17/2014 08:30 PM, Liviu Dudau wrote:
> Introduce a default implementation for remapping PCI bus I/O resources
> onto the CPU address space. Architectures with special needs may
> provide their own version, but most should be able to use this one.
> 
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>

One nit below, otherwise:

Reviewed-by: Rob Herring <robh@kernel.org>

> ---
>  drivers/pci/pci.c             | 33 +++++++++++++++++++++++++++++++++
>  include/asm-generic/pgtable.h |  4 ++++
>  include/linux/pci.h           |  3 +++
>  3 files changed, 40 insertions(+)
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 2c9ac70..654b44c 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -2704,6 +2704,39 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
>  }
>  EXPORT_SYMBOL(pci_request_regions_exclusive);
>  
> +/**
> + *	pci_remap_iospace - Remap the memory mapped I/O space
> + *	@res: Resource describing the I/O space
> + *	@phys_addr: physical address where the range will be mapped.
> + *
> + *	Remap the memory mapped I/O space described by the @res
> + *	into the CPU physical address space. Only architectures
> + *	that have memory mapped IO defined (and hence PCI_IOBASE)
> + *	should call this function.
> + */
> +int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
> +{
> +	int err = -ENODEV;
> +
> +#ifdef PCI_IOBASE
> +	if (!(res->flags & IORESOURCE_IO))
> +		return -EINVAL;
> +
> +	if (res->end > IO_SPACE_LIMIT)
> +		return -EINVAL;
> +
> +	err = ioremap_page_range(res->start + (unsigned long)PCI_IOBASE,
> +				res->end + 1 + (unsigned long)PCI_IOBASE,
> +				phys_addr, pgprot_device(PAGE_KERNEL));
> +#else
> +	/* this architecture does not have memory mapped I/O space,
> +	   so this function should never be called */
> +	WARN_ON(1);

Printing what the comment says in the warning would be better than
making the user look-up why they got a warning.

Rob

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

* Re: [PATCH v11 03/10] ARM: Define PCI_IOBASE as the base of virtual PCI IO space.
@ 2014-09-20  2:14     ` Arnd Bergmann
  0 siblings, 0 replies; 105+ messages in thread
From: Arnd Bergmann @ 2014-09-20  2:14 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Bjorn Helgaas, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML

On Thursday 18 September 2014, Liviu Dudau wrote:
> This is needed for calls into OF code that parses PCI ranges.
> It signals support for memory mapped PCI I/O accesses that
> are described be device trees.
> 
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>

Acked-by: Arnd Bergmann <arnd@arndb.de>

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

* Re: [PATCH v11 03/10] ARM: Define PCI_IOBASE as the base of virtual PCI IO space.
@ 2014-09-20  2:14     ` Arnd Bergmann
  0 siblings, 0 replies; 105+ messages in thread
From: Arnd Bergmann @ 2014-09-20  2:14 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Bjorn Helgaas, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML

On Thursday 18 September 2014, Liviu Dudau wrote:
> This is needed for calls into OF code that parses PCI ranges.
> It signals support for memory mapped PCI I/O accesses that
> are described be device trees.
> 
> Cc: Russell King <linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org>
> Cc: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
> Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Reviewed-by: Catalin Marinas <catalin.marinas-5wv7dgnIgG8@public.gmane.org>
> Signed-off-by: Liviu Dudau <Liviu.Dudau-5wv7dgnIgG8@public.gmane.org>

Acked-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
--
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] 105+ messages in thread

* [PATCH v11 03/10] ARM: Define PCI_IOBASE as the base of virtual PCI IO space.
@ 2014-09-20  2:14     ` Arnd Bergmann
  0 siblings, 0 replies; 105+ messages in thread
From: Arnd Bergmann @ 2014-09-20  2:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 18 September 2014, Liviu Dudau wrote:
> This is needed for calls into OF code that parses PCI ranges.
> It signals support for memory mapped PCI I/O accesses that
> are described be device trees.
> 
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>

Acked-by: Arnd Bergmann <arnd@arndb.de>

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

* Re: [PATCH v11 10/10] PCI: Introduce pci_remap_iospace() for remapping PCI I/O bus resources into CPU space
  2014-09-19 21:54     ` Bjorn Helgaas
@ 2014-09-20  2:20       ` Arnd Bergmann
  -1 siblings, 0 replies; 105+ messages in thread
From: Arnd Bergmann @ 2014-09-20  2:20 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Liviu Dudau, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML

On Friday 19 September 2014, Bjorn Helgaas wrote:
> On Thu, Sep 18, 2014 at 02:30:25AM +0100, Liviu Dudau wrote:

> PCI_IOBASE is a virtual address.  So PCI_IOBASE + res->start is also a
> virtual address (only for IORESOURCE_IO).
> 
> Since res->start is normally a *physical* address, I think it would be less
> confusing to do something like this:
> 
>     vaddr = PCI_IOBASE + res->start;
>     ioremap_page_range(vaddr, vaddr + resource_size(res), ...);
> 
> so we have a hint that the first two ioremap_page_range() parameters are
> virtual addresses.  It's also confusing that it uses "unsigned long" for
> the virtual addresses, when we usually use "void *".  But that's out of
> scope for this patch.

Good idea. I think it will have to be (unsigned long)PCI_IOBASE above then,
since ioremap_page_range takes a 'unsigned long' virtual address and PCI_IOBASE
should really remain an __iomem pointer.

	Arnd

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

* [PATCH v11 10/10] PCI: Introduce pci_remap_iospace() for remapping PCI I/O bus resources into CPU space
@ 2014-09-20  2:20       ` Arnd Bergmann
  0 siblings, 0 replies; 105+ messages in thread
From: Arnd Bergmann @ 2014-09-20  2:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday 19 September 2014, Bjorn Helgaas wrote:
> On Thu, Sep 18, 2014 at 02:30:25AM +0100, Liviu Dudau wrote:

> PCI_IOBASE is a virtual address.  So PCI_IOBASE + res->start is also a
> virtual address (only for IORESOURCE_IO).
> 
> Since res->start is normally a *physical* address, I think it would be less
> confusing to do something like this:
> 
>     vaddr = PCI_IOBASE + res->start;
>     ioremap_page_range(vaddr, vaddr + resource_size(res), ...);
> 
> so we have a hint that the first two ioremap_page_range() parameters are
> virtual addresses.  It's also confusing that it uses "unsigned long" for
> the virtual addresses, when we usually use "void *".  But that's out of
> scope for this patch.

Good idea. I think it will have to be (unsigned long)PCI_IOBASE above then,
since ioremap_page_range takes a 'unsigned long' virtual address and PCI_IOBASE
should really remain an __iomem pointer.

	Arnd

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

* Re: [PATCH v11 07/10] OF: Introduce helper function for getting PCI domain_nr
  2014-09-18  1:30   ` Liviu Dudau
@ 2014-09-20  2:24     ` Arnd Bergmann
  -1 siblings, 0 replies; 105+ messages in thread
From: Arnd Bergmann @ 2014-09-20  2:24 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Bjorn Helgaas, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	Grant Likely

On Thursday 18 September 2014, Liviu Dudau wrote:
> 
> Add of_pci_get_domain_nr() to retrieve the PCI domain number
> of a given device from DT. If the information is not present,
> the function can be requested to allocate a new domain number.
> 
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: Rob Herring <robh+dt@kernel.org>
> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>

This is more elaborate than I remember it, and while the simpler
version (which potentially resulted in a conflict for inconsistent
DTs) was fine, this one also seems ok.

Acked-by: Arnd Bergmann <arnd@arndb.de>

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

* [PATCH v11 07/10] OF: Introduce helper function for getting PCI domain_nr
@ 2014-09-20  2:24     ` Arnd Bergmann
  0 siblings, 0 replies; 105+ messages in thread
From: Arnd Bergmann @ 2014-09-20  2:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 18 September 2014, Liviu Dudau wrote:
> 
> Add of_pci_get_domain_nr() to retrieve the PCI domain number
> of a given device from DT. If the information is not present,
> the function can be requested to allocate a new domain number.
> 
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: Rob Herring <robh+dt@kernel.org>
> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>

This is more elaborate than I remember it, and while the simpler
version (which potentially resulted in a conflict for inconsistent
DTs) was fine, this one also seems ok.

Acked-by: Arnd Bergmann <arnd@arndb.de>

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

* Re: [PATCH v11 04/10] PCI: OF: Fix the conversion of IO ranges into IO resources.
  2014-09-18  1:30   ` Liviu Dudau
@ 2014-09-20 17:33     ` Rob Herring
  -1 siblings, 0 replies; 105+ messages in thread
From: Rob Herring @ 2014-09-20 17:33 UTC (permalink / raw)
  To: Liviu Dudau, Bjorn Helgaas, Arnd Bergmann, Rob Herring,
	Jason Gunthorpe, Benjamin Herrenschmidt, Catalin Marinas,
	Will Deacon, Russell King, linux-pci, Linus Walleij
  Cc: Tanmay Inamdar, Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	Grant Likely, Thierry Reding, Simon Horman

On 09/17/2014 08:30 PM, Liviu Dudau wrote:
> The ranges property for a host bridge controller in DT describes
> the mapping between the PCI bus address and the CPU physical address.
> The resources framework however expects that the IO resources start
> at a pseudo "port" address 0 (zero) and have a maximum size of IO_SPACE_LIMIT.
> The conversion from pci ranges to resources failed to take that into account.
> 
> In the process move the function into drivers/of/address.c as it now
> depends on pci_address_to_pio() code and make it return an error code.
> Also fix all the drivers that depend on the old behaviour by fetching
> the CPU physical address based on the port number.
> 
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: Thierry Reding <thierry.reding@gmail.com>
> Cc: Simon Horman <horms@verge.net.au>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>

A few minor things below.

> ---
>  arch/arm/mach-integrator/pci_v3.c | 23 ++++++++++----------
>  drivers/of/address.c              | 46 +++++++++++++++++++++++++++++++++++++++
>  drivers/pci/host/pci-tegra.c      | 10 ++++++---
>  drivers/pci/host/pcie-rcar.c      | 21 +++++++++++++-----
>  include/linux/of_address.h        | 13 ++---------
>  5 files changed, 82 insertions(+), 31 deletions(-)
> 
> diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
> index 05e1f73..3321e1b 100644
> --- a/arch/arm/mach-integrator/pci_v3.c
> +++ b/arch/arm/mach-integrator/pci_v3.c
> @@ -660,6 +660,7 @@ static void __init pci_v3_preinit(void)
>  {
>  	unsigned long flags;
>  	unsigned int temp;
> +	phys_addr_t io_address = pci_pio_to_address(io_mem.start);
>  
>  	pcibios_min_mem = 0x00100000;
>  
> @@ -701,7 +702,7 @@ static void __init pci_v3_preinit(void)
>  	/*
>  	 * Setup window 2 - PCI IO
>  	 */
> -	v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_mem.start) |
> +	v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_address) |
>  			V3_LB_BASE_ENABLE);
>  	v3_writew(V3_LB_MAP2, v3_addr_to_lb_map2(0));
>  
> @@ -742,6 +743,7 @@ static void __init pci_v3_preinit(void)
>  static void __init pci_v3_postinit(void)
>  {
>  	unsigned int pci_cmd;
> +	phys_addr_t io_address = pci_pio_to_address(io_mem.start);
>  
>  	pci_cmd = PCI_COMMAND_MEMORY |
>  		  PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
> @@ -758,7 +760,7 @@ static void __init pci_v3_postinit(void)
>  		       "interrupt: %d\n", ret);
>  #endif
>  
> -	register_isa_ports(non_mem.start, io_mem.start, 0);
> +	register_isa_ports(non_mem.start, io_address, 0);
>  }
>  
>  /*
> @@ -867,33 +869,32 @@ static int __init pci_v3_probe(struct platform_device *pdev)
>  
>  	for_each_of_pci_range(&parser, &range) {
>  		if (!range.flags) {
> -			of_pci_range_to_resource(&range, np, &conf_mem);
> +			ret = of_pci_range_to_resource(&range, np, &conf_mem);
>  			conf_mem.name = "PCIv3 config";
>  		}
>  		if (range.flags & IORESOURCE_IO) {
> -			of_pci_range_to_resource(&range, np, &io_mem);
> +			ret = of_pci_range_to_resource(&range, np, &io_mem);
>  			io_mem.name = "PCIv3 I/O";
>  		}
>  		if ((range.flags & IORESOURCE_MEM) &&
>  			!(range.flags & IORESOURCE_PREFETCH)) {
>  			non_mem_pci = range.pci_addr;
>  			non_mem_pci_sz = range.size;
> -			of_pci_range_to_resource(&range, np, &non_mem);
> +			ret = of_pci_range_to_resource(&range, np, &non_mem);
>  			non_mem.name = "PCIv3 non-prefetched mem";
>  		}
>  		if ((range.flags & IORESOURCE_MEM) &&
>  			(range.flags & IORESOURCE_PREFETCH)) {
>  			pre_mem_pci = range.pci_addr;
>  			pre_mem_pci_sz = range.size;
> -			of_pci_range_to_resource(&range, np, &pre_mem);
> +			ret = of_pci_range_to_resource(&range, np, &pre_mem);
>  			pre_mem.name = "PCIv3 prefetched mem";
>  		}
> -	}
>  
> -	if (!conf_mem.start || !io_mem.start ||
> -	    !non_mem.start || !pre_mem.start) {
> -		dev_err(&pdev->dev, "missing ranges in device node\n");
> -		return -EINVAL;
> +		if (ret < 0) {
> +			dev_err(&pdev->dev, "missing ranges in device node\n");
> +			return -EINVAL;

You should return ret rather than potentially changing the return value.

> +		}
>  	}
>  
>  	pci_v3.map_irq = of_irq_parse_and_map_pci;
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 2373a92..ff10b64 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -947,3 +947,49 @@ bool of_dma_is_coherent(struct device_node *np)
>  	return false;
>  }
>  EXPORT_SYMBOL_GPL(of_dma_is_coherent);
> +
> +/*
> + * of_pci_range_to_resource - Create a resource from an of_pci_range
> + * @range:	the PCI range that describes the resource
> + * @np:		device node where the range belongs to
> + * @res:	pointer to a valid resource that will be updated to
> + *              reflect the values contained in the range.
> + *
> + * Returns EINVAL if the range cannot be converted to resource.
> + *
> + * Note that if the range is an IO range, the resource will be converted
> + * using pci_address_to_pio() which can fail if it is called too early or
> + * if the range cannot be matched to any host bridge IO space (our case here).
> + * To guard against that we try to register the IO range first.
> + * If that fails we know that pci_address_to_pio() will do too.
> + */
> +int of_pci_range_to_resource(struct of_pci_range *range,
> +	struct device_node *np, struct resource *res)
> +{
> +	int err;
> +	res->flags = range->flags;
> +	res->parent = res->child = res->sibling = NULL;
> +	res->name = np->full_name;
> +
> +	if (res->flags & IORESOURCE_IO) {
> +		unsigned long port = -1;

Assigning a signed value to unsigned...

Does port need to be 64-bit on 64-bit hosts?

> +		err = pci_register_io_range(range->cpu_addr, range->size);
> +		if (err)
> +			goto invalid_range;
> +		port = pci_address_to_pio(range->cpu_addr);
> +		if (port == (unsigned long)-1) {
> +			err = -EINVAL;
> +			goto invalid_range;
> +		}
> +		res->start = port;
> +	} else {
> +		res->start = range->cpu_addr;
> +	}
> +	res->end = res->start + range->size - 1;
> +	return 0;
> +
> +invalid_range:
> +	res->start = (resource_size_t)OF_BAD_ADDR;
> +	res->end = (resource_size_t)OF_BAD_ADDR;
> +	return err;
> +}
> diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
> index 0fb0fdb..946935d 100644
> --- a/drivers/pci/host/pci-tegra.c
> +++ b/drivers/pci/host/pci-tegra.c
> @@ -626,13 +626,14 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable);
>  static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
>  {
>  	struct tegra_pcie *pcie = sys_to_pcie(sys);
> +	phys_addr_t io_start = pci_pio_to_address(pcie->io.start);
>  
>  	pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
>  	pci_add_resource_offset(&sys->resources, &pcie->prefetch,
>  				sys->mem_offset);
>  	pci_add_resource(&sys->resources, &pcie->busn);
>  
> -	pci_ioremap_io(nr * SZ_64K, pcie->io.start);
> +	pci_ioremap_io(nr * SZ_64K, io_start);
>  
>  	return 1;
>  }
> @@ -737,6 +738,7 @@ static irqreturn_t tegra_pcie_isr(int irq, void *arg)
>  static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
>  {
>  	u32 fpci_bar, size, axi_address;
> +	phys_addr_t io_start = pci_pio_to_address(pcie->io.start);
>  
>  	/* Bar 0: type 1 extended configuration space */
>  	fpci_bar = 0xfe100000;
> @@ -749,7 +751,7 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
>  	/* Bar 1: downstream IO bar */
>  	fpci_bar = 0xfdfc0000;
>  	size = resource_size(&pcie->io);
> -	axi_address = pcie->io.start;
> +	axi_address = io_start;
>  	afi_writel(pcie, axi_address, AFI_AXI_BAR1_START);
>  	afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ);
>  	afi_writel(pcie, fpci_bar, AFI_FPCI_BAR1);
> @@ -1520,7 +1522,9 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
>  	}
>  
>  	for_each_of_pci_range(&parser, &range) {
> -		of_pci_range_to_resource(&range, np, &res);
> +		err = of_pci_range_to_resource(&range, np, &res);
> +		if (err < 0)
> +			return err;
>  
>  		switch (res.flags & IORESOURCE_TYPE_BITS) {
>  		case IORESOURCE_IO:
> diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
> index 4884ee5..61158e0 100644
> --- a/drivers/pci/host/pcie-rcar.c
> +++ b/drivers/pci/host/pcie-rcar.c
> @@ -323,6 +323,7 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
>  
>  	/* Setup PCIe address space mappings for each resource */
>  	resource_size_t size;
> +	resource_size_t res_start;
>  	u32 mask;
>  
>  	rcar_pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
> @@ -335,8 +336,13 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
>  	mask = (roundup_pow_of_two(size) / SZ_128) - 1;
>  	rcar_pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
>  
> -	rcar_pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win));
> -	rcar_pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win));
> +	if (res->flags & IORESOURCE_IO)
> +		res_start = pci_pio_to_address(res->start);
> +	else
> +		res_start = res->start;
> +
> +	rcar_pci_write_reg(pcie, upper_32_bits(res_start), PCIEPARH(win));
> +	rcar_pci_write_reg(pcie, lower_32_bits(res_start), PCIEPARL(win));
>  
>  	/* First resource is for IO */
>  	mask = PAR_ENABLE;
> @@ -363,9 +369,10 @@ static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
>  
>  		rcar_pcie_setup_window(i, pcie);
>  
> -		if (res->flags & IORESOURCE_IO)
> -			pci_ioremap_io(nr * SZ_64K, res->start);
> -		else
> +		if (res->flags & IORESOURCE_IO) {
> +			phys_addr_t io_start = pci_pio_to_address(res->start);
> +			pci_ioremap_io(nr * SZ_64K, io_start);
> +		} else
>  			pci_add_resource(&sys->resources, res);
>  	}
>  	pci_add_resource(&sys->resources, &pcie->busn);
> @@ -935,8 +942,10 @@ static int rcar_pcie_probe(struct platform_device *pdev)
>  	}
>  
>  	for_each_of_pci_range(&parser, &range) {
> -		of_pci_range_to_resource(&range, pdev->dev.of_node,
> +		err = of_pci_range_to_resource(&range, pdev->dev.of_node,
>  						&pcie->res[win++]);
> +		if (err < 0)
> +			return err;
>  
>  		if (win > RCAR_PCI_MAX_RESOURCES)
>  			break;
> diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> index f8cc7da..c9d70deb 100644
> --- a/include/linux/of_address.h
> +++ b/include/linux/of_address.h
> @@ -23,17 +23,8 @@ struct of_pci_range {
>  #define for_each_of_pci_range(parser, range) \
>  	for (; of_pci_range_parser_one(parser, range);)
>  
> -static inline void of_pci_range_to_resource(struct of_pci_range *range,
> -					    struct device_node *np,
> -					    struct resource *res)
> -{
> -	res->flags = range->flags;
> -	res->start = range->cpu_addr;
> -	res->end = range->cpu_addr + range->size - 1;
> -	res->parent = res->child = res->sibling = NULL;
> -	res->name = np->full_name;
> -}
> -
> +extern int of_pci_range_to_resource(struct of_pci_range *range,
> +		struct device_node *np, struct resource *res);

We probably need an empty version of this now for !OF_ADDRESS.

Rob

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

* [PATCH v11 04/10] PCI: OF: Fix the conversion of IO ranges into IO resources.
@ 2014-09-20 17:33     ` Rob Herring
  0 siblings, 0 replies; 105+ messages in thread
From: Rob Herring @ 2014-09-20 17:33 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/17/2014 08:30 PM, Liviu Dudau wrote:
> The ranges property for a host bridge controller in DT describes
> the mapping between the PCI bus address and the CPU physical address.
> The resources framework however expects that the IO resources start
> at a pseudo "port" address 0 (zero) and have a maximum size of IO_SPACE_LIMIT.
> The conversion from pci ranges to resources failed to take that into account.
> 
> In the process move the function into drivers/of/address.c as it now
> depends on pci_address_to_pio() code and make it return an error code.
> Also fix all the drivers that depend on the old behaviour by fetching
> the CPU physical address based on the port number.
> 
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: Thierry Reding <thierry.reding@gmail.com>
> Cc: Simon Horman <horms@verge.net.au>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>

A few minor things below.

> ---
>  arch/arm/mach-integrator/pci_v3.c | 23 ++++++++++----------
>  drivers/of/address.c              | 46 +++++++++++++++++++++++++++++++++++++++
>  drivers/pci/host/pci-tegra.c      | 10 ++++++---
>  drivers/pci/host/pcie-rcar.c      | 21 +++++++++++++-----
>  include/linux/of_address.h        | 13 ++---------
>  5 files changed, 82 insertions(+), 31 deletions(-)
> 
> diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
> index 05e1f73..3321e1b 100644
> --- a/arch/arm/mach-integrator/pci_v3.c
> +++ b/arch/arm/mach-integrator/pci_v3.c
> @@ -660,6 +660,7 @@ static void __init pci_v3_preinit(void)
>  {
>  	unsigned long flags;
>  	unsigned int temp;
> +	phys_addr_t io_address = pci_pio_to_address(io_mem.start);
>  
>  	pcibios_min_mem = 0x00100000;
>  
> @@ -701,7 +702,7 @@ static void __init pci_v3_preinit(void)
>  	/*
>  	 * Setup window 2 - PCI IO
>  	 */
> -	v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_mem.start) |
> +	v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_address) |
>  			V3_LB_BASE_ENABLE);
>  	v3_writew(V3_LB_MAP2, v3_addr_to_lb_map2(0));
>  
> @@ -742,6 +743,7 @@ static void __init pci_v3_preinit(void)
>  static void __init pci_v3_postinit(void)
>  {
>  	unsigned int pci_cmd;
> +	phys_addr_t io_address = pci_pio_to_address(io_mem.start);
>  
>  	pci_cmd = PCI_COMMAND_MEMORY |
>  		  PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
> @@ -758,7 +760,7 @@ static void __init pci_v3_postinit(void)
>  		       "interrupt: %d\n", ret);
>  #endif
>  
> -	register_isa_ports(non_mem.start, io_mem.start, 0);
> +	register_isa_ports(non_mem.start, io_address, 0);
>  }
>  
>  /*
> @@ -867,33 +869,32 @@ static int __init pci_v3_probe(struct platform_device *pdev)
>  
>  	for_each_of_pci_range(&parser, &range) {
>  		if (!range.flags) {
> -			of_pci_range_to_resource(&range, np, &conf_mem);
> +			ret = of_pci_range_to_resource(&range, np, &conf_mem);
>  			conf_mem.name = "PCIv3 config";
>  		}
>  		if (range.flags & IORESOURCE_IO) {
> -			of_pci_range_to_resource(&range, np, &io_mem);
> +			ret = of_pci_range_to_resource(&range, np, &io_mem);
>  			io_mem.name = "PCIv3 I/O";
>  		}
>  		if ((range.flags & IORESOURCE_MEM) &&
>  			!(range.flags & IORESOURCE_PREFETCH)) {
>  			non_mem_pci = range.pci_addr;
>  			non_mem_pci_sz = range.size;
> -			of_pci_range_to_resource(&range, np, &non_mem);
> +			ret = of_pci_range_to_resource(&range, np, &non_mem);
>  			non_mem.name = "PCIv3 non-prefetched mem";
>  		}
>  		if ((range.flags & IORESOURCE_MEM) &&
>  			(range.flags & IORESOURCE_PREFETCH)) {
>  			pre_mem_pci = range.pci_addr;
>  			pre_mem_pci_sz = range.size;
> -			of_pci_range_to_resource(&range, np, &pre_mem);
> +			ret = of_pci_range_to_resource(&range, np, &pre_mem);
>  			pre_mem.name = "PCIv3 prefetched mem";
>  		}
> -	}
>  
> -	if (!conf_mem.start || !io_mem.start ||
> -	    !non_mem.start || !pre_mem.start) {
> -		dev_err(&pdev->dev, "missing ranges in device node\n");
> -		return -EINVAL;
> +		if (ret < 0) {
> +			dev_err(&pdev->dev, "missing ranges in device node\n");
> +			return -EINVAL;

You should return ret rather than potentially changing the return value.

> +		}
>  	}
>  
>  	pci_v3.map_irq = of_irq_parse_and_map_pci;
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 2373a92..ff10b64 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -947,3 +947,49 @@ bool of_dma_is_coherent(struct device_node *np)
>  	return false;
>  }
>  EXPORT_SYMBOL_GPL(of_dma_is_coherent);
> +
> +/*
> + * of_pci_range_to_resource - Create a resource from an of_pci_range
> + * @range:	the PCI range that describes the resource
> + * @np:		device node where the range belongs to
> + * @res:	pointer to a valid resource that will be updated to
> + *              reflect the values contained in the range.
> + *
> + * Returns EINVAL if the range cannot be converted to resource.
> + *
> + * Note that if the range is an IO range, the resource will be converted
> + * using pci_address_to_pio() which can fail if it is called too early or
> + * if the range cannot be matched to any host bridge IO space (our case here).
> + * To guard against that we try to register the IO range first.
> + * If that fails we know that pci_address_to_pio() will do too.
> + */
> +int of_pci_range_to_resource(struct of_pci_range *range,
> +	struct device_node *np, struct resource *res)
> +{
> +	int err;
> +	res->flags = range->flags;
> +	res->parent = res->child = res->sibling = NULL;
> +	res->name = np->full_name;
> +
> +	if (res->flags & IORESOURCE_IO) {
> +		unsigned long port = -1;

Assigning a signed value to unsigned...

Does port need to be 64-bit on 64-bit hosts?

> +		err = pci_register_io_range(range->cpu_addr, range->size);
> +		if (err)
> +			goto invalid_range;
> +		port = pci_address_to_pio(range->cpu_addr);
> +		if (port == (unsigned long)-1) {
> +			err = -EINVAL;
> +			goto invalid_range;
> +		}
> +		res->start = port;
> +	} else {
> +		res->start = range->cpu_addr;
> +	}
> +	res->end = res->start + range->size - 1;
> +	return 0;
> +
> +invalid_range:
> +	res->start = (resource_size_t)OF_BAD_ADDR;
> +	res->end = (resource_size_t)OF_BAD_ADDR;
> +	return err;
> +}
> diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
> index 0fb0fdb..946935d 100644
> --- a/drivers/pci/host/pci-tegra.c
> +++ b/drivers/pci/host/pci-tegra.c
> @@ -626,13 +626,14 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable);
>  static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
>  {
>  	struct tegra_pcie *pcie = sys_to_pcie(sys);
> +	phys_addr_t io_start = pci_pio_to_address(pcie->io.start);
>  
>  	pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
>  	pci_add_resource_offset(&sys->resources, &pcie->prefetch,
>  				sys->mem_offset);
>  	pci_add_resource(&sys->resources, &pcie->busn);
>  
> -	pci_ioremap_io(nr * SZ_64K, pcie->io.start);
> +	pci_ioremap_io(nr * SZ_64K, io_start);
>  
>  	return 1;
>  }
> @@ -737,6 +738,7 @@ static irqreturn_t tegra_pcie_isr(int irq, void *arg)
>  static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
>  {
>  	u32 fpci_bar, size, axi_address;
> +	phys_addr_t io_start = pci_pio_to_address(pcie->io.start);
>  
>  	/* Bar 0: type 1 extended configuration space */
>  	fpci_bar = 0xfe100000;
> @@ -749,7 +751,7 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
>  	/* Bar 1: downstream IO bar */
>  	fpci_bar = 0xfdfc0000;
>  	size = resource_size(&pcie->io);
> -	axi_address = pcie->io.start;
> +	axi_address = io_start;
>  	afi_writel(pcie, axi_address, AFI_AXI_BAR1_START);
>  	afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ);
>  	afi_writel(pcie, fpci_bar, AFI_FPCI_BAR1);
> @@ -1520,7 +1522,9 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
>  	}
>  
>  	for_each_of_pci_range(&parser, &range) {
> -		of_pci_range_to_resource(&range, np, &res);
> +		err = of_pci_range_to_resource(&range, np, &res);
> +		if (err < 0)
> +			return err;
>  
>  		switch (res.flags & IORESOURCE_TYPE_BITS) {
>  		case IORESOURCE_IO:
> diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
> index 4884ee5..61158e0 100644
> --- a/drivers/pci/host/pcie-rcar.c
> +++ b/drivers/pci/host/pcie-rcar.c
> @@ -323,6 +323,7 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
>  
>  	/* Setup PCIe address space mappings for each resource */
>  	resource_size_t size;
> +	resource_size_t res_start;
>  	u32 mask;
>  
>  	rcar_pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
> @@ -335,8 +336,13 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
>  	mask = (roundup_pow_of_two(size) / SZ_128) - 1;
>  	rcar_pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
>  
> -	rcar_pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win));
> -	rcar_pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win));
> +	if (res->flags & IORESOURCE_IO)
> +		res_start = pci_pio_to_address(res->start);
> +	else
> +		res_start = res->start;
> +
> +	rcar_pci_write_reg(pcie, upper_32_bits(res_start), PCIEPARH(win));
> +	rcar_pci_write_reg(pcie, lower_32_bits(res_start), PCIEPARL(win));
>  
>  	/* First resource is for IO */
>  	mask = PAR_ENABLE;
> @@ -363,9 +369,10 @@ static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
>  
>  		rcar_pcie_setup_window(i, pcie);
>  
> -		if (res->flags & IORESOURCE_IO)
> -			pci_ioremap_io(nr * SZ_64K, res->start);
> -		else
> +		if (res->flags & IORESOURCE_IO) {
> +			phys_addr_t io_start = pci_pio_to_address(res->start);
> +			pci_ioremap_io(nr * SZ_64K, io_start);
> +		} else
>  			pci_add_resource(&sys->resources, res);
>  	}
>  	pci_add_resource(&sys->resources, &pcie->busn);
> @@ -935,8 +942,10 @@ static int rcar_pcie_probe(struct platform_device *pdev)
>  	}
>  
>  	for_each_of_pci_range(&parser, &range) {
> -		of_pci_range_to_resource(&range, pdev->dev.of_node,
> +		err = of_pci_range_to_resource(&range, pdev->dev.of_node,
>  						&pcie->res[win++]);
> +		if (err < 0)
> +			return err;
>  
>  		if (win > RCAR_PCI_MAX_RESOURCES)
>  			break;
> diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> index f8cc7da..c9d70deb 100644
> --- a/include/linux/of_address.h
> +++ b/include/linux/of_address.h
> @@ -23,17 +23,8 @@ struct of_pci_range {
>  #define for_each_of_pci_range(parser, range) \
>  	for (; of_pci_range_parser_one(parser, range);)
>  
> -static inline void of_pci_range_to_resource(struct of_pci_range *range,
> -					    struct device_node *np,
> -					    struct resource *res)
> -{
> -	res->flags = range->flags;
> -	res->start = range->cpu_addr;
> -	res->end = range->cpu_addr + range->size - 1;
> -	res->parent = res->child = res->sibling = NULL;
> -	res->name = np->full_name;
> -}
> -
> +extern int of_pci_range_to_resource(struct of_pci_range *range,
> +		struct device_node *np, struct resource *res);

We probably need an empty version of this now for !OF_ADDRESS.

Rob

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

* Re: [PATCH v11 07/10] OF: Introduce helper function for getting PCI domain_nr
  2014-09-18  1:30   ` Liviu Dudau
@ 2014-09-20 17:52     ` Rob Herring
  -1 siblings, 0 replies; 105+ messages in thread
From: Rob Herring @ 2014-09-20 17:52 UTC (permalink / raw)
  To: Liviu Dudau, Bjorn Helgaas, Arnd Bergmann, Rob Herring,
	Jason Gunthorpe, Benjamin Herrenschmidt, Catalin Marinas,
	Will Deacon, Russell King, linux-pci, Linus Walleij
  Cc: Tanmay Inamdar, Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	Grant Likely

On 09/17/2014 08:30 PM, Liviu Dudau wrote:
> Add of_pci_get_domain_nr() to retrieve the PCI domain number
> of a given device from DT. If the information is not present,
> the function can be requested to allocate a new domain number.
> 
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: Rob Herring <robh+dt@kernel.org>
> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
> ---

[...]

> +/**
> + * This function will try to obtain the host bridge domain number by
> + * using of_alias_get_id() call with "pci-domain" as a stem. If that
> + * fails, a local allocator will be used. The local allocator can
> + * be requested to return a new domain_nr if the information is missing
> + * from the device tree.
> + *
> + * @node: device tree node with the domain information
> + * @allocate_if_missing: if DT lacks information about the domain nr,
> + * allocate a new number.
> + *
> + * Returns the associated domain number from DT, or a new domain number
> + * if DT information is missing and @allocate_if_missing is true. If
> + * @allocate_if_missing is false then the last allocated domain number
> + * will be returned.
> + */
> +int of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing)
> +{
> +	int domain;
> +
> +	domain = atomic_read(&of_domain_nr);
> +	if (domain == -1) {
> +		/* first run, get max defined domain nr in device tree */
> +		domain = of_get_max_pci_domain_nr();
> +		/* then set the start value for allocator to be max + 1 */
> +		atomic_set(&of_domain_nr, domain + 1);

atomic_read followed by atomic_set is not an atomic operation.

As I previously said, I don't like how this function is a mixture of
data retrieval and domian # allocation. I think we need 2 functions.

> +	}
> +	domain = of_alias_get_id(node, "pci-domain");

I still do not like using aliases here. Just put pci-domain or
linux,pci-domain into the PCI node.

I think we should assume all PCI root buses either have a domain
property or they don't and a mixture is an error. I'm not sure if that
simplifies the code or not though.

In the interest of merging, I think you should just do a simple
allocation and add the DT domain handling as a second step. You will
also need to document the DT part.

Rob


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

* [PATCH v11 07/10] OF: Introduce helper function for getting PCI domain_nr
@ 2014-09-20 17:52     ` Rob Herring
  0 siblings, 0 replies; 105+ messages in thread
From: Rob Herring @ 2014-09-20 17:52 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/17/2014 08:30 PM, Liviu Dudau wrote:
> Add of_pci_get_domain_nr() to retrieve the PCI domain number
> of a given device from DT. If the information is not present,
> the function can be requested to allocate a new domain number.
> 
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: Rob Herring <robh+dt@kernel.org>
> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
> ---

[...]

> +/**
> + * This function will try to obtain the host bridge domain number by
> + * using of_alias_get_id() call with "pci-domain" as a stem. If that
> + * fails, a local allocator will be used. The local allocator can
> + * be requested to return a new domain_nr if the information is missing
> + * from the device tree.
> + *
> + * @node: device tree node with the domain information
> + * @allocate_if_missing: if DT lacks information about the domain nr,
> + * allocate a new number.
> + *
> + * Returns the associated domain number from DT, or a new domain number
> + * if DT information is missing and @allocate_if_missing is true. If
> + * @allocate_if_missing is false then the last allocated domain number
> + * will be returned.
> + */
> +int of_pci_get_domain_nr(struct device_node *node, bool allocate_if_missing)
> +{
> +	int domain;
> +
> +	domain = atomic_read(&of_domain_nr);
> +	if (domain == -1) {
> +		/* first run, get max defined domain nr in device tree */
> +		domain = of_get_max_pci_domain_nr();
> +		/* then set the start value for allocator to be max + 1 */
> +		atomic_set(&of_domain_nr, domain + 1);

atomic_read followed by atomic_set is not an atomic operation.

As I previously said, I don't like how this function is a mixture of
data retrieval and domian # allocation. I think we need 2 functions.

> +	}
> +	domain = of_alias_get_id(node, "pci-domain");

I still do not like using aliases here. Just put pci-domain or
linux,pci-domain into the PCI node.

I think we should assume all PCI root buses either have a domain
property or they don't and a mixture is an error. I'm not sure if that
simplifies the code or not though.

In the interest of merging, I think you should just do a simple
allocation and add the DT domain handling as a second step. You will
also need to document the DT part.

Rob

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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
  2014-09-18  1:30   ` Liviu Dudau
  (?)
  (?)
@ 2014-09-22  9:32     ` Robert Richter
  -1 siblings, 0 replies; 105+ messages in thread
From: Robert Richter @ 2014-09-22  9:32 UTC (permalink / raw)
  To: Liviu Dudau, Bjorn Helgaas
  Cc: Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	Grant Likely, Sunil Goutham

On 18.09.14 02:30:23, Liviu Dudau wrote:
> +int of_pci_get_host_bridge_resources(struct device_node *dev,
> +			unsigned char busno, unsigned char bus_max,
> +			struct list_head *resources, resource_size_t *io_base)
> +{
> +	struct resource *res;
> +	struct resource *bus_range;
> +	struct of_pci_range range;
> +	struct of_pci_range_parser parser;
> +	char range_type[4];
> +	int err;
> +
> +	if (!io_base)
> +		return -EINVAL;
> +	*io_base = OF_BAD_ADDR;

This breaks for mem-mapped pci host controllers. The patch below fixes
this.

This series was tested with the fix on top for Cavium Thunder.

Tested-by: Robert Richter <rrichter@cavium.com>

-Robert



>From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
From: Robert Richter <rrichter@cavium.com>
Date: Mon, 22 Sep 2014 10:46:01 +0200
Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges

The pci host bridge was not created if io_base was not set when
calling of_pci_get_host_bridge_resources(). This is esp. the case for
mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
parameter io_base is optional now.

Signed-off-by: Robert Richter <rrichter@cavium.com>
---
 drivers/of/of_pci.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index ffdb45ed8682..1f0e7c2505ee 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -182,9 +182,8 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
 	char range_type[4];
 	int err;
 
-	if (!io_base)
-		return -EINVAL;
-	*io_base = OF_BAD_ADDR;
+	if (io_base)
+		*io_base = OF_BAD_ADDR;
 
 	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
 	if (!bus_range)
@@ -242,7 +241,7 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
 			goto parse_failed;
 		}
 
-		if (resource_type(res) == IORESOURCE_IO) {
+		if (io_base && resource_type(res) == IORESOURCE_IO) {
 			if (*io_base != OF_BAD_ADDR)
 				pr_warn("More than one I/O resource converted. CPU offset for old range lost!\n");
 			*io_base = range.cpu_addr;
-- 
2.1.0


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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-22  9:32     ` Robert Richter
  0 siblings, 0 replies; 105+ messages in thread
From: Robert Richter @ 2014-09-22  9:32 UTC (permalink / raw)
  To: Liviu Dudau, Bjorn Helgaas
  Cc: Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	Grant Likely, Sunil Goutham

On 18.09.14 02:30:23, Liviu Dudau wrote:
> +int of_pci_get_host_bridge_resources(struct device_node *dev,
> +			unsigned char busno, unsigned char bus_max,
> +			struct list_head *resources, resource_size_t *io_base)
> +{
> +	struct resource *res;
> +	struct resource *bus_range;
> +	struct of_pci_range range;
> +	struct of_pci_range_parser parser;
> +	char range_type[4];
> +	int err;
> +
> +	if (!io_base)
> +		return -EINVAL;
> +	*io_base = OF_BAD_ADDR;

This breaks for mem-mapped pci host controllers. The patch below fixes
this.

This series was tested with the fix on top for Cavium Thunder.

Tested-by: Robert Richter <rrichter@cavium.com>

-Robert



From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
From: Robert Richter <rrichter@cavium.com>
Date: Mon, 22 Sep 2014 10:46:01 +0200
Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges

The pci host bridge was not created if io_base was not set when
calling of_pci_get_host_bridge_resources(). This is esp. the case for
mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
parameter io_base is optional now.

Signed-off-by: Robert Richter <rrichter@cavium.com>
---
 drivers/of/of_pci.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index ffdb45ed8682..1f0e7c2505ee 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -182,9 +182,8 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
 	char range_type[4];
 	int err;
 
-	if (!io_base)
-		return -EINVAL;
-	*io_base = OF_BAD_ADDR;
+	if (io_base)
+		*io_base = OF_BAD_ADDR;
 
 	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
 	if (!bus_range)
@@ -242,7 +241,7 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
 			goto parse_failed;
 		}
 
-		if (resource_type(res) == IORESOURCE_IO) {
+		if (io_base && resource_type(res) == IORESOURCE_IO) {
 			if (*io_base != OF_BAD_ADDR)
 				pr_warn("More than one I/O resource converted. CPU offset for old range lost!\n");
 			*io_base = range.cpu_addr;
-- 
2.1.0

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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-22  9:32     ` Robert Richter
  0 siblings, 0 replies; 105+ messages in thread
From: Robert Richter @ 2014-09-22  9:32 UTC (permalink / raw)
  To: Liviu Dudau, Bjorn Helgaas
  Cc: Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	Grant Likely, Sunil Goutham

On 18.09.14 02:30:23, Liviu Dudau wrote:
> +int of_pci_get_host_bridge_resources(struct device_node *dev,
> +			unsigned char busno, unsigned char bus_max,
> +			struct list_head *resources, resource_size_t *io_base)
> +{
> +	struct resource *res;
> +	struct resource *bus_range;
> +	struct of_pci_range range;
> +	struct of_pci_range_parser parser;
> +	char range_type[4];
> +	int err;
> +
> +	if (!io_base)
> +		return -EINVAL;
> +	*io_base = OF_BAD_ADDR;

This breaks for mem-mapped pci host controllers. The patch below fixes
this.

This series was tested with the fix on top for Cavium Thunder.

Tested-by: Robert Richter <rrichter@cavium.com>

-Robert

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

* [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-22  9:32     ` Robert Richter
  0 siblings, 0 replies; 105+ messages in thread
From: Robert Richter @ 2014-09-22  9:32 UTC (permalink / raw)
  To: linux-arm-kernel

On 18.09.14 02:30:23, Liviu Dudau wrote:
> +int of_pci_get_host_bridge_resources(struct device_node *dev,
> +			unsigned char busno, unsigned char bus_max,
> +			struct list_head *resources, resource_size_t *io_base)
> +{
> +	struct resource *res;
> +	struct resource *bus_range;
> +	struct of_pci_range range;
> +	struct of_pci_range_parser parser;
> +	char range_type[4];
> +	int err;
> +
> +	if (!io_base)
> +		return -EINVAL;
> +	*io_base = OF_BAD_ADDR;

This breaks for mem-mapped pci host controllers. The patch below fixes
this.

This series was tested with the fix on top for Cavium Thunder.

Tested-by: Robert Richter <rrichter@cavium.com>

-Robert



>From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
From: Robert Richter <rrichter@cavium.com>
Date: Mon, 22 Sep 2014 10:46:01 +0200
Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges

The pci host bridge was not created if io_base was not set when
calling of_pci_get_host_bridge_resources(). This is esp. the case for
mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
parameter io_base is optional now.

Signed-off-by: Robert Richter <rrichter@cavium.com>
---
 drivers/of/of_pci.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index ffdb45ed8682..1f0e7c2505ee 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -182,9 +182,8 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
 	char range_type[4];
 	int err;
 
-	if (!io_base)
-		return -EINVAL;
-	*io_base = OF_BAD_ADDR;
+	if (io_base)
+		*io_base = OF_BAD_ADDR;
 
 	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
 	if (!bus_range)
@@ -242,7 +241,7 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
 			goto parse_failed;
 		}
 
-		if (resource_type(res) == IORESOURCE_IO) {
+		if (io_base && resource_type(res) == IORESOURCE_IO) {
 			if (*io_base != OF_BAD_ADDR)
 				pr_warn("More than one I/O resource converted. CPU offset for old range lost!\n");
 			*io_base = range.cpu_addr;
-- 
2.1.0

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

* Re: [PATCH v11 07/10] OF: Introduce helper function for getting PCI domain_nr
  2014-09-19 21:03     ` Bjorn Helgaas
@ 2014-09-22 11:05       ` Liviu Dudau
  -1 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-22 11:05 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	grant.likely

On Fri, Sep 19, 2014 at 10:03:13PM +0100, Bjorn Helgaas wrote:
> On Thu, Sep 18, 2014 at 02:30:22AM +0100, Liviu Dudau wrote:
> > Add of_pci_get_domain_nr() to retrieve the PCI domain number
> > of a given device from DT. If the information is not present,
> > the function can be requested to allocate a new domain number.
> 
> Is of_pci_get_domain_nr() used somewhere?  If the use is in some future
> series, please mention it explicitly.  I'm just trying to avoid merging
> unused code.

It is used in the arm64 specific patch that I have dropped out of my
pull request. After discussions with Catalin I will add the patch back
into the tree that you've pulled from as he is OK with your tree carrying
the whole package.

I need to ask for some guidance here: for addressing some of your comments
and Rob's I can add more patches in my v11 branch and you can pull them
when you think they are ready. But one of your comments was requesting
splitting a patch into two blocks - one that moves of_pci_range_to_resource()
into drivers/of/address.c and one that fixes it's behaviour - and I don't
know how you would like that handled. Should I revert the original patch
and add the new ones, or should I rebase the whole series into a different
branch that you can pull from?

Best regards,
Liviu

> 
> Bjorn
> 

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


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

* [PATCH v11 07/10] OF: Introduce helper function for getting PCI domain_nr
@ 2014-09-22 11:05       ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-22 11:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Sep 19, 2014 at 10:03:13PM +0100, Bjorn Helgaas wrote:
> On Thu, Sep 18, 2014 at 02:30:22AM +0100, Liviu Dudau wrote:
> > Add of_pci_get_domain_nr() to retrieve the PCI domain number
> > of a given device from DT. If the information is not present,
> > the function can be requested to allocate a new domain number.
> 
> Is of_pci_get_domain_nr() used somewhere?  If the use is in some future
> series, please mention it explicitly.  I'm just trying to avoid merging
> unused code.

It is used in the arm64 specific patch that I have dropped out of my
pull request. After discussions with Catalin I will add the patch back
into the tree that you've pulled from as he is OK with your tree carrying
the whole package.

I need to ask for some guidance here: for addressing some of your comments
and Rob's I can add more patches in my v11 branch and you can pull them
when you think they are ready. But one of your comments was requesting
splitting a patch into two blocks - one that moves of_pci_range_to_resource()
into drivers/of/address.c and one that fixes it's behaviour - and I don't
know how you would like that handled. Should I revert the original patch
and add the new ones, or should I rebase the whole series into a different
branch that you can pull from?

Best regards,
Liviu

> 
> Bjorn
> 

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

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

* Re: [PATCH v11 00/10] Support for creating generic PCI host bridges from DT
  2014-09-19 21:59   ` Bjorn Helgaas
@ 2014-09-22 11:35     ` Liviu Dudau
  -1 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-22 11:35 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML

On Fri, Sep 19, 2014 at 10:59:05PM +0100, Bjorn Helgaas wrote:
> On Thu, Sep 18, 2014 at 02:30:15AM +0100, Liviu Dudau wrote:
> > This is my version 11 of the attempt at adding support for generic PCI host
> > bridge controllers that make use of device tree information to
> > configure themselves. It contains minor cleanups compared with v10 to address
> > the existing comments.
> > ...
> > Catalin Marinas (1):
> >   PCI: Introduce generic domain handling for PCI busses.
> > 
> > Liviu Dudau (9):
> >   Fix ioport_map() for !CONFIG_GENERIC_IOMAP cases.
> >   PCI: Introduce helper functions to deal with PCI I/O ranges.
> >   ARM: Define PCI_IOBASE as the base of virtual PCI IO space.
> >   PCI: OF: Fix the conversion of IO ranges into IO resources.
> >   PCI: Create pci_host_bridge before its associated bus in
> >     pci_create_root_bus.
> >   OF: Introduce helper function for getting PCI domain_nr
> >   OF: PCI: Add support for parsing PCI host bridge resources from DT
> >   PCI: Assign unassigned bus resources in pci_scan_root_bus()
> >   PCI: Introduce pci_remap_iospace() for remapping PCI I/O bus resources
> >     into CPU space
> > 
> >  arch/arm/include/asm/io.h         |   1 +
> >  arch/arm/mach-integrator/pci_v3.c |  23 +++---
> >  drivers/of/address.c              | 146 ++++++++++++++++++++++++++++++++
> >  drivers/of/of_pci.c               | 170 ++++++++++++++++++++++++++++++++++++++
> >  drivers/pci/host/pci-tegra.c      |  10 ++-
> >  drivers/pci/host/pcie-rcar.c      |  21 +++--
> >  drivers/pci/pci.c                 |  33 ++++++++
> >  drivers/pci/probe.c               |  46 +++++++----
> >  include/asm-generic/io.h          |   2 +-
> >  include/asm-generic/pgtable.h     |   4 +
> >  include/linux/of_address.h        |  15 +---
> >  include/linux/of_pci.h            |  18 ++++
> >  include/linux/pci.h               |  24 ++++++
> >  13 files changed, 463 insertions(+), 50 deletions(-)
> 
> I put this on a pci/liviu-generic-v11 branch.  I mentioned a couple things
> in response to the individual patches, so I'm hoping you can send me
> incremental patches to address them.  Then I'll update this branch, rename
> it, and get it into linux-next.

Thanks a lot for that!

As I've mentioned in the other email, I can send incremental patches for most
of the comments (and Acks?). Don't know how to handle the split of 
"[PATH v11 4/10] PCI: OF: Fix the conversion of IO ranges into IO resources."
that you are asking for.

Best regards,
Liviu

> 
> Bjorn
> 

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


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

* [PATCH v11 00/10] Support for creating generic PCI host bridges from DT
@ 2014-09-22 11:35     ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-22 11:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Sep 19, 2014 at 10:59:05PM +0100, Bjorn Helgaas wrote:
> On Thu, Sep 18, 2014 at 02:30:15AM +0100, Liviu Dudau wrote:
> > This is my version 11 of the attempt at adding support for generic PCI host
> > bridge controllers that make use of device tree information to
> > configure themselves. It contains minor cleanups compared with v10 to address
> > the existing comments.
> > ...
> > Catalin Marinas (1):
> >   PCI: Introduce generic domain handling for PCI busses.
> > 
> > Liviu Dudau (9):
> >   Fix ioport_map() for !CONFIG_GENERIC_IOMAP cases.
> >   PCI: Introduce helper functions to deal with PCI I/O ranges.
> >   ARM: Define PCI_IOBASE as the base of virtual PCI IO space.
> >   PCI: OF: Fix the conversion of IO ranges into IO resources.
> >   PCI: Create pci_host_bridge before its associated bus in
> >     pci_create_root_bus.
> >   OF: Introduce helper function for getting PCI domain_nr
> >   OF: PCI: Add support for parsing PCI host bridge resources from DT
> >   PCI: Assign unassigned bus resources in pci_scan_root_bus()
> >   PCI: Introduce pci_remap_iospace() for remapping PCI I/O bus resources
> >     into CPU space
> > 
> >  arch/arm/include/asm/io.h         |   1 +
> >  arch/arm/mach-integrator/pci_v3.c |  23 +++---
> >  drivers/of/address.c              | 146 ++++++++++++++++++++++++++++++++
> >  drivers/of/of_pci.c               | 170 ++++++++++++++++++++++++++++++++++++++
> >  drivers/pci/host/pci-tegra.c      |  10 ++-
> >  drivers/pci/host/pcie-rcar.c      |  21 +++--
> >  drivers/pci/pci.c                 |  33 ++++++++
> >  drivers/pci/probe.c               |  46 +++++++----
> >  include/asm-generic/io.h          |   2 +-
> >  include/asm-generic/pgtable.h     |   4 +
> >  include/linux/of_address.h        |  15 +---
> >  include/linux/of_pci.h            |  18 ++++
> >  include/linux/pci.h               |  24 ++++++
> >  13 files changed, 463 insertions(+), 50 deletions(-)
> 
> I put this on a pci/liviu-generic-v11 branch.  I mentioned a couple things
> in response to the individual patches, so I'm hoping you can send me
> incremental patches to address them.  Then I'll update this branch, rename
> it, and get it into linux-next.

Thanks a lot for that!

As I've mentioned in the other email, I can send incremental patches for most
of the comments (and Acks?). Don't know how to handle the split of 
"[PATH v11 4/10] PCI: OF: Fix the conversion of IO ranges into IO resources."
that you are asking for.

Best regards,
Liviu

> 
> Bjorn
> 

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

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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
  2014-09-22  9:32     ` Robert Richter
  (?)
@ 2014-09-22 11:43       ` Liviu Dudau
  -1 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-22 11:43 UTC (permalink / raw)
  To: Robert Richter
  Cc: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	grant.likely, Sunil Goutham

On Mon, Sep 22, 2014 at 10:32:28AM +0100, Robert Richter wrote:
> On 18.09.14 02:30:23, Liviu Dudau wrote:
> > +int of_pci_get_host_bridge_resources(struct device_node *dev,
> > +			unsigned char busno, unsigned char bus_max,
> > +			struct list_head *resources, resource_size_t *io_base)
> > +{
> > +	struct resource *res;
> > +	struct resource *bus_range;
> > +	struct of_pci_range range;
> > +	struct of_pci_range_parser parser;
> > +	char range_type[4];
> > +	int err;
> > +
> > +	if (!io_base)
> > +		return -EINVAL;
> > +	*io_base = OF_BAD_ADDR;
> 

Hi Robert,

> This breaks for mem-mapped pci host controllers. The patch below fixes
> this.

I think you mean PCI host controller that have only memory mapped ranges,
am I right? Initially I've read your reply as to mean that the host
controller is accessed through some memory mapped area, which I believe is
the case for all host controllers.

> 
> This series was tested with the fix on top for Cavium Thunder.
> 
> Tested-by: Robert Richter <rrichter@cavium.com>

Thanks for that!

> 
> -Robert
> 
> 
> 
> From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
> From: Robert Richter <rrichter@cavium.com>
> Date: Mon, 22 Sep 2014 10:46:01 +0200
> Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
> 
> The pci host bridge was not created if io_base was not set when
> calling of_pci_get_host_bridge_resources(). This is esp. the case for
> mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
> parameter io_base is optional now.

I think the message is misleading. What you want to do is make io_base
optional for the case where the PCI host bridge only expects to have only
IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.

As I'm going to touch this area again to address a comment from Bjorn,
do you mind if I roll this patch into mine with your Signed-off-by and
the mention that you have made io_base optional?

Best regards,
Liviu

> 
> Signed-off-by: Robert Richter <rrichter@cavium.com>
> ---
>  drivers/of/of_pci.c | 7 +++----
>  1 file changed, 3 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
> index ffdb45ed8682..1f0e7c2505ee 100644
> --- a/drivers/of/of_pci.c
> +++ b/drivers/of/of_pci.c
> @@ -182,9 +182,8 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
>  	char range_type[4];
>  	int err;
>  
> -	if (!io_base)
> -		return -EINVAL;
> -	*io_base = OF_BAD_ADDR;
> +	if (io_base)
> +		*io_base = OF_BAD_ADDR;
>  
>  	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
>  	if (!bus_range)
> @@ -242,7 +241,7 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
>  			goto parse_failed;
>  		}
>  
> -		if (resource_type(res) == IORESOURCE_IO) {
> +		if (io_base && resource_type(res) == IORESOURCE_IO) {
>  			if (*io_base != OF_BAD_ADDR)
>  				pr_warn("More than one I/O resource converted. CPU offset for old range lost!\n");
>  			*io_base = range.cpu_addr;
> -- 
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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


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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-22 11:43       ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-22 11:43 UTC (permalink / raw)
  To: Robert Richter
  Cc: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	grant.likely

On Mon, Sep 22, 2014 at 10:32:28AM +0100, Robert Richter wrote:
> On 18.09.14 02:30:23, Liviu Dudau wrote:
> > +int of_pci_get_host_bridge_resources(struct device_node *dev,
> > +			unsigned char busno, unsigned char bus_max,
> > +			struct list_head *resources, resource_size_t *io_base)
> > +{
> > +	struct resource *res;
> > +	struct resource *bus_range;
> > +	struct of_pci_range range;
> > +	struct of_pci_range_parser parser;
> > +	char range_type[4];
> > +	int err;
> > +
> > +	if (!io_base)
> > +		return -EINVAL;
> > +	*io_base = OF_BAD_ADDR;
> 

Hi Robert,

> This breaks for mem-mapped pci host controllers. The patch below fixes
> this.

I think you mean PCI host controller that have only memory mapped ranges,
am I right? Initially I've read your reply as to mean that the host
controller is accessed through some memory mapped area, which I believe is
the case for all host controllers.

> 
> This series was tested with the fix on top for Cavium Thunder.
> 
> Tested-by: Robert Richter <rrichter@cavium.com>

Thanks for that!

> 
> -Robert
> 
> 
> 
> From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
> From: Robert Richter <rrichter@cavium.com>
> Date: Mon, 22 Sep 2014 10:46:01 +0200
> Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
> 
> The pci host bridge was not created if io_base was not set when
> calling of_pci_get_host_bridge_resources(). This is esp. the case for
> mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
> parameter io_base is optional now.

I think the message is misleading. What you want to do is make io_base
optional for the case where the PCI host bridge only expects to have only
IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.

As I'm going to touch this area again to address a comment from Bjorn,
do you mind if I roll this patch into mine with your Signed-off-by and
the mention that you have made io_base optional?

Best regards,
Liviu

> 
> Signed-off-by: Robert Richter <rrichter@cavium.com>
> ---
>  drivers/of/of_pci.c | 7 +++----
>  1 file changed, 3 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
> index ffdb45ed8682..1f0e7c2505ee 100644
> --- a/drivers/of/of_pci.c
> +++ b/drivers/of/of_pci.c
> @@ -182,9 +182,8 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
>  	char range_type[4];
>  	int err;
>  
> -	if (!io_base)
> -		return -EINVAL;
> -	*io_base = OF_BAD_ADDR;
> +	if (io_base)
> +		*io_base = OF_BAD_ADDR;
>  
>  	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
>  	if (!bus_range)
> @@ -242,7 +241,7 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
>  			goto parse_failed;
>  		}
>  
> -		if (resource_type(res) == IORESOURCE_IO) {
> +		if (io_base && resource_type(res) == IORESOURCE_IO) {
>  			if (*io_base != OF_BAD_ADDR)
>  				pr_warn("More than one I/O resource converted. CPU offset for old range lost!\n");
>  			*io_base = range.cpu_addr;
> -- 
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

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

* [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-22 11:43       ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-22 11:43 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Sep 22, 2014 at 10:32:28AM +0100, Robert Richter wrote:
> On 18.09.14 02:30:23, Liviu Dudau wrote:
> > +int of_pci_get_host_bridge_resources(struct device_node *dev,
> > +			unsigned char busno, unsigned char bus_max,
> > +			struct list_head *resources, resource_size_t *io_base)
> > +{
> > +	struct resource *res;
> > +	struct resource *bus_range;
> > +	struct of_pci_range range;
> > +	struct of_pci_range_parser parser;
> > +	char range_type[4];
> > +	int err;
> > +
> > +	if (!io_base)
> > +		return -EINVAL;
> > +	*io_base = OF_BAD_ADDR;
> 

Hi Robert,

> This breaks for mem-mapped pci host controllers. The patch below fixes
> this.

I think you mean PCI host controller that have only memory mapped ranges,
am I right? Initially I've read your reply as to mean that the host
controller is accessed through some memory mapped area, which I believe is
the case for all host controllers.

> 
> This series was tested with the fix on top for Cavium Thunder.
> 
> Tested-by: Robert Richter <rrichter@cavium.com>

Thanks for that!

> 
> -Robert
> 
> 
> 
> From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
> From: Robert Richter <rrichter@cavium.com>
> Date: Mon, 22 Sep 2014 10:46:01 +0200
> Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
> 
> The pci host bridge was not created if io_base was not set when
> calling of_pci_get_host_bridge_resources(). This is esp. the case for
> mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
> parameter io_base is optional now.

I think the message is misleading. What you want to do is make io_base
optional for the case where the PCI host bridge only expects to have only
IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.

As I'm going to touch this area again to address a comment from Bjorn,
do you mind if I roll this patch into mine with your Signed-off-by and
the mention that you have made io_base optional?

Best regards,
Liviu

> 
> Signed-off-by: Robert Richter <rrichter@cavium.com>
> ---
>  drivers/of/of_pci.c | 7 +++----
>  1 file changed, 3 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
> index ffdb45ed8682..1f0e7c2505ee 100644
> --- a/drivers/of/of_pci.c
> +++ b/drivers/of/of_pci.c
> @@ -182,9 +182,8 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
>  	char range_type[4];
>  	int err;
>  
> -	if (!io_base)
> -		return -EINVAL;
> -	*io_base = OF_BAD_ADDR;
> +	if (io_base)
> +		*io_base = OF_BAD_ADDR;
>  
>  	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
>  	if (!bus_range)
> @@ -242,7 +241,7 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
>  			goto parse_failed;
>  		}
>  
> -		if (resource_type(res) == IORESOURCE_IO) {
> +		if (io_base && resource_type(res) == IORESOURCE_IO) {
>  			if (*io_base != OF_BAD_ADDR)
>  				pr_warn("More than one I/O resource converted. CPU offset for old range lost!\n");
>  			*io_base = range.cpu_addr;
> -- 
> 2.1.0
> 
> --
> 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
> 

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

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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-22 12:15         ` Robert Richter
  0 siblings, 0 replies; 105+ messages in thread
From: Robert Richter @ 2014-09-22 12:15 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	grant.likely, Sunil Goutham

On 22.09.14 12:43:17, Liviu Dudau wrote:
> On Mon, Sep 22, 2014 at 10:32:28AM +0100, Robert Richter wrote:
> > On 18.09.14 02:30:23, Liviu Dudau wrote:
> > > +int of_pci_get_host_bridge_resources(struct device_node *dev,
> > > +			unsigned char busno, unsigned char bus_max,
> > > +			struct list_head *resources, resource_size_t *io_base)
> > > +{
> > > +	struct resource *res;
> > > +	struct resource *bus_range;
> > > +	struct of_pci_range range;
> > > +	struct of_pci_range_parser parser;
> > > +	char range_type[4];
> > > +	int err;
> > > +
> > > +	if (!io_base)
> > > +		return -EINVAL;
> > > +	*io_base = OF_BAD_ADDR;
> > 
> 
> Hi Robert,
> 
> > This breaks for mem-mapped pci host controllers. The patch below fixes
> > this.
> 
> I think you mean PCI host controller that have only memory mapped ranges,
> am I right? Initially I've read your reply as to mean that the host
> controller is accessed through some memory mapped area, which I believe is
> the case for all host controllers.

Right, that's meant here. Sorry for the misleading comment.

> 
> > 
> > This series was tested with the fix on top for Cavium Thunder.
> > 
> > Tested-by: Robert Richter <rrichter@cavium.com>
> 
> Thanks for that!
> 
> > 
> > -Robert
> > 
> > 
> > 
> > From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
> > From: Robert Richter <rrichter@cavium.com>
> > Date: Mon, 22 Sep 2014 10:46:01 +0200
> > Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
> > 
> > The pci host bridge was not created if io_base was not set when
> > calling of_pci_get_host_bridge_resources(). This is esp. the case for
> > mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
> > parameter io_base is optional now.
> 
> I think the message is misleading. What you want to do is make io_base
> optional for the case where the PCI host bridge only expects to have only
> IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.
> 
> As I'm going to touch this area again to address a comment from Bjorn,
> do you mind if I roll this patch into mine with your Signed-off-by and
> the mention that you have made io_base optional?

Sure, fine with me.

Thanks,

-Robert


> 
> Best regards,
> Liviu
> 
> > 
> > Signed-off-by: Robert Richter <rrichter@cavium.com>
> > ---
> >  drivers/of/of_pci.c | 7 +++----
> >  1 file changed, 3 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
> > index ffdb45ed8682..1f0e7c2505ee 100644
> > --- a/drivers/of/of_pci.c
> > +++ b/drivers/of/of_pci.c
> > @@ -182,9 +182,8 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
> >  	char range_type[4];
> >  	int err;
> >  
> > -	if (!io_base)
> > -		return -EINVAL;
> > -	*io_base = OF_BAD_ADDR;
> > +	if (io_base)
> > +		*io_base = OF_BAD_ADDR;
> >  
> >  	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
> >  	if (!bus_range)
> > @@ -242,7 +241,7 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
> >  			goto parse_failed;
> >  		}
> >  
> > -		if (resource_type(res) == IORESOURCE_IO) {
> > +		if (io_base && resource_type(res) == IORESOURCE_IO) {
> >  			if (*io_base != OF_BAD_ADDR)
> >  				pr_warn("More than one I/O resource converted. CPU offset for old range lost!\n");
> >  			*io_base = range.cpu_addr;
> > -- 
> > 2.1.0
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > 
> 
> -- 
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ¯\_(ツ)_/¯
> 

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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-22 12:15         ` Robert Richter
  0 siblings, 0 replies; 105+ messages in thread
From: Robert Richter @ 2014-09-22 12:15 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A

On 22.09.14 12:43:17, Liviu Dudau wrote:
> On Mon, Sep 22, 2014 at 10:32:28AM +0100, Robert Richter wrote:
> > On 18.09.14 02:30:23, Liviu Dudau wrote:
> > > +int of_pci_get_host_bridge_resources(struct device_node *dev,
> > > +			unsigned char busno, unsigned char bus_max,
> > > +			struct list_head *resources, resource_size_t *io_base)
> > > +{
> > > +	struct resource *res;
> > > +	struct resource *bus_range;
> > > +	struct of_pci_range range;
> > > +	struct of_pci_range_parser parser;
> > > +	char range_type[4];
> > > +	int err;
> > > +
> > > +	if (!io_base)
> > > +		return -EINVAL;
> > > +	*io_base = OF_BAD_ADDR;
> > 
> 
> Hi Robert,
> 
> > This breaks for mem-mapped pci host controllers. The patch below fixes
> > this.
> 
> I think you mean PCI host controller that have only memory mapped ranges,
> am I right? Initially I've read your reply as to mean that the host
> controller is accessed through some memory mapped area, which I believe is
> the case for all host controllers.

Right, that's meant here. Sorry for the misleading comment.

> 
> > 
> > This series was tested with the fix on top for Cavium Thunder.
> > 
> > Tested-by: Robert Richter <rrichter-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>
> 
> Thanks for that!
> 
> > 
> > -Robert
> > 
> > 
> > 
> > From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
> > From: Robert Richter <rrichter-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>
> > Date: Mon, 22 Sep 2014 10:46:01 +0200
> > Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
> > 
> > The pci host bridge was not created if io_base was not set when
> > calling of_pci_get_host_bridge_resources(). This is esp. the case for
> > mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
> > parameter io_base is optional now.
> 
> I think the message is misleading. What you want to do is make io_base
> optional for the case where the PCI host bridge only expects to have only
> IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.
> 
> As I'm going to touch this area again to address a comment from Bjorn,
> do you mind if I roll this patch into mine with your Signed-off-by and
> the mention that you have made io_base optional?

Sure, fine with me.

Thanks,

-Robert


> 
> Best regards,
> Liviu
> 
> > 
> > Signed-off-by: Robert Richter <rrichter-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>
> > ---
> >  drivers/of/of_pci.c | 7 +++----
> >  1 file changed, 3 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
> > index ffdb45ed8682..1f0e7c2505ee 100644
> > --- a/drivers/of/of_pci.c
> > +++ b/drivers/of/of_pci.c
> > @@ -182,9 +182,8 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
> >  	char range_type[4];
> >  	int err;
> >  
> > -	if (!io_base)
> > -		return -EINVAL;
> > -	*io_base = OF_BAD_ADDR;
> > +	if (io_base)
> > +		*io_base = OF_BAD_ADDR;
> >  
> >  	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
> >  	if (!bus_range)
> > @@ -242,7 +241,7 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
> >  			goto parse_failed;
> >  		}
> >  
> > -		if (resource_type(res) == IORESOURCE_IO) {
> > +		if (io_base && resource_type(res) == IORESOURCE_IO) {
> >  			if (*io_base != OF_BAD_ADDR)
> >  				pr_warn("More than one I/O resource converted. CPU offset for old range lost!\n");
> >  			*io_base = range.cpu_addr;
> > -- 
> > 2.1.0
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> > the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > 
> 
> -- 
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ¯\_(ツ)_/¯
> 
--
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] 105+ messages in thread

* [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-22 12:15         ` Robert Richter
  0 siblings, 0 replies; 105+ messages in thread
From: Robert Richter @ 2014-09-22 12:15 UTC (permalink / raw)
  To: linux-arm-kernel

On 22.09.14 12:43:17, Liviu Dudau wrote:
> On Mon, Sep 22, 2014 at 10:32:28AM +0100, Robert Richter wrote:
> > On 18.09.14 02:30:23, Liviu Dudau wrote:
> > > +int of_pci_get_host_bridge_resources(struct device_node *dev,
> > > +			unsigned char busno, unsigned char bus_max,
> > > +			struct list_head *resources, resource_size_t *io_base)
> > > +{
> > > +	struct resource *res;
> > > +	struct resource *bus_range;
> > > +	struct of_pci_range range;
> > > +	struct of_pci_range_parser parser;
> > > +	char range_type[4];
> > > +	int err;
> > > +
> > > +	if (!io_base)
> > > +		return -EINVAL;
> > > +	*io_base = OF_BAD_ADDR;
> > 
> 
> Hi Robert,
> 
> > This breaks for mem-mapped pci host controllers. The patch below fixes
> > this.
> 
> I think you mean PCI host controller that have only memory mapped ranges,
> am I right? Initially I've read your reply as to mean that the host
> controller is accessed through some memory mapped area, which I believe is
> the case for all host controllers.

Right, that's meant here. Sorry for the misleading comment.

> 
> > 
> > This series was tested with the fix on top for Cavium Thunder.
> > 
> > Tested-by: Robert Richter <rrichter@cavium.com>
> 
> Thanks for that!
> 
> > 
> > -Robert
> > 
> > 
> > 
> > From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
> > From: Robert Richter <rrichter@cavium.com>
> > Date: Mon, 22 Sep 2014 10:46:01 +0200
> > Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
> > 
> > The pci host bridge was not created if io_base was not set when
> > calling of_pci_get_host_bridge_resources(). This is esp. the case for
> > mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
> > parameter io_base is optional now.
> 
> I think the message is misleading. What you want to do is make io_base
> optional for the case where the PCI host bridge only expects to have only
> IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.
> 
> As I'm going to touch this area again to address a comment from Bjorn,
> do you mind if I roll this patch into mine with your Signed-off-by and
> the mention that you have made io_base optional?

Sure, fine with me.

Thanks,

-Robert


> 
> Best regards,
> Liviu
> 
> > 
> > Signed-off-by: Robert Richter <rrichter@cavium.com>
> > ---
> >  drivers/of/of_pci.c | 7 +++----
> >  1 file changed, 3 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
> > index ffdb45ed8682..1f0e7c2505ee 100644
> > --- a/drivers/of/of_pci.c
> > +++ b/drivers/of/of_pci.c
> > @@ -182,9 +182,8 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
> >  	char range_type[4];
> >  	int err;
> >  
> > -	if (!io_base)
> > -		return -EINVAL;
> > -	*io_base = OF_BAD_ADDR;
> > +	if (io_base)
> > +		*io_base = OF_BAD_ADDR;
> >  
> >  	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
> >  	if (!bus_range)
> > @@ -242,7 +241,7 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
> >  			goto parse_failed;
> >  		}
> >  
> > -		if (resource_type(res) == IORESOURCE_IO) {
> > +		if (io_base && resource_type(res) == IORESOURCE_IO) {
> >  			if (*io_base != OF_BAD_ADDR)
> >  				pr_warn("More than one I/O resource converted. CPU offset for old range lost!\n");
> >  			*io_base = range.cpu_addr;
> > -- 
> > 2.1.0
> > 
> > --
> > 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
> > 
> 
> -- 
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ?\_(?)_/?
> 

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

* Re: [PATCH v11 07/10] OF: Introduce helper function for getting PCI domain_nr
  2014-09-20  2:24     ` Arnd Bergmann
@ 2014-09-22 15:20       ` Liviu Dudau
  -1 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-22 15:20 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Bjorn Helgaas, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	grant.likely

On Sat, Sep 20, 2014 at 03:24:20AM +0100, Arnd Bergmann wrote:
> On Thursday 18 September 2014, Liviu Dudau wrote:
> > 
> > Add of_pci_get_domain_nr() to retrieve the PCI domain number
> > of a given device from DT. If the information is not present,
> > the function can be requested to allocate a new domain number.
> > 
> > Cc: Bjorn Helgaas <bhelgaas@google.com>
> > Cc: Arnd Bergmann <arnd@arndb.de>
> > Cc: Grant Likely <grant.likely@linaro.org>
> > Cc: Rob Herring <robh+dt@kernel.org>
> > Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
> > Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
> 
> This is more elaborate than I remember it, and while the simpler
> version (which potentially resulted in a conflict for inconsistent
> DTs) was fine, this one also seems ok.
> 
> Acked-by: Arnd Bergmann <arnd@arndb.de>

Thanks Arnd!

Best regards,
Liviu

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

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


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

* [PATCH v11 07/10] OF: Introduce helper function for getting PCI domain_nr
@ 2014-09-22 15:20       ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-22 15:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Sep 20, 2014 at 03:24:20AM +0100, Arnd Bergmann wrote:
> On Thursday 18 September 2014, Liviu Dudau wrote:
> > 
> > Add of_pci_get_domain_nr() to retrieve the PCI domain number
> > of a given device from DT. If the information is not present,
> > the function can be requested to allocate a new domain number.
> > 
> > Cc: Bjorn Helgaas <bhelgaas@google.com>
> > Cc: Arnd Bergmann <arnd@arndb.de>
> > Cc: Grant Likely <grant.likely@linaro.org>
> > Cc: Rob Herring <robh+dt@kernel.org>
> > Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
> > Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
> 
> This is more elaborate than I remember it, and while the simpler
> version (which potentially resulted in a conflict for inconsistent
> DTs) was fine, this one also seems ok.
> 
> Acked-by: Arnd Bergmann <arnd@arndb.de>

Thanks Arnd!

Best regards,
Liviu

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

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

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

* Re: [PATCH v11 07/10] OF: Introduce helper function for getting PCI domain_nr
  2014-09-22 11:05       ` Liviu Dudau
@ 2014-09-22 15:25         ` Bjorn Helgaas
  -1 siblings, 0 replies; 105+ messages in thread
From: Bjorn Helgaas @ 2014-09-22 15:25 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	grant.likely

On Mon, Sep 22, 2014 at 5:05 AM, Liviu Dudau <Liviu.Dudau@arm.com> wrote:
> On Fri, Sep 19, 2014 at 10:03:13PM +0100, Bjorn Helgaas wrote:
>> On Thu, Sep 18, 2014 at 02:30:22AM +0100, Liviu Dudau wrote:
>> > Add of_pci_get_domain_nr() to retrieve the PCI domain number
>> > of a given device from DT. If the information is not present,
>> > the function can be requested to allocate a new domain number.
>>
>> Is of_pci_get_domain_nr() used somewhere?  If the use is in some future
>> series, please mention it explicitly.  I'm just trying to avoid merging
>> unused code.
>
> It is used in the arm64 specific patch that I have dropped out of my
> pull request. After discussions with Catalin I will add the patch back
> into the tree that you've pulled from as he is OK with your tree carrying
> the whole package.
>
> I need to ask for some guidance here: for addressing some of your comments
> and Rob's I can add more patches in my v11 branch and you can pull them
> when you think they are ready. But one of your comments was requesting
> splitting a patch into two blocks - one that moves of_pci_range_to_resource()
> into drivers/of/address.c and one that fixes it's behaviour - and I don't
> know how you would like that handled. Should I revert the original patch
> and add the new ones, or should I rebase the whole series into a different
> branch that you can pull from?

I guess the easiest thing is probably just to send a v12 series.  I
was hoping we were close enough for me to just hand-integrate minor
tweaks into my branch, but I think that will just create more
confusion.

Bjorn

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

* [PATCH v11 07/10] OF: Introduce helper function for getting PCI domain_nr
@ 2014-09-22 15:25         ` Bjorn Helgaas
  0 siblings, 0 replies; 105+ messages in thread
From: Bjorn Helgaas @ 2014-09-22 15:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Sep 22, 2014 at 5:05 AM, Liviu Dudau <Liviu.Dudau@arm.com> wrote:
> On Fri, Sep 19, 2014 at 10:03:13PM +0100, Bjorn Helgaas wrote:
>> On Thu, Sep 18, 2014 at 02:30:22AM +0100, Liviu Dudau wrote:
>> > Add of_pci_get_domain_nr() to retrieve the PCI domain number
>> > of a given device from DT. If the information is not present,
>> > the function can be requested to allocate a new domain number.
>>
>> Is of_pci_get_domain_nr() used somewhere?  If the use is in some future
>> series, please mention it explicitly.  I'm just trying to avoid merging
>> unused code.
>
> It is used in the arm64 specific patch that I have dropped out of my
> pull request. After discussions with Catalin I will add the patch back
> into the tree that you've pulled from as he is OK with your tree carrying
> the whole package.
>
> I need to ask for some guidance here: for addressing some of your comments
> and Rob's I can add more patches in my v11 branch and you can pull them
> when you think they are ready. But one of your comments was requesting
> splitting a patch into two blocks - one that moves of_pci_range_to_resource()
> into drivers/of/address.c and one that fixes it's behaviour - and I don't
> know how you would like that handled. Should I revert the original patch
> and add the new ones, or should I rebase the whole series into a different
> branch that you can pull from?

I guess the easiest thing is probably just to send a v12 series.  I
was hoping we were close enough for me to just hand-integrate minor
tweaks into my branch, but I think that will just create more
confusion.

Bjorn

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

* Re: [PATCH v11 10/10] PCI: Introduce pci_remap_iospace() for remapping PCI I/O bus resources into CPU space
  2014-09-20  2:20       ` Arnd Bergmann
@ 2014-09-22 15:29         ` Robert Richter
  -1 siblings, 0 replies; 105+ messages in thread
From: Robert Richter @ 2014-09-22 15:29 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Bjorn Helgaas, Liviu Dudau, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML

On 20.09.14 04:20:31, Arnd Bergmann wrote:
> On Friday 19 September 2014, Bjorn Helgaas wrote:
> > On Thu, Sep 18, 2014 at 02:30:25AM +0100, Liviu Dudau wrote:
> 
> > PCI_IOBASE is a virtual address.  So PCI_IOBASE + res->start is also a
> > virtual address (only for IORESOURCE_IO).
> > 
> > Since res->start is normally a *physical* address, I think it would be less
> > confusing to do something like this:
> > 
> >     vaddr = PCI_IOBASE + res->start;
> >     ioremap_page_range(vaddr, vaddr + resource_size(res), ...);
> > 
> > so we have a hint that the first two ioremap_page_range() parameters are
> > virtual addresses.  It's also confusing that it uses "unsigned long" for
> > the virtual addresses, when we usually use "void *".  But that's out of
> > scope for this patch.
> 
> Good idea. I think it will have to be (unsigned long)PCI_IOBASE above then,
> since ioremap_page_range takes a 'unsigned long' virtual address and PCI_IOBASE
> should really remain an __iomem pointer.

Right, I see this warning here:

drivers/pci/pci.c: In function ‘pci_remap_iospace’:
drivers/pci/pci.c:2728:8: warning: assignment makes integer from pointer without a cast [enabled by default]

-Robert

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

* [PATCH v11 10/10] PCI: Introduce pci_remap_iospace() for remapping PCI I/O bus resources into CPU space
@ 2014-09-22 15:29         ` Robert Richter
  0 siblings, 0 replies; 105+ messages in thread
From: Robert Richter @ 2014-09-22 15:29 UTC (permalink / raw)
  To: linux-arm-kernel

On 20.09.14 04:20:31, Arnd Bergmann wrote:
> On Friday 19 September 2014, Bjorn Helgaas wrote:
> > On Thu, Sep 18, 2014 at 02:30:25AM +0100, Liviu Dudau wrote:
> 
> > PCI_IOBASE is a virtual address.  So PCI_IOBASE + res->start is also a
> > virtual address (only for IORESOURCE_IO).
> > 
> > Since res->start is normally a *physical* address, I think it would be less
> > confusing to do something like this:
> > 
> >     vaddr = PCI_IOBASE + res->start;
> >     ioremap_page_range(vaddr, vaddr + resource_size(res), ...);
> > 
> > so we have a hint that the first two ioremap_page_range() parameters are
> > virtual addresses.  It's also confusing that it uses "unsigned long" for
> > the virtual addresses, when we usually use "void *".  But that's out of
> > scope for this patch.
> 
> Good idea. I think it will have to be (unsigned long)PCI_IOBASE above then,
> since ioremap_page_range takes a 'unsigned long' virtual address and PCI_IOBASE
> should really remain an __iomem pointer.

Right, I see this warning here:

drivers/pci/pci.c: In function ?pci_remap_iospace?:
drivers/pci/pci.c:2728:8: warning: assignment makes integer from pointer without a cast [enabled by default]

-Robert

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

* Re: [PATCH v11 04/10] PCI: OF: Fix the conversion of IO ranges into IO resources.
  2014-09-20 17:33     ` Rob Herring
  (?)
@ 2014-09-22 15:32       ` Liviu Dudau
  -1 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-22 15:32 UTC (permalink / raw)
  To: Rob Herring
  Cc: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	grant.likely, Thierry Reding, Simon Horman

On Sat, Sep 20, 2014 at 06:33:11PM +0100, Rob Herring wrote:
> On 09/17/2014 08:30 PM, Liviu Dudau wrote:
> > The ranges property for a host bridge controller in DT describes
> > the mapping between the PCI bus address and the CPU physical address.
> > The resources framework however expects that the IO resources start
> > at a pseudo "port" address 0 (zero) and have a maximum size of IO_SPACE_LIMIT.
> > The conversion from pci ranges to resources failed to take that into account.
> >
> > In the process move the function into drivers/of/address.c as it now
> > depends on pci_address_to_pio() code and make it return an error code.
> > Also fix all the drivers that depend on the old behaviour by fetching
> > the CPU physical address based on the port number.
> >
> > Cc: Grant Likely <grant.likely@linaro.org>
> > Cc: Rob Herring <robh+dt@kernel.org>
> > Cc: Arnd Bergmann <arnd@arndb.de>
> > Cc: Linus Walleij <linus.walleij@linaro.org>
> > Cc: Thierry Reding <thierry.reding@gmail.com>
> > Cc: Simon Horman <horms@verge.net.au>
> > Cc: Catalin Marinas <catalin.marinas@arm.com>
> > Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
> 
> A few minor things below.
> 
> > ---
> >  arch/arm/mach-integrator/pci_v3.c | 23 ++++++++++----------
> >  drivers/of/address.c              | 46 +++++++++++++++++++++++++++++++++++++++
> >  drivers/pci/host/pci-tegra.c      | 10 ++++++---
> >  drivers/pci/host/pcie-rcar.c      | 21 +++++++++++++-----
> >  include/linux/of_address.h        | 13 ++---------
> >  5 files changed, 82 insertions(+), 31 deletions(-)
> >
> > diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
> > index 05e1f73..3321e1b 100644
> > --- a/arch/arm/mach-integrator/pci_v3.c
> > +++ b/arch/arm/mach-integrator/pci_v3.c
> > @@ -660,6 +660,7 @@ static void __init pci_v3_preinit(void)
> >  {
> >       unsigned long flags;
> >       unsigned int temp;
> > +     phys_addr_t io_address = pci_pio_to_address(io_mem.start);
> >
> >       pcibios_min_mem = 0x00100000;
> >
> > @@ -701,7 +702,7 @@ static void __init pci_v3_preinit(void)
> >       /*
> >        * Setup window 2 - PCI IO
> >        */
> > -     v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_mem.start) |
> > +     v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_address) |
> >                       V3_LB_BASE_ENABLE);
> >       v3_writew(V3_LB_MAP2, v3_addr_to_lb_map2(0));
> >
> > @@ -742,6 +743,7 @@ static void __init pci_v3_preinit(void)
> >  static void __init pci_v3_postinit(void)
> >  {
> >       unsigned int pci_cmd;
> > +     phys_addr_t io_address = pci_pio_to_address(io_mem.start);
> >
> >       pci_cmd = PCI_COMMAND_MEMORY |
> >                 PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
> > @@ -758,7 +760,7 @@ static void __init pci_v3_postinit(void)
> >                      "interrupt: %d\n", ret);
> >  #endif
> >
> > -     register_isa_ports(non_mem.start, io_mem.start, 0);
> > +     register_isa_ports(non_mem.start, io_address, 0);
> >  }
> >
> >  /*
> > @@ -867,33 +869,32 @@ static int __init pci_v3_probe(struct platform_device *pdev)
> >
> >       for_each_of_pci_range(&parser, &range) {
> >               if (!range.flags) {
> > -                     of_pci_range_to_resource(&range, np, &conf_mem);
> > +                     ret = of_pci_range_to_resource(&range, np, &conf_mem);
> >                       conf_mem.name = "PCIv3 config";
> >               }
> >               if (range.flags & IORESOURCE_IO) {
> > -                     of_pci_range_to_resource(&range, np, &io_mem);
> > +                     ret = of_pci_range_to_resource(&range, np, &io_mem);
> >                       io_mem.name = "PCIv3 I/O";
> >               }
> >               if ((range.flags & IORESOURCE_MEM) &&
> >                       !(range.flags & IORESOURCE_PREFETCH)) {
> >                       non_mem_pci = range.pci_addr;
> >                       non_mem_pci_sz = range.size;
> > -                     of_pci_range_to_resource(&range, np, &non_mem);
> > +                     ret = of_pci_range_to_resource(&range, np, &non_mem);
> >                       non_mem.name = "PCIv3 non-prefetched mem";
> >               }
> >               if ((range.flags & IORESOURCE_MEM) &&
> >                       (range.flags & IORESOURCE_PREFETCH)) {
> >                       pre_mem_pci = range.pci_addr;
> >                       pre_mem_pci_sz = range.size;
> > -                     of_pci_range_to_resource(&range, np, &pre_mem);
> > +                     ret = of_pci_range_to_resource(&range, np, &pre_mem);
> >                       pre_mem.name = "PCIv3 prefetched mem";
> >               }
> > -     }
> >
> > -     if (!conf_mem.start || !io_mem.start ||
> > -         !non_mem.start || !pre_mem.start) {
> > -             dev_err(&pdev->dev, "missing ranges in device node\n");
> > -             return -EINVAL;
> > +             if (ret < 0) {
> > +                     dev_err(&pdev->dev, "missing ranges in device node\n");
> > +                     return -EINVAL;
> 
> You should return ret rather than potentially changing the return value.

I was trying to keep the existing behaviour, which was to return -EINVAL if the
parsing has failed. But I can return ret and propagate the original error code.

> 
> > +             }
> >       }
> >
> >       pci_v3.map_irq = of_irq_parse_and_map_pci;
> > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > index 2373a92..ff10b64 100644
> > --- a/drivers/of/address.c
> > +++ b/drivers/of/address.c
> > @@ -947,3 +947,49 @@ bool of_dma_is_coherent(struct device_node *np)
> >       return false;
> >  }
> >  EXPORT_SYMBOL_GPL(of_dma_is_coherent);
> > +
> > +/*
> > + * of_pci_range_to_resource - Create a resource from an of_pci_range
> > + * @range:   the PCI range that describes the resource
> > + * @np:              device node where the range belongs to
> > + * @res:     pointer to a valid resource that will be updated to
> > + *              reflect the values contained in the range.
> > + *
> > + * Returns EINVAL if the range cannot be converted to resource.
> > + *
> > + * Note that if the range is an IO range, the resource will be converted
> > + * using pci_address_to_pio() which can fail if it is called too early or
> > + * if the range cannot be matched to any host bridge IO space (our case here).
> > + * To guard against that we try to register the IO range first.
> > + * If that fails we know that pci_address_to_pio() will do too.
> > + */
> > +int of_pci_range_to_resource(struct of_pci_range *range,
> > +     struct device_node *np, struct resource *res)
> > +{
> > +     int err;
> > +     res->flags = range->flags;
> > +     res->parent = res->child = res->sibling = NULL;
> > +     res->name = np->full_name;
> > +
> > +     if (res->flags & IORESOURCE_IO) {
> > +             unsigned long port = -1;
> 
> Assigning a signed value to unsigned...

Ooops, sorry about that. Removed the initialisation now.

> 
> Does port need to be 64-bit on 64-bit hosts?

I'm following existing APIs. Basically my function is a variant of __of_address_to_resource() 

> 
> > +             err = pci_register_io_range(range->cpu_addr, range->size);
> > +             if (err)
> > +                     goto invalid_range;
> > +             port = pci_address_to_pio(range->cpu_addr);
> > +             if (port == (unsigned long)-1) {
> > +                     err = -EINVAL;
> > +                     goto invalid_range;
> > +             }
> > +             res->start = port;
> > +     } else {
> > +             res->start = range->cpu_addr;
> > +     }
> > +     res->end = res->start + range->size - 1;
> > +     return 0;
> > +
> > +invalid_range:
> > +     res->start = (resource_size_t)OF_BAD_ADDR;
> > +     res->end = (resource_size_t)OF_BAD_ADDR;
> > +     return err;
> > +}
> > diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
> > index 0fb0fdb..946935d 100644
> > --- a/drivers/pci/host/pci-tegra.c
> > +++ b/drivers/pci/host/pci-tegra.c
> > @@ -626,13 +626,14 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable);
> >  static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
> >  {
> >       struct tegra_pcie *pcie = sys_to_pcie(sys);
> > +     phys_addr_t io_start = pci_pio_to_address(pcie->io.start);
> >
> >       pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
> >       pci_add_resource_offset(&sys->resources, &pcie->prefetch,
> >                               sys->mem_offset);
> >       pci_add_resource(&sys->resources, &pcie->busn);
> >
> > -     pci_ioremap_io(nr * SZ_64K, pcie->io.start);
> > +     pci_ioremap_io(nr * SZ_64K, io_start);
> >
> >       return 1;
> >  }
> > @@ -737,6 +738,7 @@ static irqreturn_t tegra_pcie_isr(int irq, void *arg)
> >  static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
> >  {
> >       u32 fpci_bar, size, axi_address;
> > +     phys_addr_t io_start = pci_pio_to_address(pcie->io.start);
> >
> >       /* Bar 0: type 1 extended configuration space */
> >       fpci_bar = 0xfe100000;
> > @@ -749,7 +751,7 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
> >       /* Bar 1: downstream IO bar */
> >       fpci_bar = 0xfdfc0000;
> >       size = resource_size(&pcie->io);
> > -     axi_address = pcie->io.start;
> > +     axi_address = io_start;
> >       afi_writel(pcie, axi_address, AFI_AXI_BAR1_START);
> >       afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ);
> >       afi_writel(pcie, fpci_bar, AFI_FPCI_BAR1);
> > @@ -1520,7 +1522,9 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
> >       }
> >
> >       for_each_of_pci_range(&parser, &range) {
> > -             of_pci_range_to_resource(&range, np, &res);
> > +             err = of_pci_range_to_resource(&range, np, &res);
> > +             if (err < 0)
> > +                     return err;
> >
> >               switch (res.flags & IORESOURCE_TYPE_BITS) {
> >               case IORESOURCE_IO:
> > diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
> > index 4884ee5..61158e0 100644
> > --- a/drivers/pci/host/pcie-rcar.c
> > +++ b/drivers/pci/host/pcie-rcar.c
> > @@ -323,6 +323,7 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
> >
> >       /* Setup PCIe address space mappings for each resource */
> >       resource_size_t size;
> > +     resource_size_t res_start;
> >       u32 mask;
> >
> >       rcar_pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
> > @@ -335,8 +336,13 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
> >       mask = (roundup_pow_of_two(size) / SZ_128) - 1;
> >       rcar_pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
> >
> > -     rcar_pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win));
> > -     rcar_pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win));
> > +     if (res->flags & IORESOURCE_IO)
> > +             res_start = pci_pio_to_address(res->start);
> > +     else
> > +             res_start = res->start;
> > +
> > +     rcar_pci_write_reg(pcie, upper_32_bits(res_start), PCIEPARH(win));
> > +     rcar_pci_write_reg(pcie, lower_32_bits(res_start), PCIEPARL(win));
> >
> >       /* First resource is for IO */
> >       mask = PAR_ENABLE;
> > @@ -363,9 +369,10 @@ static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
> >
> >               rcar_pcie_setup_window(i, pcie);
> >
> > -             if (res->flags & IORESOURCE_IO)
> > -                     pci_ioremap_io(nr * SZ_64K, res->start);
> > -             else
> > +             if (res->flags & IORESOURCE_IO) {
> > +                     phys_addr_t io_start = pci_pio_to_address(res->start);
> > +                     pci_ioremap_io(nr * SZ_64K, io_start);
> > +             } else
> >                       pci_add_resource(&sys->resources, res);
> >       }
> >       pci_add_resource(&sys->resources, &pcie->busn);
> > @@ -935,8 +942,10 @@ static int rcar_pcie_probe(struct platform_device *pdev)
> >       }
> >
> >       for_each_of_pci_range(&parser, &range) {
> > -             of_pci_range_to_resource(&range, pdev->dev.of_node,
> > +             err = of_pci_range_to_resource(&range, pdev->dev.of_node,
> >                                               &pcie->res[win++]);
> > +             if (err < 0)
> > +                     return err;
> >
> >               if (win > RCAR_PCI_MAX_RESOURCES)
> >                       break;
> > diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> > index f8cc7da..c9d70deb 100644
> > --- a/include/linux/of_address.h
> > +++ b/include/linux/of_address.h
> > @@ -23,17 +23,8 @@ struct of_pci_range {
> >  #define for_each_of_pci_range(parser, range) \
> >       for (; of_pci_range_parser_one(parser, range);)
> >
> > -static inline void of_pci_range_to_resource(struct of_pci_range *range,
> > -                                         struct device_node *np,
> > -                                         struct resource *res)
> > -{
> > -     res->flags = range->flags;
> > -     res->start = range->cpu_addr;
> > -     res->end = range->cpu_addr + range->size - 1;
> > -     res->parent = res->child = res->sibling = NULL;
> > -     res->name = np->full_name;
> > -}
> > -
> > +extern int of_pci_range_to_resource(struct of_pci_range *range,
> > +             struct device_node *np, struct resource *res);
> 
> We probably need an empty version of this now for !OF_ADDRESS.

Good catch! Will update my patch.

Thanks for finding time to review the series!

Best regards,
Liviu

> 
> Rob
> 

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


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

* Re: [PATCH v11 04/10] PCI: OF: Fix the conversion of IO ranges into IO resources.
@ 2014-09-22 15:32       ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-22 15:32 UTC (permalink / raw)
  To: Rob Herring
  Cc: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	grant.likely

On Sat, Sep 20, 2014 at 06:33:11PM +0100, Rob Herring wrote:
> On 09/17/2014 08:30 PM, Liviu Dudau wrote:
> > The ranges property for a host bridge controller in DT describes
> > the mapping between the PCI bus address and the CPU physical address.
> > The resources framework however expects that the IO resources start
> > at a pseudo "port" address 0 (zero) and have a maximum size of IO_SPACE_LIMIT.
> > The conversion from pci ranges to resources failed to take that into account.
> >
> > In the process move the function into drivers/of/address.c as it now
> > depends on pci_address_to_pio() code and make it return an error code.
> > Also fix all the drivers that depend on the old behaviour by fetching
> > the CPU physical address based on the port number.
> >
> > Cc: Grant Likely <grant.likely@linaro.org>
> > Cc: Rob Herring <robh+dt@kernel.org>
> > Cc: Arnd Bergmann <arnd@arndb.de>
> > Cc: Linus Walleij <linus.walleij@linaro.org>
> > Cc: Thierry Reding <thierry.reding@gmail.com>
> > Cc: Simon Horman <horms@verge.net.au>
> > Cc: Catalin Marinas <catalin.marinas@arm.com>
> > Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
> 
> A few minor things below.
> 
> > ---
> >  arch/arm/mach-integrator/pci_v3.c | 23 ++++++++++----------
> >  drivers/of/address.c              | 46 +++++++++++++++++++++++++++++++++++++++
> >  drivers/pci/host/pci-tegra.c      | 10 ++++++---
> >  drivers/pci/host/pcie-rcar.c      | 21 +++++++++++++-----
> >  include/linux/of_address.h        | 13 ++---------
> >  5 files changed, 82 insertions(+), 31 deletions(-)
> >
> > diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
> > index 05e1f73..3321e1b 100644
> > --- a/arch/arm/mach-integrator/pci_v3.c
> > +++ b/arch/arm/mach-integrator/pci_v3.c
> > @@ -660,6 +660,7 @@ static void __init pci_v3_preinit(void)
> >  {
> >       unsigned long flags;
> >       unsigned int temp;
> > +     phys_addr_t io_address = pci_pio_to_address(io_mem.start);
> >
> >       pcibios_min_mem = 0x00100000;
> >
> > @@ -701,7 +702,7 @@ static void __init pci_v3_preinit(void)
> >       /*
> >        * Setup window 2 - PCI IO
> >        */
> > -     v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_mem.start) |
> > +     v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_address) |
> >                       V3_LB_BASE_ENABLE);
> >       v3_writew(V3_LB_MAP2, v3_addr_to_lb_map2(0));
> >
> > @@ -742,6 +743,7 @@ static void __init pci_v3_preinit(void)
> >  static void __init pci_v3_postinit(void)
> >  {
> >       unsigned int pci_cmd;
> > +     phys_addr_t io_address = pci_pio_to_address(io_mem.start);
> >
> >       pci_cmd = PCI_COMMAND_MEMORY |
> >                 PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
> > @@ -758,7 +760,7 @@ static void __init pci_v3_postinit(void)
> >                      "interrupt: %d\n", ret);
> >  #endif
> >
> > -     register_isa_ports(non_mem.start, io_mem.start, 0);
> > +     register_isa_ports(non_mem.start, io_address, 0);
> >  }
> >
> >  /*
> > @@ -867,33 +869,32 @@ static int __init pci_v3_probe(struct platform_device *pdev)
> >
> >       for_each_of_pci_range(&parser, &range) {
> >               if (!range.flags) {
> > -                     of_pci_range_to_resource(&range, np, &conf_mem);
> > +                     ret = of_pci_range_to_resource(&range, np, &conf_mem);
> >                       conf_mem.name = "PCIv3 config";
> >               }
> >               if (range.flags & IORESOURCE_IO) {
> > -                     of_pci_range_to_resource(&range, np, &io_mem);
> > +                     ret = of_pci_range_to_resource(&range, np, &io_mem);
> >                       io_mem.name = "PCIv3 I/O";
> >               }
> >               if ((range.flags & IORESOURCE_MEM) &&
> >                       !(range.flags & IORESOURCE_PREFETCH)) {
> >                       non_mem_pci = range.pci_addr;
> >                       non_mem_pci_sz = range.size;
> > -                     of_pci_range_to_resource(&range, np, &non_mem);
> > +                     ret = of_pci_range_to_resource(&range, np, &non_mem);
> >                       non_mem.name = "PCIv3 non-prefetched mem";
> >               }
> >               if ((range.flags & IORESOURCE_MEM) &&
> >                       (range.flags & IORESOURCE_PREFETCH)) {
> >                       pre_mem_pci = range.pci_addr;
> >                       pre_mem_pci_sz = range.size;
> > -                     of_pci_range_to_resource(&range, np, &pre_mem);
> > +                     ret = of_pci_range_to_resource(&range, np, &pre_mem);
> >                       pre_mem.name = "PCIv3 prefetched mem";
> >               }
> > -     }
> >
> > -     if (!conf_mem.start || !io_mem.start ||
> > -         !non_mem.start || !pre_mem.start) {
> > -             dev_err(&pdev->dev, "missing ranges in device node\n");
> > -             return -EINVAL;
> > +             if (ret < 0) {
> > +                     dev_err(&pdev->dev, "missing ranges in device node\n");
> > +                     return -EINVAL;
> 
> You should return ret rather than potentially changing the return value.

I was trying to keep the existing behaviour, which was to return -EINVAL if the
parsing has failed. But I can return ret and propagate the original error code.

> 
> > +             }
> >       }
> >
> >       pci_v3.map_irq = of_irq_parse_and_map_pci;
> > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > index 2373a92..ff10b64 100644
> > --- a/drivers/of/address.c
> > +++ b/drivers/of/address.c
> > @@ -947,3 +947,49 @@ bool of_dma_is_coherent(struct device_node *np)
> >       return false;
> >  }
> >  EXPORT_SYMBOL_GPL(of_dma_is_coherent);
> > +
> > +/*
> > + * of_pci_range_to_resource - Create a resource from an of_pci_range
> > + * @range:   the PCI range that describes the resource
> > + * @np:              device node where the range belongs to
> > + * @res:     pointer to a valid resource that will be updated to
> > + *              reflect the values contained in the range.
> > + *
> > + * Returns EINVAL if the range cannot be converted to resource.
> > + *
> > + * Note that if the range is an IO range, the resource will be converted
> > + * using pci_address_to_pio() which can fail if it is called too early or
> > + * if the range cannot be matched to any host bridge IO space (our case here).
> > + * To guard against that we try to register the IO range first.
> > + * If that fails we know that pci_address_to_pio() will do too.
> > + */
> > +int of_pci_range_to_resource(struct of_pci_range *range,
> > +     struct device_node *np, struct resource *res)
> > +{
> > +     int err;
> > +     res->flags = range->flags;
> > +     res->parent = res->child = res->sibling = NULL;
> > +     res->name = np->full_name;
> > +
> > +     if (res->flags & IORESOURCE_IO) {
> > +             unsigned long port = -1;
> 
> Assigning a signed value to unsigned...

Ooops, sorry about that. Removed the initialisation now.

> 
> Does port need to be 64-bit on 64-bit hosts?

I'm following existing APIs. Basically my function is a variant of __of_address_to_resource() 

> 
> > +             err = pci_register_io_range(range->cpu_addr, range->size);
> > +             if (err)
> > +                     goto invalid_range;
> > +             port = pci_address_to_pio(range->cpu_addr);
> > +             if (port == (unsigned long)-1) {
> > +                     err = -EINVAL;
> > +                     goto invalid_range;
> > +             }
> > +             res->start = port;
> > +     } else {
> > +             res->start = range->cpu_addr;
> > +     }
> > +     res->end = res->start + range->size - 1;
> > +     return 0;
> > +
> > +invalid_range:
> > +     res->start = (resource_size_t)OF_BAD_ADDR;
> > +     res->end = (resource_size_t)OF_BAD_ADDR;
> > +     return err;
> > +}
> > diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
> > index 0fb0fdb..946935d 100644
> > --- a/drivers/pci/host/pci-tegra.c
> > +++ b/drivers/pci/host/pci-tegra.c
> > @@ -626,13 +626,14 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable);
> >  static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
> >  {
> >       struct tegra_pcie *pcie = sys_to_pcie(sys);
> > +     phys_addr_t io_start = pci_pio_to_address(pcie->io.start);
> >
> >       pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
> >       pci_add_resource_offset(&sys->resources, &pcie->prefetch,
> >                               sys->mem_offset);
> >       pci_add_resource(&sys->resources, &pcie->busn);
> >
> > -     pci_ioremap_io(nr * SZ_64K, pcie->io.start);
> > +     pci_ioremap_io(nr * SZ_64K, io_start);
> >
> >       return 1;
> >  }
> > @@ -737,6 +738,7 @@ static irqreturn_t tegra_pcie_isr(int irq, void *arg)
> >  static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
> >  {
> >       u32 fpci_bar, size, axi_address;
> > +     phys_addr_t io_start = pci_pio_to_address(pcie->io.start);
> >
> >       /* Bar 0: type 1 extended configuration space */
> >       fpci_bar = 0xfe100000;
> > @@ -749,7 +751,7 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
> >       /* Bar 1: downstream IO bar */
> >       fpci_bar = 0xfdfc0000;
> >       size = resource_size(&pcie->io);
> > -     axi_address = pcie->io.start;
> > +     axi_address = io_start;
> >       afi_writel(pcie, axi_address, AFI_AXI_BAR1_START);
> >       afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ);
> >       afi_writel(pcie, fpci_bar, AFI_FPCI_BAR1);
> > @@ -1520,7 +1522,9 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
> >       }
> >
> >       for_each_of_pci_range(&parser, &range) {
> > -             of_pci_range_to_resource(&range, np, &res);
> > +             err = of_pci_range_to_resource(&range, np, &res);
> > +             if (err < 0)
> > +                     return err;
> >
> >               switch (res.flags & IORESOURCE_TYPE_BITS) {
> >               case IORESOURCE_IO:
> > diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
> > index 4884ee5..61158e0 100644
> > --- a/drivers/pci/host/pcie-rcar.c
> > +++ b/drivers/pci/host/pcie-rcar.c
> > @@ -323,6 +323,7 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
> >
> >       /* Setup PCIe address space mappings for each resource */
> >       resource_size_t size;
> > +     resource_size_t res_start;
> >       u32 mask;
> >
> >       rcar_pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
> > @@ -335,8 +336,13 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
> >       mask = (roundup_pow_of_two(size) / SZ_128) - 1;
> >       rcar_pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
> >
> > -     rcar_pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win));
> > -     rcar_pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win));
> > +     if (res->flags & IORESOURCE_IO)
> > +             res_start = pci_pio_to_address(res->start);
> > +     else
> > +             res_start = res->start;
> > +
> > +     rcar_pci_write_reg(pcie, upper_32_bits(res_start), PCIEPARH(win));
> > +     rcar_pci_write_reg(pcie, lower_32_bits(res_start), PCIEPARL(win));
> >
> >       /* First resource is for IO */
> >       mask = PAR_ENABLE;
> > @@ -363,9 +369,10 @@ static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
> >
> >               rcar_pcie_setup_window(i, pcie);
> >
> > -             if (res->flags & IORESOURCE_IO)
> > -                     pci_ioremap_io(nr * SZ_64K, res->start);
> > -             else
> > +             if (res->flags & IORESOURCE_IO) {
> > +                     phys_addr_t io_start = pci_pio_to_address(res->start);
> > +                     pci_ioremap_io(nr * SZ_64K, io_start);
> > +             } else
> >                       pci_add_resource(&sys->resources, res);
> >       }
> >       pci_add_resource(&sys->resources, &pcie->busn);
> > @@ -935,8 +942,10 @@ static int rcar_pcie_probe(struct platform_device *pdev)
> >       }
> >
> >       for_each_of_pci_range(&parser, &range) {
> > -             of_pci_range_to_resource(&range, pdev->dev.of_node,
> > +             err = of_pci_range_to_resource(&range, pdev->dev.of_node,
> >                                               &pcie->res[win++]);
> > +             if (err < 0)
> > +                     return err;
> >
> >               if (win > RCAR_PCI_MAX_RESOURCES)
> >                       break;
> > diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> > index f8cc7da..c9d70deb 100644
> > --- a/include/linux/of_address.h
> > +++ b/include/linux/of_address.h
> > @@ -23,17 +23,8 @@ struct of_pci_range {
> >  #define for_each_of_pci_range(parser, range) \
> >       for (; of_pci_range_parser_one(parser, range);)
> >
> > -static inline void of_pci_range_to_resource(struct of_pci_range *range,
> > -                                         struct device_node *np,
> > -                                         struct resource *res)
> > -{
> > -     res->flags = range->flags;
> > -     res->start = range->cpu_addr;
> > -     res->end = range->cpu_addr + range->size - 1;
> > -     res->parent = res->child = res->sibling = NULL;
> > -     res->name = np->full_name;
> > -}
> > -
> > +extern int of_pci_range_to_resource(struct of_pci_range *range,
> > +             struct device_node *np, struct resource *res);
> 
> We probably need an empty version of this now for !OF_ADDRESS.

Good catch! Will update my patch.

Thanks for finding time to review the series!

Best regards,
Liviu

> 
> Rob
> 

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

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

* [PATCH v11 04/10] PCI: OF: Fix the conversion of IO ranges into IO resources.
@ 2014-09-22 15:32       ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-22 15:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Sep 20, 2014 at 06:33:11PM +0100, Rob Herring wrote:
> On 09/17/2014 08:30 PM, Liviu Dudau wrote:
> > The ranges property for a host bridge controller in DT describes
> > the mapping between the PCI bus address and the CPU physical address.
> > The resources framework however expects that the IO resources start
> > at a pseudo "port" address 0 (zero) and have a maximum size of IO_SPACE_LIMIT.
> > The conversion from pci ranges to resources failed to take that into account.
> >
> > In the process move the function into drivers/of/address.c as it now
> > depends on pci_address_to_pio() code and make it return an error code.
> > Also fix all the drivers that depend on the old behaviour by fetching
> > the CPU physical address based on the port number.
> >
> > Cc: Grant Likely <grant.likely@linaro.org>
> > Cc: Rob Herring <robh+dt@kernel.org>
> > Cc: Arnd Bergmann <arnd@arndb.de>
> > Cc: Linus Walleij <linus.walleij@linaro.org>
> > Cc: Thierry Reding <thierry.reding@gmail.com>
> > Cc: Simon Horman <horms@verge.net.au>
> > Cc: Catalin Marinas <catalin.marinas@arm.com>
> > Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
> 
> A few minor things below.
> 
> > ---
> >  arch/arm/mach-integrator/pci_v3.c | 23 ++++++++++----------
> >  drivers/of/address.c              | 46 +++++++++++++++++++++++++++++++++++++++
> >  drivers/pci/host/pci-tegra.c      | 10 ++++++---
> >  drivers/pci/host/pcie-rcar.c      | 21 +++++++++++++-----
> >  include/linux/of_address.h        | 13 ++---------
> >  5 files changed, 82 insertions(+), 31 deletions(-)
> >
> > diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
> > index 05e1f73..3321e1b 100644
> > --- a/arch/arm/mach-integrator/pci_v3.c
> > +++ b/arch/arm/mach-integrator/pci_v3.c
> > @@ -660,6 +660,7 @@ static void __init pci_v3_preinit(void)
> >  {
> >       unsigned long flags;
> >       unsigned int temp;
> > +     phys_addr_t io_address = pci_pio_to_address(io_mem.start);
> >
> >       pcibios_min_mem = 0x00100000;
> >
> > @@ -701,7 +702,7 @@ static void __init pci_v3_preinit(void)
> >       /*
> >        * Setup window 2 - PCI IO
> >        */
> > -     v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_mem.start) |
> > +     v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_address) |
> >                       V3_LB_BASE_ENABLE);
> >       v3_writew(V3_LB_MAP2, v3_addr_to_lb_map2(0));
> >
> > @@ -742,6 +743,7 @@ static void __init pci_v3_preinit(void)
> >  static void __init pci_v3_postinit(void)
> >  {
> >       unsigned int pci_cmd;
> > +     phys_addr_t io_address = pci_pio_to_address(io_mem.start);
> >
> >       pci_cmd = PCI_COMMAND_MEMORY |
> >                 PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
> > @@ -758,7 +760,7 @@ static void __init pci_v3_postinit(void)
> >                      "interrupt: %d\n", ret);
> >  #endif
> >
> > -     register_isa_ports(non_mem.start, io_mem.start, 0);
> > +     register_isa_ports(non_mem.start, io_address, 0);
> >  }
> >
> >  /*
> > @@ -867,33 +869,32 @@ static int __init pci_v3_probe(struct platform_device *pdev)
> >
> >       for_each_of_pci_range(&parser, &range) {
> >               if (!range.flags) {
> > -                     of_pci_range_to_resource(&range, np, &conf_mem);
> > +                     ret = of_pci_range_to_resource(&range, np, &conf_mem);
> >                       conf_mem.name = "PCIv3 config";
> >               }
> >               if (range.flags & IORESOURCE_IO) {
> > -                     of_pci_range_to_resource(&range, np, &io_mem);
> > +                     ret = of_pci_range_to_resource(&range, np, &io_mem);
> >                       io_mem.name = "PCIv3 I/O";
> >               }
> >               if ((range.flags & IORESOURCE_MEM) &&
> >                       !(range.flags & IORESOURCE_PREFETCH)) {
> >                       non_mem_pci = range.pci_addr;
> >                       non_mem_pci_sz = range.size;
> > -                     of_pci_range_to_resource(&range, np, &non_mem);
> > +                     ret = of_pci_range_to_resource(&range, np, &non_mem);
> >                       non_mem.name = "PCIv3 non-prefetched mem";
> >               }
> >               if ((range.flags & IORESOURCE_MEM) &&
> >                       (range.flags & IORESOURCE_PREFETCH)) {
> >                       pre_mem_pci = range.pci_addr;
> >                       pre_mem_pci_sz = range.size;
> > -                     of_pci_range_to_resource(&range, np, &pre_mem);
> > +                     ret = of_pci_range_to_resource(&range, np, &pre_mem);
> >                       pre_mem.name = "PCIv3 prefetched mem";
> >               }
> > -     }
> >
> > -     if (!conf_mem.start || !io_mem.start ||
> > -         !non_mem.start || !pre_mem.start) {
> > -             dev_err(&pdev->dev, "missing ranges in device node\n");
> > -             return -EINVAL;
> > +             if (ret < 0) {
> > +                     dev_err(&pdev->dev, "missing ranges in device node\n");
> > +                     return -EINVAL;
> 
> You should return ret rather than potentially changing the return value.

I was trying to keep the existing behaviour, which was to return -EINVAL if the
parsing has failed. But I can return ret and propagate the original error code.

> 
> > +             }
> >       }
> >
> >       pci_v3.map_irq = of_irq_parse_and_map_pci;
> > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > index 2373a92..ff10b64 100644
> > --- a/drivers/of/address.c
> > +++ b/drivers/of/address.c
> > @@ -947,3 +947,49 @@ bool of_dma_is_coherent(struct device_node *np)
> >       return false;
> >  }
> >  EXPORT_SYMBOL_GPL(of_dma_is_coherent);
> > +
> > +/*
> > + * of_pci_range_to_resource - Create a resource from an of_pci_range
> > + * @range:   the PCI range that describes the resource
> > + * @np:              device node where the range belongs to
> > + * @res:     pointer to a valid resource that will be updated to
> > + *              reflect the values contained in the range.
> > + *
> > + * Returns EINVAL if the range cannot be converted to resource.
> > + *
> > + * Note that if the range is an IO range, the resource will be converted
> > + * using pci_address_to_pio() which can fail if it is called too early or
> > + * if the range cannot be matched to any host bridge IO space (our case here).
> > + * To guard against that we try to register the IO range first.
> > + * If that fails we know that pci_address_to_pio() will do too.
> > + */
> > +int of_pci_range_to_resource(struct of_pci_range *range,
> > +     struct device_node *np, struct resource *res)
> > +{
> > +     int err;
> > +     res->flags = range->flags;
> > +     res->parent = res->child = res->sibling = NULL;
> > +     res->name = np->full_name;
> > +
> > +     if (res->flags & IORESOURCE_IO) {
> > +             unsigned long port = -1;
> 
> Assigning a signed value to unsigned...

Ooops, sorry about that. Removed the initialisation now.

> 
> Does port need to be 64-bit on 64-bit hosts?

I'm following existing APIs. Basically my function is a variant of __of_address_to_resource() 

> 
> > +             err = pci_register_io_range(range->cpu_addr, range->size);
> > +             if (err)
> > +                     goto invalid_range;
> > +             port = pci_address_to_pio(range->cpu_addr);
> > +             if (port == (unsigned long)-1) {
> > +                     err = -EINVAL;
> > +                     goto invalid_range;
> > +             }
> > +             res->start = port;
> > +     } else {
> > +             res->start = range->cpu_addr;
> > +     }
> > +     res->end = res->start + range->size - 1;
> > +     return 0;
> > +
> > +invalid_range:
> > +     res->start = (resource_size_t)OF_BAD_ADDR;
> > +     res->end = (resource_size_t)OF_BAD_ADDR;
> > +     return err;
> > +}
> > diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
> > index 0fb0fdb..946935d 100644
> > --- a/drivers/pci/host/pci-tegra.c
> > +++ b/drivers/pci/host/pci-tegra.c
> > @@ -626,13 +626,14 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable);
> >  static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
> >  {
> >       struct tegra_pcie *pcie = sys_to_pcie(sys);
> > +     phys_addr_t io_start = pci_pio_to_address(pcie->io.start);
> >
> >       pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
> >       pci_add_resource_offset(&sys->resources, &pcie->prefetch,
> >                               sys->mem_offset);
> >       pci_add_resource(&sys->resources, &pcie->busn);
> >
> > -     pci_ioremap_io(nr * SZ_64K, pcie->io.start);
> > +     pci_ioremap_io(nr * SZ_64K, io_start);
> >
> >       return 1;
> >  }
> > @@ -737,6 +738,7 @@ static irqreturn_t tegra_pcie_isr(int irq, void *arg)
> >  static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
> >  {
> >       u32 fpci_bar, size, axi_address;
> > +     phys_addr_t io_start = pci_pio_to_address(pcie->io.start);
> >
> >       /* Bar 0: type 1 extended configuration space */
> >       fpci_bar = 0xfe100000;
> > @@ -749,7 +751,7 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
> >       /* Bar 1: downstream IO bar */
> >       fpci_bar = 0xfdfc0000;
> >       size = resource_size(&pcie->io);
> > -     axi_address = pcie->io.start;
> > +     axi_address = io_start;
> >       afi_writel(pcie, axi_address, AFI_AXI_BAR1_START);
> >       afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ);
> >       afi_writel(pcie, fpci_bar, AFI_FPCI_BAR1);
> > @@ -1520,7 +1522,9 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
> >       }
> >
> >       for_each_of_pci_range(&parser, &range) {
> > -             of_pci_range_to_resource(&range, np, &res);
> > +             err = of_pci_range_to_resource(&range, np, &res);
> > +             if (err < 0)
> > +                     return err;
> >
> >               switch (res.flags & IORESOURCE_TYPE_BITS) {
> >               case IORESOURCE_IO:
> > diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
> > index 4884ee5..61158e0 100644
> > --- a/drivers/pci/host/pcie-rcar.c
> > +++ b/drivers/pci/host/pcie-rcar.c
> > @@ -323,6 +323,7 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
> >
> >       /* Setup PCIe address space mappings for each resource */
> >       resource_size_t size;
> > +     resource_size_t res_start;
> >       u32 mask;
> >
> >       rcar_pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
> > @@ -335,8 +336,13 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
> >       mask = (roundup_pow_of_two(size) / SZ_128) - 1;
> >       rcar_pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
> >
> > -     rcar_pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win));
> > -     rcar_pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win));
> > +     if (res->flags & IORESOURCE_IO)
> > +             res_start = pci_pio_to_address(res->start);
> > +     else
> > +             res_start = res->start;
> > +
> > +     rcar_pci_write_reg(pcie, upper_32_bits(res_start), PCIEPARH(win));
> > +     rcar_pci_write_reg(pcie, lower_32_bits(res_start), PCIEPARL(win));
> >
> >       /* First resource is for IO */
> >       mask = PAR_ENABLE;
> > @@ -363,9 +369,10 @@ static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
> >
> >               rcar_pcie_setup_window(i, pcie);
> >
> > -             if (res->flags & IORESOURCE_IO)
> > -                     pci_ioremap_io(nr * SZ_64K, res->start);
> > -             else
> > +             if (res->flags & IORESOURCE_IO) {
> > +                     phys_addr_t io_start = pci_pio_to_address(res->start);
> > +                     pci_ioremap_io(nr * SZ_64K, io_start);
> > +             } else
> >                       pci_add_resource(&sys->resources, res);
> >       }
> >       pci_add_resource(&sys->resources, &pcie->busn);
> > @@ -935,8 +942,10 @@ static int rcar_pcie_probe(struct platform_device *pdev)
> >       }
> >
> >       for_each_of_pci_range(&parser, &range) {
> > -             of_pci_range_to_resource(&range, pdev->dev.of_node,
> > +             err = of_pci_range_to_resource(&range, pdev->dev.of_node,
> >                                               &pcie->res[win++]);
> > +             if (err < 0)
> > +                     return err;
> >
> >               if (win > RCAR_PCI_MAX_RESOURCES)
> >                       break;
> > diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> > index f8cc7da..c9d70deb 100644
> > --- a/include/linux/of_address.h
> > +++ b/include/linux/of_address.h
> > @@ -23,17 +23,8 @@ struct of_pci_range {
> >  #define for_each_of_pci_range(parser, range) \
> >       for (; of_pci_range_parser_one(parser, range);)
> >
> > -static inline void of_pci_range_to_resource(struct of_pci_range *range,
> > -                                         struct device_node *np,
> > -                                         struct resource *res)
> > -{
> > -     res->flags = range->flags;
> > -     res->start = range->cpu_addr;
> > -     res->end = range->cpu_addr + range->size - 1;
> > -     res->parent = res->child = res->sibling = NULL;
> > -     res->name = np->full_name;
> > -}
> > -
> > +extern int of_pci_range_to_resource(struct of_pci_range *range,
> > +             struct device_node *np, struct resource *res);
> 
> We probably need an empty version of this now for !OF_ADDRESS.

Good catch! Will update my patch.

Thanks for finding time to review the series!

Best regards,
Liviu

> 
> Rob
> 

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

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

* Re: [PATCH v11 07/10] OF: Introduce helper function for getting PCI domain_nr
  2014-09-22 15:25         ` Bjorn Helgaas
@ 2014-09-22 15:33           ` Liviu Dudau
  -1 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-22 15:33 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	grant.likely

On Mon, Sep 22, 2014 at 04:25:13PM +0100, Bjorn Helgaas wrote:
> On Mon, Sep 22, 2014 at 5:05 AM, Liviu Dudau <Liviu.Dudau@arm.com> wrote:
> > On Fri, Sep 19, 2014 at 10:03:13PM +0100, Bjorn Helgaas wrote:
> >> On Thu, Sep 18, 2014 at 02:30:22AM +0100, Liviu Dudau wrote:
> >> > Add of_pci_get_domain_nr() to retrieve the PCI domain number
> >> > of a given device from DT. If the information is not present,
> >> > the function can be requested to allocate a new domain number.
> >>
> >> Is of_pci_get_domain_nr() used somewhere?  If the use is in some future
> >> series, please mention it explicitly.  I'm just trying to avoid merging
> >> unused code.
> >
> > It is used in the arm64 specific patch that I have dropped out of my
> > pull request. After discussions with Catalin I will add the patch back
> > into the tree that you've pulled from as he is OK with your tree carrying
> > the whole package.
> >
> > I need to ask for some guidance here: for addressing some of your comments
> > and Rob's I can add more patches in my v11 branch and you can pull them
> > when you think they are ready. But one of your comments was requesting
> > splitting a patch into two blocks - one that moves of_pci_range_to_resource()
> > into drivers/of/address.c and one that fixes it's behaviour - and I don't
> > know how you would like that handled. Should I revert the original patch
> > and add the new ones, or should I rebase the whole series into a different
> > branch that you can pull from?
> 
> I guess the easiest thing is probably just to send a v12 series.  I
> was hoping we were close enough for me to just hand-integrate minor
> tweaks into my branch, but I think that will just create more
> confusion.

OK, I will send v12 then with all the acquired ACKs and fixes.

Best regards,
Liviu

> 
> Bjorn
> 

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


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

* [PATCH v11 07/10] OF: Introduce helper function for getting PCI domain_nr
@ 2014-09-22 15:33           ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-22 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Sep 22, 2014 at 04:25:13PM +0100, Bjorn Helgaas wrote:
> On Mon, Sep 22, 2014 at 5:05 AM, Liviu Dudau <Liviu.Dudau@arm.com> wrote:
> > On Fri, Sep 19, 2014 at 10:03:13PM +0100, Bjorn Helgaas wrote:
> >> On Thu, Sep 18, 2014 at 02:30:22AM +0100, Liviu Dudau wrote:
> >> > Add of_pci_get_domain_nr() to retrieve the PCI domain number
> >> > of a given device from DT. If the information is not present,
> >> > the function can be requested to allocate a new domain number.
> >>
> >> Is of_pci_get_domain_nr() used somewhere?  If the use is in some future
> >> series, please mention it explicitly.  I'm just trying to avoid merging
> >> unused code.
> >
> > It is used in the arm64 specific patch that I have dropped out of my
> > pull request. After discussions with Catalin I will add the patch back
> > into the tree that you've pulled from as he is OK with your tree carrying
> > the whole package.
> >
> > I need to ask for some guidance here: for addressing some of your comments
> > and Rob's I can add more patches in my v11 branch and you can pull them
> > when you think they are ready. But one of your comments was requesting
> > splitting a patch into two blocks - one that moves of_pci_range_to_resource()
> > into drivers/of/address.c and one that fixes it's behaviour - and I don't
> > know how you would like that handled. Should I revert the original patch
> > and add the new ones, or should I rebase the whole series into a different
> > branch that you can pull from?
> 
> I guess the easiest thing is probably just to send a v12 series.  I
> was hoping we were close enough for me to just hand-integrate minor
> tweaks into my branch, but I think that will just create more
> confusion.

OK, I will send v12 then with all the acquired ACKs and fixes.

Best regards,
Liviu

> 
> Bjorn
> 

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

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

* Re: [PATCH v11 04/10] PCI: OF: Fix the conversion of IO ranges into IO resources.
  2014-09-22 15:32       ` Liviu Dudau
  (?)
@ 2014-09-22 17:18         ` Rob Herring
  -1 siblings, 0 replies; 105+ messages in thread
From: Rob Herring @ 2014-09-22 17:18 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	grant.likely, Thierry Reding, Simon Horman

On Mon, Sep 22, 2014 at 10:32 AM, Liviu Dudau <Liviu.Dudau@arm.com> wrote:
> On Sat, Sep 20, 2014 at 06:33:11PM +0100, Rob Herring wrote:
>> On 09/17/2014 08:30 PM, Liviu Dudau wrote:
>> > The ranges property for a host bridge controller in DT describes
>> > the mapping between the PCI bus address and the CPU physical address.
>> > The resources framework however expects that the IO resources start
>> > at a pseudo "port" address 0 (zero) and have a maximum size of IO_SPACE_LIMIT.
>> > The conversion from pci ranges to resources failed to take that into account.

[...]

>> >               if ((range.flags & IORESOURCE_MEM) &&
>> >                       (range.flags & IORESOURCE_PREFETCH)) {
>> >                       pre_mem_pci = range.pci_addr;
>> >                       pre_mem_pci_sz = range.size;
>> > -                     of_pci_range_to_resource(&range, np, &pre_mem);
>> > +                     ret = of_pci_range_to_resource(&range, np, &pre_mem);
>> >                       pre_mem.name = "PCIv3 prefetched mem";
>> >               }
>> > -     }
>> >
>> > -     if (!conf_mem.start || !io_mem.start ||
>> > -         !non_mem.start || !pre_mem.start) {
>> > -             dev_err(&pdev->dev, "missing ranges in device node\n");
>> > -             return -EINVAL;
>> > +             if (ret < 0) {
>> > +                     dev_err(&pdev->dev, "missing ranges in device node\n");
>> > +                     return -EINVAL;
>>
>> You should return ret rather than potentially changing the return value.
>
> I was trying to keep the existing behaviour, which was to return -EINVAL if the
> parsing has failed. But I can return ret and propagate the original error code.

A valid concern, but I checked and I believe the return from
of_pci_range_to_resource is currently -EINVAL.

>> > +int of_pci_range_to_resource(struct of_pci_range *range,
>> > +     struct device_node *np, struct resource *res)
>> > +{
>> > +     int err;
>> > +     res->flags = range->flags;
>> > +     res->parent = res->child = res->sibling = NULL;
>> > +     res->name = np->full_name;
>> > +
>> > +     if (res->flags & IORESOURCE_IO) {
>> > +             unsigned long port = -1;
>>
>> Assigning a signed value to unsigned...
>
> Ooops, sorry about that. Removed the initialisation now.
>
>>
>> Does port need to be 64-bit on 64-bit hosts?
>
> I'm following existing APIs. Basically my function is a variant of __of_address_to_resource()

Okay.

Rob

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

* Re: [PATCH v11 04/10] PCI: OF: Fix the conversion of IO ranges into IO resources.
@ 2014-09-22 17:18         ` Rob Herring
  0 siblings, 0 replies; 105+ messages in thread
From: Rob Herring @ 2014-09-22 17:18 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	grant.likely

On Mon, Sep 22, 2014 at 10:32 AM, Liviu Dudau <Liviu.Dudau@arm.com> wrote:
> On Sat, Sep 20, 2014 at 06:33:11PM +0100, Rob Herring wrote:
>> On 09/17/2014 08:30 PM, Liviu Dudau wrote:
>> > The ranges property for a host bridge controller in DT describes
>> > the mapping between the PCI bus address and the CPU physical address.
>> > The resources framework however expects that the IO resources start
>> > at a pseudo "port" address 0 (zero) and have a maximum size of IO_SPACE_LIMIT.
>> > The conversion from pci ranges to resources failed to take that into account.

[...]

>> >               if ((range.flags & IORESOURCE_MEM) &&
>> >                       (range.flags & IORESOURCE_PREFETCH)) {
>> >                       pre_mem_pci = range.pci_addr;
>> >                       pre_mem_pci_sz = range.size;
>> > -                     of_pci_range_to_resource(&range, np, &pre_mem);
>> > +                     ret = of_pci_range_to_resource(&range, np, &pre_mem);
>> >                       pre_mem.name = "PCIv3 prefetched mem";
>> >               }
>> > -     }
>> >
>> > -     if (!conf_mem.start || !io_mem.start ||
>> > -         !non_mem.start || !pre_mem.start) {
>> > -             dev_err(&pdev->dev, "missing ranges in device node\n");
>> > -             return -EINVAL;
>> > +             if (ret < 0) {
>> > +                     dev_err(&pdev->dev, "missing ranges in device node\n");
>> > +                     return -EINVAL;
>>
>> You should return ret rather than potentially changing the return value.
>
> I was trying to keep the existing behaviour, which was to return -EINVAL if the
> parsing has failed. But I can return ret and propagate the original error code.

A valid concern, but I checked and I believe the return from
of_pci_range_to_resource is currently -EINVAL.

>> > +int of_pci_range_to_resource(struct of_pci_range *range,
>> > +     struct device_node *np, struct resource *res)
>> > +{
>> > +     int err;
>> > +     res->flags = range->flags;
>> > +     res->parent = res->child = res->sibling = NULL;
>> > +     res->name = np->full_name;
>> > +
>> > +     if (res->flags & IORESOURCE_IO) {
>> > +             unsigned long port = -1;
>>
>> Assigning a signed value to unsigned...
>
> Ooops, sorry about that. Removed the initialisation now.
>
>>
>> Does port need to be 64-bit on 64-bit hosts?
>
> I'm following existing APIs. Basically my function is a variant of __of_address_to_resource()

Okay.

Rob

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

* [PATCH v11 04/10] PCI: OF: Fix the conversion of IO ranges into IO resources.
@ 2014-09-22 17:18         ` Rob Herring
  0 siblings, 0 replies; 105+ messages in thread
From: Rob Herring @ 2014-09-22 17:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Sep 22, 2014 at 10:32 AM, Liviu Dudau <Liviu.Dudau@arm.com> wrote:
> On Sat, Sep 20, 2014 at 06:33:11PM +0100, Rob Herring wrote:
>> On 09/17/2014 08:30 PM, Liviu Dudau wrote:
>> > The ranges property for a host bridge controller in DT describes
>> > the mapping between the PCI bus address and the CPU physical address.
>> > The resources framework however expects that the IO resources start
>> > at a pseudo "port" address 0 (zero) and have a maximum size of IO_SPACE_LIMIT.
>> > The conversion from pci ranges to resources failed to take that into account.

[...]

>> >               if ((range.flags & IORESOURCE_MEM) &&
>> >                       (range.flags & IORESOURCE_PREFETCH)) {
>> >                       pre_mem_pci = range.pci_addr;
>> >                       pre_mem_pci_sz = range.size;
>> > -                     of_pci_range_to_resource(&range, np, &pre_mem);
>> > +                     ret = of_pci_range_to_resource(&range, np, &pre_mem);
>> >                       pre_mem.name = "PCIv3 prefetched mem";
>> >               }
>> > -     }
>> >
>> > -     if (!conf_mem.start || !io_mem.start ||
>> > -         !non_mem.start || !pre_mem.start) {
>> > -             dev_err(&pdev->dev, "missing ranges in device node\n");
>> > -             return -EINVAL;
>> > +             if (ret < 0) {
>> > +                     dev_err(&pdev->dev, "missing ranges in device node\n");
>> > +                     return -EINVAL;
>>
>> You should return ret rather than potentially changing the return value.
>
> I was trying to keep the existing behaviour, which was to return -EINVAL if the
> parsing has failed. But I can return ret and propagate the original error code.

A valid concern, but I checked and I believe the return from
of_pci_range_to_resource is currently -EINVAL.

>> > +int of_pci_range_to_resource(struct of_pci_range *range,
>> > +     struct device_node *np, struct resource *res)
>> > +{
>> > +     int err;
>> > +     res->flags = range->flags;
>> > +     res->parent = res->child = res->sibling = NULL;
>> > +     res->name = np->full_name;
>> > +
>> > +     if (res->flags & IORESOURCE_IO) {
>> > +             unsigned long port = -1;
>>
>> Assigning a signed value to unsigned...
>
> Ooops, sorry about that. Removed the initialisation now.
>
>>
>> Does port need to be 64-bit on 64-bit hosts?
>
> I'm following existing APIs. Basically my function is a variant of __of_address_to_resource()

Okay.

Rob

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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
  2014-09-20  0:28       ` Rob Herring
@ 2014-09-22 17:55         ` Liviu Dudau
  -1 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-22 17:55 UTC (permalink / raw)
  To: Rob Herring
  Cc: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	grant.likely

On Sat, Sep 20, 2014 at 01:28:38AM +0100, Rob Herring wrote:
> On 09/19/2014 04:06 PM, Bjorn Helgaas wrote:
> > On Thu, Sep 18, 2014 at 02:30:23AM +0100, Liviu Dudau wrote:
> >> Provide a function to parse the PCI DT ranges that can be used to
> >> create a pci_host_bridge structure together with its associated
> >> bus.
> >>
> >> Cc: Bjorn Helgaas <bhelgaas@google.com>
> >> Cc: Arnd Bergmann <arnd@arndb.de>
> >> Cc: Grant Likely <grant.likely@linaro.org>
> >> Cc: Rob Herring <robh+dt@kernel.org>
> >> Cc: Catalin Marinas <catalin.marinas@arm.com>
> >> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
> >> ---
> 
> [...]
> 
> >> +int of_pci_get_host_bridge_resources(struct device_node *dev,
> >> +			unsigned char busno, unsigned char bus_max,
> >> +			struct list_head *resources, resource_size_t *io_base)
> >> +{
> >> +	struct resource *res;
> >> +	struct resource *bus_range;
> >> +	struct of_pci_range range;
> >> +	struct of_pci_range_parser parser;
> >> +	char range_type[4];
> >> +	int err;
> >> +
> >> +	if (!io_base)
> >> +		return -EINVAL;
> >> +	*io_base = OF_BAD_ADDR;
> >> +
> >> +	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
> 
> This function does a lot of kalloc's but there is not an easy way to
> undo those allocations. Hot unplug of a host bridge or probe error
> handling would leak memory.
> 
> You could pass in struct device and use the devm_ variant (also
> addressing Bjorn's comment), but not having an uninit/remove function
> make what clean-up drivers have to do error prone. For example, on
> uninit a driver needs to call pci_free_resource_list.

If the function fails to parse the ranges for whatever reason it will
call pci_free_resource_list on the resources that have been added already
and it will clean up. If it is successful, then it is the job of the caller
to free the list, as mentioned in the comment associated with the function.

The reason why I am reluctant to use devm_ here is that the ranges are only
parsed here, no filtering is applied. Architectures and/or host bridge
drivers can/could impose additional restrictions to the list before passing
it to pci_scan_root_bus() for example.

Best regards,
Liviu

> 
> Rob
> 

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


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

* [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-22 17:55         ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-22 17:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Sep 20, 2014 at 01:28:38AM +0100, Rob Herring wrote:
> On 09/19/2014 04:06 PM, Bjorn Helgaas wrote:
> > On Thu, Sep 18, 2014 at 02:30:23AM +0100, Liviu Dudau wrote:
> >> Provide a function to parse the PCI DT ranges that can be used to
> >> create a pci_host_bridge structure together with its associated
> >> bus.
> >>
> >> Cc: Bjorn Helgaas <bhelgaas@google.com>
> >> Cc: Arnd Bergmann <arnd@arndb.de>
> >> Cc: Grant Likely <grant.likely@linaro.org>
> >> Cc: Rob Herring <robh+dt@kernel.org>
> >> Cc: Catalin Marinas <catalin.marinas@arm.com>
> >> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
> >> ---
> 
> [...]
> 
> >> +int of_pci_get_host_bridge_resources(struct device_node *dev,
> >> +			unsigned char busno, unsigned char bus_max,
> >> +			struct list_head *resources, resource_size_t *io_base)
> >> +{
> >> +	struct resource *res;
> >> +	struct resource *bus_range;
> >> +	struct of_pci_range range;
> >> +	struct of_pci_range_parser parser;
> >> +	char range_type[4];
> >> +	int err;
> >> +
> >> +	if (!io_base)
> >> +		return -EINVAL;
> >> +	*io_base = OF_BAD_ADDR;
> >> +
> >> +	bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
> 
> This function does a lot of kalloc's but there is not an easy way to
> undo those allocations. Hot unplug of a host bridge or probe error
> handling would leak memory.
> 
> You could pass in struct device and use the devm_ variant (also
> addressing Bjorn's comment), but not having an uninit/remove function
> make what clean-up drivers have to do error prone. For example, on
> uninit a driver needs to call pci_free_resource_list.

If the function fails to parse the ranges for whatever reason it will
call pci_free_resource_list on the resources that have been added already
and it will clean up. If it is successful, then it is the job of the caller
to free the list, as mentioned in the comment associated with the function.

The reason why I am reluctant to use devm_ here is that the ranges are only
parsed here, no filtering is applied. Architectures and/or host bridge
drivers can/could impose additional restrictions to the list before passing
it to pci_scan_root_bus() for example.

Best regards,
Liviu

> 
> Rob
> 

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

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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
  2014-09-22 17:55         ` Liviu Dudau
@ 2014-09-22 22:11           ` Rob Herring
  -1 siblings, 0 replies; 105+ messages in thread
From: Rob Herring @ 2014-09-22 22:11 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Bjorn Helgaas, Arnd Bergmann, Rob Herring, Jason Gunthorpe,
	Benjamin Herrenschmidt, Catalin Marinas, Will Deacon,
	Russell King, linux-pci, Linus Walleij, Tanmay Inamdar,
	Grant Likely, Sinan Kaya, Jingoo Han, Kukjin Kim,
	Suravee Suthikulanit, linux-arch, LKML, Device Tree ML, LAKML,
	grant.likely

On Mon, Sep 22, 2014 at 12:55 PM, Liviu Dudau <Liviu.Dudau@arm.com> wrote:
> On Sat, Sep 20, 2014 at 01:28:38AM +0100, Rob Herring wrote:
>> On 09/19/2014 04:06 PM, Bjorn Helgaas wrote:
>> > On Thu, Sep 18, 2014 at 02:30:23AM +0100, Liviu Dudau wrote:
>> >> Provide a function to parse the PCI DT ranges that can be used to
>> >> create a pci_host_bridge structure together with its associated
>> >> bus.
>> >>
>> >> Cc: Bjorn Helgaas <bhelgaas@google.com>
>> >> Cc: Arnd Bergmann <arnd@arndb.de>
>> >> Cc: Grant Likely <grant.likely@linaro.org>
>> >> Cc: Rob Herring <robh+dt@kernel.org>
>> >> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> >> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
>> >> ---
>>
>> [...]
>>
>> >> +int of_pci_get_host_bridge_resources(struct device_node *dev,
>> >> +                  unsigned char busno, unsigned char bus_max,
>> >> +                  struct list_head *resources, resource_size_t *io_base)
>> >> +{
>> >> +  struct resource *res;
>> >> +  struct resource *bus_range;
>> >> +  struct of_pci_range range;
>> >> +  struct of_pci_range_parser parser;
>> >> +  char range_type[4];
>> >> +  int err;
>> >> +
>> >> +  if (!io_base)
>> >> +          return -EINVAL;
>> >> +  *io_base = OF_BAD_ADDR;
>> >> +
>> >> +  bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
>>
>> This function does a lot of kalloc's but there is not an easy way to
>> undo those allocations. Hot unplug of a host bridge or probe error
>> handling would leak memory.
>>
>> You could pass in struct device and use the devm_ variant (also
>> addressing Bjorn's comment), but not having an uninit/remove function
>> make what clean-up drivers have to do error prone. For example, on
>> uninit a driver needs to call pci_free_resource_list.
>
> If the function fails to parse the ranges for whatever reason it will
> call pci_free_resource_list on the resources that have been added already
> and it will clean up. If it is successful, then it is the job of the caller
> to free the list, as mentioned in the comment associated with the function.
>
> The reason why I am reluctant to use devm_ here is that the ranges are only
> parsed here, no filtering is applied. Architectures and/or host bridge
> drivers can/could impose additional restrictions to the list before passing
> it to pci_scan_root_bus() for example.

Okay, as long as the caller has a single clean-up responsibility, I
guess it is fine.

Rob

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

* [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-22 22:11           ` Rob Herring
  0 siblings, 0 replies; 105+ messages in thread
From: Rob Herring @ 2014-09-22 22:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Sep 22, 2014 at 12:55 PM, Liviu Dudau <Liviu.Dudau@arm.com> wrote:
> On Sat, Sep 20, 2014 at 01:28:38AM +0100, Rob Herring wrote:
>> On 09/19/2014 04:06 PM, Bjorn Helgaas wrote:
>> > On Thu, Sep 18, 2014 at 02:30:23AM +0100, Liviu Dudau wrote:
>> >> Provide a function to parse the PCI DT ranges that can be used to
>> >> create a pci_host_bridge structure together with its associated
>> >> bus.
>> >>
>> >> Cc: Bjorn Helgaas <bhelgaas@google.com>
>> >> Cc: Arnd Bergmann <arnd@arndb.de>
>> >> Cc: Grant Likely <grant.likely@linaro.org>
>> >> Cc: Rob Herring <robh+dt@kernel.org>
>> >> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> >> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
>> >> ---
>>
>> [...]
>>
>> >> +int of_pci_get_host_bridge_resources(struct device_node *dev,
>> >> +                  unsigned char busno, unsigned char bus_max,
>> >> +                  struct list_head *resources, resource_size_t *io_base)
>> >> +{
>> >> +  struct resource *res;
>> >> +  struct resource *bus_range;
>> >> +  struct of_pci_range range;
>> >> +  struct of_pci_range_parser parser;
>> >> +  char range_type[4];
>> >> +  int err;
>> >> +
>> >> +  if (!io_base)
>> >> +          return -EINVAL;
>> >> +  *io_base = OF_BAD_ADDR;
>> >> +
>> >> +  bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
>>
>> This function does a lot of kalloc's but there is not an easy way to
>> undo those allocations. Hot unplug of a host bridge or probe error
>> handling would leak memory.
>>
>> You could pass in struct device and use the devm_ variant (also
>> addressing Bjorn's comment), but not having an uninit/remove function
>> make what clean-up drivers have to do error prone. For example, on
>> uninit a driver needs to call pci_free_resource_list.
>
> If the function fails to parse the ranges for whatever reason it will
> call pci_free_resource_list on the resources that have been added already
> and it will clean up. If it is successful, then it is the job of the caller
> to free the list, as mentioned in the comment associated with the function.
>
> The reason why I am reluctant to use devm_ here is that the ranges are only
> parsed here, no filtering is applied. Architectures and/or host bridge
> drivers can/could impose additional restrictions to the list before passing
> it to pci_scan_root_bus() for example.

Okay, as long as the caller has a single clean-up responsibility, I
guess it is fine.

Rob

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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
  2014-09-22 11:43       ` Liviu Dudau
  (?)
@ 2014-09-23  7:56         ` Arnd Bergmann
  -1 siblings, 0 replies; 105+ messages in thread
From: Arnd Bergmann @ 2014-09-23  7:56 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Liviu Dudau, Robert Richter, Benjamin Herrenschmidt, linux-pci,
	Linus Walleij, Will Deacon, Grant Likely, Tanmay Inamdar,
	linux-arch, Kukjin Kim, Russell King, Jingoo Han,
	Jason Gunthorpe, Catalin Marinas, grant.likely, Device Tree ML,
	Rob Herring, Bjorn Helgaas, Sinan Kaya, Sunil Goutham, LKML,
	Suravee Suthikulanit

On Monday 22 September 2014 12:43:17 Liviu Dudau wrote:
> > 
> > From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
> > From: Robert Richter <rrichter@cavium.com>
> > Date: Mon, 22 Sep 2014 10:46:01 +0200
> > Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
> > 
> > The pci host bridge was not created if io_base was not set when
> > calling of_pci_get_host_bridge_resources(). This is esp. the case for
> > mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
> > parameter io_base is optional now.
> 
> I think the message is misleading. What you want to do is make io_base
> optional for the case where the PCI host bridge only expects to have only
> IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.
> 
> As I'm going to touch this area again to address a comment from Bjorn,
> do you mind if I roll this patch into mine with your Signed-off-by and
> the mention that you have made io_base optional?

I think the best way to deal with this is to move the check for 
io_base down into the place where it is used: As long as the DT only
specifies IORESOURCE_MEM windows, we don't need to look at io_base,
but if the host controller driver does not support IORESOURCE_IO
while the DT specifies it, I guess it would be nice to return an
error.

	Arnd

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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-23  7:56         ` Arnd Bergmann
  0 siblings, 0 replies; 105+ messages in thread
From: Arnd Bergmann @ 2014-09-23  7:56 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Liviu Dudau, Robert Richter, Benjamin Herrenschmidt, linux-pci,
	Linus Walleij, Will Deacon, Grant Likely, Tanmay Inamdar,
	linux-arch, Kukjin Kim, Russell King, Jingoo Han,
	Jason Gunthorpe, Catalin Marinas, grant.likely, Device Tree ML,
	Rob Herring, Bjorn Helgaas, Sinan Kaya, Sunil Goutham, LKML,
	Suravee Suthikulanit

On Monday 22 September 2014 12:43:17 Liviu Dudau wrote:
> > 
> > From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
> > From: Robert Richter <rrichter@cavium.com>
> > Date: Mon, 22 Sep 2014 10:46:01 +0200
> > Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
> > 
> > The pci host bridge was not created if io_base was not set when
> > calling of_pci_get_host_bridge_resources(). This is esp. the case for
> > mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
> > parameter io_base is optional now.
> 
> I think the message is misleading. What you want to do is make io_base
> optional for the case where the PCI host bridge only expects to have only
> IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.
> 
> As I'm going to touch this area again to address a comment from Bjorn,
> do you mind if I roll this patch into mine with your Signed-off-by and
> the mention that you have made io_base optional?

I think the best way to deal with this is to move the check for 
io_base down into the place where it is used: As long as the DT only
specifies IORESOURCE_MEM windows, we don't need to look at io_base,
but if the host controller driver does not support IORESOURCE_IO
while the DT specifies it, I guess it would be nice to return an
error.

	Arnd

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

* [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-23  7:56         ` Arnd Bergmann
  0 siblings, 0 replies; 105+ messages in thread
From: Arnd Bergmann @ 2014-09-23  7:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Monday 22 September 2014 12:43:17 Liviu Dudau wrote:
> > 
> > From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
> > From: Robert Richter <rrichter@cavium.com>
> > Date: Mon, 22 Sep 2014 10:46:01 +0200
> > Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
> > 
> > The pci host bridge was not created if io_base was not set when
> > calling of_pci_get_host_bridge_resources(). This is esp. the case for
> > mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
> > parameter io_base is optional now.
> 
> I think the message is misleading. What you want to do is make io_base
> optional for the case where the PCI host bridge only expects to have only
> IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.
> 
> As I'm going to touch this area again to address a comment from Bjorn,
> do you mind if I roll this patch into mine with your Signed-off-by and
> the mention that you have made io_base optional?

I think the best way to deal with this is to move the check for 
io_base down into the place where it is used: As long as the DT only
specifies IORESOURCE_MEM windows, we don't need to look at io_base,
but if the host controller driver does not support IORESOURCE_IO
while the DT specifies it, I guess it would be nice to return an
error.

	Arnd

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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
  2014-09-23  7:56         ` Arnd Bergmann
  (?)
  (?)
@ 2014-09-23 10:49           ` Liviu Dudau
  -1 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-23 10:49 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, Robert Richter, Benjamin Herrenschmidt,
	linux-pci, Linus Walleij, Will Deacon, Grant Likely,
	Tanmay Inamdar, linux-arch, Kukjin Kim, Russell King, Jingoo Han,
	Jason Gunthorpe, Catalin Marinas, grant.likely, Device Tree ML,
	Rob Herring, Bjorn Helgaas, Sinan Kaya, Sunil Goutham, LKML,
	Suravee Suthikulanit

On Tue, Sep 23, 2014 at 08:56:37AM +0100, Arnd Bergmann wrote:
> On Monday 22 September 2014 12:43:17 Liviu Dudau wrote:
> > > 
> > > From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
> > > From: Robert Richter <rrichter@cavium.com>
> > > Date: Mon, 22 Sep 2014 10:46:01 +0200
> > > Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
> > > 
> > > The pci host bridge was not created if io_base was not set when
> > > calling of_pci_get_host_bridge_resources(). This is esp. the case for
> > > mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
> > > parameter io_base is optional now.
> > 
> > I think the message is misleading. What you want to do is make io_base
> > optional for the case where the PCI host bridge only expects to have only
> > IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.
> > 
> > As I'm going to touch this area again to address a comment from Bjorn,
> > do you mind if I roll this patch into mine with your Signed-off-by and
> > the mention that you have made io_base optional?
> 
> I think the best way to deal with this is to move the check for 
> io_base down into the place where it is used: As long as the DT only
> specifies IORESOURCE_MEM windows, we don't need to look at io_base,
> but if the host controller driver does not support IORESOURCE_IO
> while the DT specifies it, I guess it would be nice to return an
> error.

Because the detection of IORESOURCE_{IO|MEM} happens in a loop I still
need to initialise the io_base to some invalid value before going into the
for_each_of_pci_range() {...} body. I have added a check in v12 for the
lack of valid io_base pointer if IORESOURCE_IO range is found.

Best regards,
Liviu

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

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


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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-23 10:49           ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-23 10:49 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, Robert Richter, Benjamin Herrenschmidt,
	linux-pci, Linus Walleij, Will Deacon, Grant Likely,
	Tanmay Inamdar, linux-arch, Kukjin Kim, Russell King, Jingoo Han,
	Jason Gunthorpe, Catalin Marinas, grant.likely, Device Tree ML,
	Rob Herring, Bjorn Helgaas, Sinan Kaya, Sunil Goutham, LKML

On Tue, Sep 23, 2014 at 08:56:37AM +0100, Arnd Bergmann wrote:
> On Monday 22 September 2014 12:43:17 Liviu Dudau wrote:
> > > 
> > > From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
> > > From: Robert Richter <rrichter@cavium.com>
> > > Date: Mon, 22 Sep 2014 10:46:01 +0200
> > > Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
> > > 
> > > The pci host bridge was not created if io_base was not set when
> > > calling of_pci_get_host_bridge_resources(). This is esp. the case for
> > > mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
> > > parameter io_base is optional now.
> > 
> > I think the message is misleading. What you want to do is make io_base
> > optional for the case where the PCI host bridge only expects to have only
> > IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.
> > 
> > As I'm going to touch this area again to address a comment from Bjorn,
> > do you mind if I roll this patch into mine with your Signed-off-by and
> > the mention that you have made io_base optional?
> 
> I think the best way to deal with this is to move the check for 
> io_base down into the place where it is used: As long as the DT only
> specifies IORESOURCE_MEM windows, we don't need to look at io_base,
> but if the host controller driver does not support IORESOURCE_IO
> while the DT specifies it, I guess it would be nice to return an
> error.

Because the detection of IORESOURCE_{IO|MEM} happens in a loop I still
need to initialise the io_base to some invalid value before going into the
for_each_of_pci_range() {...} body. I have added a check in v12 for the
lack of valid io_base pointer if IORESOURCE_IO range is found.

Best regards,
Liviu

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

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

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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-23 10:49           ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-23 10:49 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, Robert Richter, Benjamin Herrenschmidt,
	linux-pci, Linus Walleij, Will Deacon, Grant Likely,
	Tanmay Inamdar, linux-arch, Kukjin Kim, Russell King, Jingoo Han,
	Jason Gunthorpe, Catalin Marinas, grant.likely, Device Tree ML,
	Rob Herring, Bjorn Helgaas, Sinan Kaya, Sunil Goutham, LKML,
	Suravee Suthikulanit

On Tue, Sep 23, 2014 at 08:56:37AM +0100, Arnd Bergmann wrote:
> On Monday 22 September 2014 12:43:17 Liviu Dudau wrote:
> > > 
> > > From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
> > > From: Robert Richter <rrichter@cavium.com>
> > > Date: Mon, 22 Sep 2014 10:46:01 +0200
> > > Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
> > > 
> > > The pci host bridge was not created if io_base was not set when
> > > calling of_pci_get_host_bridge_resources(). This is esp. the case for
> > > mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
> > > parameter io_base is optional now.
> > 
> > I think the message is misleading. What you want to do is make io_base
> > optional for the case where the PCI host bridge only expects to have only
> > IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.
> > 
> > As I'm going to touch this area again to address a comment from Bjorn,
> > do you mind if I roll this patch into mine with your Signed-off-by and
> > the mention that you have made io_base optional?
> 
> I think the best way to deal with this is to move the check for 
> io_base down into the place where it is used: As long as the DT only
> specifies IORESOURCE_MEM windows, we don't need to look at io_base,
> but if the host controller driver does not support IORESOURCE_IO
> while the DT specifies it, I guess it would be nice to return an
> error.

Because the detection of IORESOURCE_{IO|MEM} happens in a loop I still
need to initialise the io_base to some invalid value before going into the
for_each_of_pci_range() {...} body. I have added a check in v12 for the
lack of valid io_base pointer if IORESOURCE_IO range is found.

Best regards,
Liviu

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

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


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

* [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-23 10:49           ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-23 10:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Sep 23, 2014 at 08:56:37AM +0100, Arnd Bergmann wrote:
> On Monday 22 September 2014 12:43:17 Liviu Dudau wrote:
> > > 
> > > From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
> > > From: Robert Richter <rrichter@cavium.com>
> > > Date: Mon, 22 Sep 2014 10:46:01 +0200
> > > Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
> > > 
> > > The pci host bridge was not created if io_base was not set when
> > > calling of_pci_get_host_bridge_resources(). This is esp. the case for
> > > mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
> > > parameter io_base is optional now.
> > 
> > I think the message is misleading. What you want to do is make io_base
> > optional for the case where the PCI host bridge only expects to have only
> > IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.
> > 
> > As I'm going to touch this area again to address a comment from Bjorn,
> > do you mind if I roll this patch into mine with your Signed-off-by and
> > the mention that you have made io_base optional?
> 
> I think the best way to deal with this is to move the check for 
> io_base down into the place where it is used: As long as the DT only
> specifies IORESOURCE_MEM windows, we don't need to look at io_base,
> but if the host controller driver does not support IORESOURCE_IO
> while the DT specifies it, I guess it would be nice to return an
> error.

Because the detection of IORESOURCE_{IO|MEM} happens in a loop I still
need to initialise the io_base to some invalid value before going into the
for_each_of_pci_range() {...} body. I have added a check in v12 for the
lack of valid io_base pointer if IORESOURCE_IO range is found.

Best regards,
Liviu

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

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

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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
  2014-09-23  7:56         ` Arnd Bergmann
  (?)
  (?)
@ 2014-09-23 13:30           ` Rob Herring
  -1 siblings, 0 replies; 105+ messages in thread
From: Rob Herring @ 2014-09-23 13:30 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, Liviu Dudau, Robert Richter,
	Benjamin Herrenschmidt, linux-pci, Linus Walleij, Will Deacon,
	Grant Likely, Tanmay Inamdar, linux-arch, Kukjin Kim,
	Russell King, Jingoo Han, Jason Gunthorpe, Catalin Marinas,
	grant.likely, Device Tree ML, Rob Herring, Bjorn Helgaas,
	Sinan Kaya, Sunil Goutham, LKML, Suravee Suthikulanit

On Tue, Sep 23, 2014 at 2:56 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Monday 22 September 2014 12:43:17 Liviu Dudau wrote:
>> >
>> > From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
>> > From: Robert Richter <rrichter@cavium.com>
>> > Date: Mon, 22 Sep 2014 10:46:01 +0200
>> > Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
>> >
>> > The pci host bridge was not created if io_base was not set when
>> > calling of_pci_get_host_bridge_resources(). This is esp. the case for
>> > mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
>> > parameter io_base is optional now.
>>
>> I think the message is misleading. What you want to do is make io_base
>> optional for the case where the PCI host bridge only expects to have only
>> IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.
>>
>> As I'm going to touch this area again to address a comment from Bjorn,
>> do you mind if I roll this patch into mine with your Signed-off-by and
>> the mention that you have made io_base optional?
>
> I think the best way to deal with this is to move the check for
> io_base down into the place where it is used: As long as the DT only
> specifies IORESOURCE_MEM windows, we don't need to look at io_base,
> but if the host controller driver does not support IORESOURCE_IO
> while the DT specifies it, I guess it would be nice to return an
> error.

The DT may specify it, but the h/w could be broken in some way so the
host driver chooses to ignore it. I don't think we should force the
host driver to provide a pointer in that case. Also, would we want it
added to the resource list if it is not going to be used?

Rob

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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-23 13:30           ` Rob Herring
  0 siblings, 0 replies; 105+ messages in thread
From: Rob Herring @ 2014-09-23 13:30 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Liviu Dudau,
	Robert Richter, Benjamin Herrenschmidt, linux-pci, Linus Walleij,
	Will Deacon, Grant Likely, Tanmay Inamdar, linux-arch,
	Kukjin Kim, Russell King, Jingoo Han, Jason Gunthorpe,
	Catalin Marinas, grant.likely-QSEj5FYQhm4dnm+yROfE0A,
	Device Tree ML, Rob Herring, Bjorn Helgaas, Sinan Kaya,
	Sunil Goutham

On Tue, Sep 23, 2014 at 2:56 AM, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
> On Monday 22 September 2014 12:43:17 Liviu Dudau wrote:
>> >
>> > From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
>> > From: Robert Richter <rrichter-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>
>> > Date: Mon, 22 Sep 2014 10:46:01 +0200
>> > Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
>> >
>> > The pci host bridge was not created if io_base was not set when
>> > calling of_pci_get_host_bridge_resources(). This is esp. the case for
>> > mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
>> > parameter io_base is optional now.
>>
>> I think the message is misleading. What you want to do is make io_base
>> optional for the case where the PCI host bridge only expects to have only
>> IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.
>>
>> As I'm going to touch this area again to address a comment from Bjorn,
>> do you mind if I roll this patch into mine with your Signed-off-by and
>> the mention that you have made io_base optional?
>
> I think the best way to deal with this is to move the check for
> io_base down into the place where it is used: As long as the DT only
> specifies IORESOURCE_MEM windows, we don't need to look at io_base,
> but if the host controller driver does not support IORESOURCE_IO
> while the DT specifies it, I guess it would be nice to return an
> error.

The DT may specify it, but the h/w could be broken in some way so the
host driver chooses to ignore it. I don't think we should force the
host driver to provide a pointer in that case. Also, would we want it
added to the resource list if it is not going to be used?

Rob
--
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] 105+ messages in thread

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-23 13:30           ` Rob Herring
  0 siblings, 0 replies; 105+ messages in thread
From: Rob Herring @ 2014-09-23 13:30 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, Liviu Dudau, Robert Richter,
	Benjamin Herrenschmidt, linux-pci, Linus Walleij, Will Deacon,
	Grant Likely, Tanmay Inamdar, linux-arch, Kukjin Kim,
	Russell King, Jingoo Han, Jason Gunthorpe, Catalin Marinas,
	grant.likely, Device Tree ML, Rob Herring, Bjorn Helgaas,
	Sinan Kaya, Sunil Goutham, LKML, Suravee Suthikulanit

On Tue, Sep 23, 2014 at 2:56 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Monday 22 September 2014 12:43:17 Liviu Dudau wrote:
>> >
>> > From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
>> > From: Robert Richter <rrichter@cavium.com>
>> > Date: Mon, 22 Sep 2014 10:46:01 +0200
>> > Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
>> >
>> > The pci host bridge was not created if io_base was not set when
>> > calling of_pci_get_host_bridge_resources(). This is esp. the case for
>> > mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
>> > parameter io_base is optional now.
>>
>> I think the message is misleading. What you want to do is make io_base
>> optional for the case where the PCI host bridge only expects to have only
>> IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.
>>
>> As I'm going to touch this area again to address a comment from Bjorn,
>> do you mind if I roll this patch into mine with your Signed-off-by and
>> the mention that you have made io_base optional?
>
> I think the best way to deal with this is to move the check for
> io_base down into the place where it is used: As long as the DT only
> specifies IORESOURCE_MEM windows, we don't need to look at io_base,
> but if the host controller driver does not support IORESOURCE_IO
> while the DT specifies it, I guess it would be nice to return an
> error.

The DT may specify it, but the h/w could be broken in some way so the
host driver chooses to ignore it. I don't think we should force the
host driver to provide a pointer in that case. Also, would we want it
added to the resource list if it is not going to be used?

Rob

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

* [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-23 13:30           ` Rob Herring
  0 siblings, 0 replies; 105+ messages in thread
From: Rob Herring @ 2014-09-23 13:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Sep 23, 2014 at 2:56 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Monday 22 September 2014 12:43:17 Liviu Dudau wrote:
>> >
>> > From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
>> > From: Robert Richter <rrichter@cavium.com>
>> > Date: Mon, 22 Sep 2014 10:46:01 +0200
>> > Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
>> >
>> > The pci host bridge was not created if io_base was not set when
>> > calling of_pci_get_host_bridge_resources(). This is esp. the case for
>> > mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
>> > parameter io_base is optional now.
>>
>> I think the message is misleading. What you want to do is make io_base
>> optional for the case where the PCI host bridge only expects to have only
>> IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.
>>
>> As I'm going to touch this area again to address a comment from Bjorn,
>> do you mind if I roll this patch into mine with your Signed-off-by and
>> the mention that you have made io_base optional?
>
> I think the best way to deal with this is to move the check for
> io_base down into the place where it is used: As long as the DT only
> specifies IORESOURCE_MEM windows, we don't need to look at io_base,
> but if the host controller driver does not support IORESOURCE_IO
> while the DT specifies it, I guess it would be nice to return an
> error.

The DT may specify it, but the h/w could be broken in some way so the
host driver chooses to ignore it. I don't think we should force the
host driver to provide a pointer in that case. Also, would we want it
added to the resource list if it is not going to be used?

Rob

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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
  2014-09-23 13:30           ` Rob Herring
  (?)
  (?)
@ 2014-09-23 13:58             ` Liviu Dudau
  -1 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-23 13:58 UTC (permalink / raw)
  To: Rob Herring
  Cc: Arnd Bergmann, linux-arm-kernel, Robert Richter,
	Benjamin Herrenschmidt, linux-pci, Linus Walleij, Will Deacon,
	Grant Likely, Tanmay Inamdar, linux-arch, Kukjin Kim,
	Russell King, Jingoo Han, Jason Gunthorpe, Catalin Marinas,
	grant.likely, Device Tree ML, Rob Herring, Bjorn Helgaas,
	Sinan Kaya, Sunil Goutham, LKML, Suravee Suthikulanit

On Tue, Sep 23, 2014 at 02:30:08PM +0100, Rob Herring wrote:
> On Tue, Sep 23, 2014 at 2:56 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> > On Monday 22 September 2014 12:43:17 Liviu Dudau wrote:
> >> >
> >> > From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
> >> > From: Robert Richter <rrichter@cavium.com>
> >> > Date: Mon, 22 Sep 2014 10:46:01 +0200
> >> > Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
> >> >
> >> > The pci host bridge was not created if io_base was not set when
> >> > calling of_pci_get_host_bridge_resources(). This is esp. the case for
> >> > mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
> >> > parameter io_base is optional now.
> >>
> >> I think the message is misleading. What you want to do is make io_base
> >> optional for the case where the PCI host bridge only expects to have only
> >> IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.
> >>
> >> As I'm going to touch this area again to address a comment from Bjorn,
> >> do you mind if I roll this patch into mine with your Signed-off-by and
> >> the mention that you have made io_base optional?
> >
> > I think the best way to deal with this is to move the check for
> > io_base down into the place where it is used: As long as the DT only
> > specifies IORESOURCE_MEM windows, we don't need to look at io_base,
> > but if the host controller driver does not support IORESOURCE_IO
> > while the DT specifies it, I guess it would be nice to return an
> > error.
> 
> The DT may specify it, but the h/w could be broken in some way so the
> host driver chooses to ignore it. I don't think we should force the
> host driver to provide a pointer in that case. Also, would we want it
> added to the resource list if it is not going to be used?

This is only for scanning the DT ranges. If the hardware is broken and
the driver knows about that then it can filter out the I/O ranges
before it passes them on to pci_scan_root_bus() or pci_create_root_bus().

Lets not complicate this function any further. If you get an I/O range
it should be expected to also pass an io_base pointer to store the
CPU address of the range, otherwise it will get lost in the conversion
to an IORESOURCE_IO resource. You want later to discard the resource
and forget the CPU address, then don't use it!

Best regards,
Liviu

> 
> Rob
> 

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


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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-23 13:58             ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-23 13:58 UTC (permalink / raw)
  To: Rob Herring
  Cc: Arnd Bergmann, linux-arm-kernel, Robert Richter,
	Benjamin Herrenschmidt, linux-pci, Linus Walleij, Will Deacon,
	Grant Likely, Tanmay Inamdar, linux-arch, Kukjin Kim,
	Russell King, Jingoo Han, Jason Gunthorpe, Catalin Marinas,
	grant.likely, Device Tree ML, Rob Herring, Bjorn Helgaas,
	Sinan Kaya, Sunil Goutham

On Tue, Sep 23, 2014 at 02:30:08PM +0100, Rob Herring wrote:
> On Tue, Sep 23, 2014 at 2:56 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> > On Monday 22 September 2014 12:43:17 Liviu Dudau wrote:
> >> >
> >> > From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
> >> > From: Robert Richter <rrichter@cavium.com>
> >> > Date: Mon, 22 Sep 2014 10:46:01 +0200
> >> > Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
> >> >
> >> > The pci host bridge was not created if io_base was not set when
> >> > calling of_pci_get_host_bridge_resources(). This is esp. the case for
> >> > mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
> >> > parameter io_base is optional now.
> >>
> >> I think the message is misleading. What you want to do is make io_base
> >> optional for the case where the PCI host bridge only expects to have only
> >> IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.
> >>
> >> As I'm going to touch this area again to address a comment from Bjorn,
> >> do you mind if I roll this patch into mine with your Signed-off-by and
> >> the mention that you have made io_base optional?
> >
> > I think the best way to deal with this is to move the check for
> > io_base down into the place where it is used: As long as the DT only
> > specifies IORESOURCE_MEM windows, we don't need to look at io_base,
> > but if the host controller driver does not support IORESOURCE_IO
> > while the DT specifies it, I guess it would be nice to return an
> > error.
> 
> The DT may specify it, but the h/w could be broken in some way so the
> host driver chooses to ignore it. I don't think we should force the
> host driver to provide a pointer in that case. Also, would we want it
> added to the resource list if it is not going to be used?

This is only for scanning the DT ranges. If the hardware is broken and
the driver knows about that then it can filter out the I/O ranges
before it passes them on to pci_scan_root_bus() or pci_create_root_bus().

Lets not complicate this function any further. If you get an I/O range
it should be expected to also pass an io_base pointer to store the
CPU address of the range, otherwise it will get lost in the conversion
to an IORESOURCE_IO resource. You want later to discard the resource
and forget the CPU address, then don't use it!

Best regards,
Liviu

> 
> Rob
> 

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

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

* Re: [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-23 13:58             ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-23 13:58 UTC (permalink / raw)
  To: Rob Herring
  Cc: Arnd Bergmann, linux-arm-kernel, Robert Richter,
	Benjamin Herrenschmidt, linux-pci, Linus Walleij, Will Deacon,
	Grant Likely, Tanmay Inamdar, linux-arch, Kukjin Kim,
	Russell King, Jingoo Han, Jason Gunthorpe, Catalin Marinas,
	grant.likely, Device Tree ML, Rob Herring, Bjorn Helgaas,
	Sinan Kaya, Sunil Goutham, LKML, Suravee Suthikulanit

On Tue, Sep 23, 2014 at 02:30:08PM +0100, Rob Herring wrote:
> On Tue, Sep 23, 2014 at 2:56 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> > On Monday 22 September 2014 12:43:17 Liviu Dudau wrote:
> >> >
> >> > From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
> >> > From: Robert Richter <rrichter@cavium.com>
> >> > Date: Mon, 22 Sep 2014 10:46:01 +0200
> >> > Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
> >> >
> >> > The pci host bridge was not created if io_base was not set when
> >> > calling of_pci_get_host_bridge_resources(). This is esp. the case for
> >> > mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
> >> > parameter io_base is optional now.
> >>
> >> I think the message is misleading. What you want to do is make io_base
> >> optional for the case where the PCI host bridge only expects to have only
> >> IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.
> >>
> >> As I'm going to touch this area again to address a comment from Bjorn,
> >> do you mind if I roll this patch into mine with your Signed-off-by and
> >> the mention that you have made io_base optional?
> >
> > I think the best way to deal with this is to move the check for
> > io_base down into the place where it is used: As long as the DT only
> > specifies IORESOURCE_MEM windows, we don't need to look at io_base,
> > but if the host controller driver does not support IORESOURCE_IO
> > while the DT specifies it, I guess it would be nice to return an
> > error.
> 
> The DT may specify it, but the h/w could be broken in some way so the
> host driver chooses to ignore it. I don't think we should force the
> host driver to provide a pointer in that case. Also, would we want it
> added to the resource list if it is not going to be used?

This is only for scanning the DT ranges. If the hardware is broken and
the driver knows about that then it can filter out the I/O ranges
before it passes them on to pci_scan_root_bus() or pci_create_root_bus().

Lets not complicate this function any further. If you get an I/O range
it should be expected to also pass an io_base pointer to store the
CPU address of the range, otherwise it will get lost in the conversion
to an IORESOURCE_IO resource. You want later to discard the resource
and forget the CPU address, then don't use it!

Best regards,
Liviu

> 
> Rob
> 

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


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

* [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT
@ 2014-09-23 13:58             ` Liviu Dudau
  0 siblings, 0 replies; 105+ messages in thread
From: Liviu Dudau @ 2014-09-23 13:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Sep 23, 2014 at 02:30:08PM +0100, Rob Herring wrote:
> On Tue, Sep 23, 2014 at 2:56 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> > On Monday 22 September 2014 12:43:17 Liviu Dudau wrote:
> >> >
> >> > From e798af4fc2f664d1aff7e863489b8298f90e716e Mon Sep 17 00:00:00 2001
> >> > From: Robert Richter <rrichter@cavium.com>
> >> > Date: Mon, 22 Sep 2014 10:46:01 +0200
> >> > Subject: [PATCH] OF: PCI: Fix creation of mem-mapped pci host bridges
> >> >
> >> > The pci host bridge was not created if io_base was not set when
> >> > calling of_pci_get_host_bridge_resources(). This is esp. the case for
> >> > mem-mapped io (IORESOURCE_MEM). This patch fixes this. Function
> >> > parameter io_base is optional now.
> >>
> >> I think the message is misleading. What you want to do is make io_base
> >> optional for the case where the PCI host bridge only expects to have only
> >> IORESOURCE_MEM ranges and doesn't care about IORESOURCE_IO ones.
> >>
> >> As I'm going to touch this area again to address a comment from Bjorn,
> >> do you mind if I roll this patch into mine with your Signed-off-by and
> >> the mention that you have made io_base optional?
> >
> > I think the best way to deal with this is to move the check for
> > io_base down into the place where it is used: As long as the DT only
> > specifies IORESOURCE_MEM windows, we don't need to look at io_base,
> > but if the host controller driver does not support IORESOURCE_IO
> > while the DT specifies it, I guess it would be nice to return an
> > error.
> 
> The DT may specify it, but the h/w could be broken in some way so the
> host driver chooses to ignore it. I don't think we should force the
> host driver to provide a pointer in that case. Also, would we want it
> added to the resource list if it is not going to be used?

This is only for scanning the DT ranges. If the hardware is broken and
the driver knows about that then it can filter out the I/O ranges
before it passes them on to pci_scan_root_bus() or pci_create_root_bus().

Lets not complicate this function any further. If you get an I/O range
it should be expected to also pass an io_base pointer to store the
CPU address of the range, otherwise it will get lost in the conversion
to an IORESOURCE_IO resource. You want later to discard the resource
and forget the CPU address, then don't use it!

Best regards,
Liviu

> 
> Rob
> 

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

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

end of thread, other threads:[~2014-09-23 13:58 UTC | newest]

Thread overview: 105+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-18  1:30 [PATCH v11 00/10] Support for creating generic PCI host bridges from DT Liviu Dudau
2014-09-18  1:30 ` Liviu Dudau
2014-09-18  1:30 ` Liviu Dudau
2014-09-18  1:30 ` [PATCH v11 01/10] Fix ioport_map() for !CONFIG_GENERIC_IOMAP cases Liviu Dudau
2014-09-18  1:30   ` Liviu Dudau
2014-09-18  1:30   ` Liviu Dudau
2014-09-18  1:30 ` [PATCH v11 02/10] PCI: Introduce helper functions to deal with PCI I/O ranges Liviu Dudau
2014-09-18  1:30   ` Liviu Dudau
2014-09-19 20:48   ` Bjorn Helgaas
2014-09-19 20:48     ` Bjorn Helgaas
2014-09-19 20:48     ` Bjorn Helgaas
2014-09-18  1:30 ` [PATCH v11 03/10] ARM: Define PCI_IOBASE as the base of virtual PCI IO space Liviu Dudau
2014-09-18  1:30   ` Liviu Dudau
2014-09-20  2:14   ` Arnd Bergmann
2014-09-20  2:14     ` Arnd Bergmann
2014-09-20  2:14     ` Arnd Bergmann
2014-09-18  1:30 ` [PATCH v11 04/10] PCI: OF: Fix the conversion of IO ranges into IO resources Liviu Dudau
2014-09-18  1:30   ` Liviu Dudau
2014-09-19 20:56   ` Bjorn Helgaas
2014-09-19 20:56     ` Bjorn Helgaas
2014-09-19 20:56     ` Bjorn Helgaas
2014-09-20 17:33   ` Rob Herring
2014-09-20 17:33     ` Rob Herring
2014-09-22 15:32     ` Liviu Dudau
2014-09-22 15:32       ` Liviu Dudau
2014-09-22 15:32       ` Liviu Dudau
2014-09-22 17:18       ` Rob Herring
2014-09-22 17:18         ` Rob Herring
2014-09-22 17:18         ` Rob Herring
2014-09-18  1:30 ` [PATCH v11 05/10] PCI: Create pci_host_bridge before its associated bus in pci_create_root_bus Liviu Dudau
2014-09-18  1:30   ` Liviu Dudau
2014-09-18  1:30   ` Liviu Dudau
2014-09-18  1:30 ` [PATCH v11 06/10] PCI: Introduce generic domain handling for PCI busses Liviu Dudau
2014-09-18  1:30   ` Liviu Dudau
2014-09-18  1:30   ` Liviu Dudau
2014-09-18  1:30 ` [PATCH v11 07/10] OF: Introduce helper function for getting PCI domain_nr Liviu Dudau
2014-09-18  1:30   ` Liviu Dudau
2014-09-18  1:30   ` Liviu Dudau
2014-09-19 21:03   ` Bjorn Helgaas
2014-09-19 21:03     ` Bjorn Helgaas
2014-09-22 11:05     ` Liviu Dudau
2014-09-22 11:05       ` Liviu Dudau
2014-09-22 15:25       ` Bjorn Helgaas
2014-09-22 15:25         ` Bjorn Helgaas
2014-09-22 15:33         ` Liviu Dudau
2014-09-22 15:33           ` Liviu Dudau
2014-09-20  2:24   ` Arnd Bergmann
2014-09-20  2:24     ` Arnd Bergmann
2014-09-22 15:20     ` Liviu Dudau
2014-09-22 15:20       ` Liviu Dudau
2014-09-20 17:52   ` Rob Herring
2014-09-20 17:52     ` Rob Herring
2014-09-18  1:30 ` [PATCH v11 08/10] OF: PCI: Add support for parsing PCI host bridge resources from DT Liviu Dudau
2014-09-18  1:30   ` Liviu Dudau
2014-09-19 21:06   ` Bjorn Helgaas
2014-09-19 21:06     ` Bjorn Helgaas
2014-09-20  0:28     ` Rob Herring
2014-09-20  0:28       ` Rob Herring
2014-09-22 17:55       ` Liviu Dudau
2014-09-22 17:55         ` Liviu Dudau
2014-09-22 22:11         ` Rob Herring
2014-09-22 22:11           ` Rob Herring
2014-09-22  9:32   ` Robert Richter
2014-09-22  9:32     ` Robert Richter
2014-09-22  9:32     ` Robert Richter
2014-09-22  9:32     ` Robert Richter
2014-09-22 11:43     ` Liviu Dudau
2014-09-22 11:43       ` Liviu Dudau
2014-09-22 11:43       ` Liviu Dudau
2014-09-22 12:15       ` Robert Richter
2014-09-22 12:15         ` Robert Richter
2014-09-22 12:15         ` Robert Richter
2014-09-23  7:56       ` Arnd Bergmann
2014-09-23  7:56         ` Arnd Bergmann
2014-09-23  7:56         ` Arnd Bergmann
2014-09-23 10:49         ` Liviu Dudau
2014-09-23 10:49           ` Liviu Dudau
2014-09-23 10:49           ` Liviu Dudau
2014-09-23 10:49           ` Liviu Dudau
2014-09-23 13:30         ` Rob Herring
2014-09-23 13:30           ` Rob Herring
2014-09-23 13:30           ` Rob Herring
2014-09-23 13:30           ` Rob Herring
2014-09-23 13:58           ` Liviu Dudau
2014-09-23 13:58             ` Liviu Dudau
2014-09-23 13:58             ` Liviu Dudau
2014-09-23 13:58             ` Liviu Dudau
2014-09-18  1:30 ` [PATCH v11 09/10] PCI: Assign unassigned bus resources in pci_scan_root_bus() Liviu Dudau
2014-09-18  1:30   ` Liviu Dudau
2014-09-18  1:30   ` Liviu Dudau
2014-09-18  1:30 ` [PATCH v11 10/10] PCI: Introduce pci_remap_iospace() for remapping PCI I/O bus resources into CPU space Liviu Dudau
2014-09-18  1:30   ` Liviu Dudau
2014-09-18  1:30   ` Liviu Dudau
2014-09-19 21:54   ` Bjorn Helgaas
2014-09-19 21:54     ` Bjorn Helgaas
2014-09-20  2:20     ` Arnd Bergmann
2014-09-20  2:20       ` Arnd Bergmann
2014-09-22 15:29       ` Robert Richter
2014-09-22 15:29         ` Robert Richter
2014-09-20  0:34   ` Rob Herring
2014-09-20  0:34     ` Rob Herring
2014-09-19 21:59 ` [PATCH v11 00/10] Support for creating generic PCI host bridges from DT Bjorn Helgaas
2014-09-19 21:59   ` Bjorn Helgaas
2014-09-22 11:35   ` Liviu Dudau
2014-09-22 11:35     ` Liviu Dudau

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.