Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1650414 > unrolled thread

[PATCH v9 0/7] LPC: legacy ISA I/O support

Started byGabriele Paoloni <gabriele.paoloni@huawei.com>
First post2017-05-25 13:50 +0200
Last post2017-05-25 13:50 +0200
Articles 6 — 2 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v9 0/7] LPC: legacy ISA I/O support Gabriele Paoloni <gabriele.paoloni@huawei.com> - 2017-05-25 13:50 +0200
    [PATCH v9 7/7] MANTAINERS: Add maintainer for HiSilicon LPC driver Gabriele Paoloni <gabriele.paoloni@huawei.com> - 2017-05-25 13:50 +0200
    [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts Gabriele Paoloni <gabriele.paoloni@huawei.com> - 2017-05-25 13:50 +0200
      Re: [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI  IO hosts Bjorn Helgaas <helgaas@kernel.org> - 2017-05-27 03:30 +0200
        RE: [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI  IO hosts Gabriele Paoloni <gabriele.paoloni@huawei.com> - 2017-05-30 10:20 +0200
    [PATCH v9 3/7] OF: Add missing I/O range exception for indirect-IO devices Gabriele Paoloni <gabriele.paoloni@huawei.com> - 2017-05-25 13:50 +0200

#1650414 — [PATCH v9 0/7] LPC: legacy ISA I/O support

FromGabriele Paoloni <gabriele.paoloni@huawei.com>
Date2017-05-25 13:50 +0200
Subject[PATCH v9 0/7] LPC: legacy ISA I/O support
Message-ID<tKZhw-7An-19@gated-at.bofh.it>
From: gabriele paoloni <gabriele.paoloni@huawei.com>

This patchset supports the IPMI-bt device attached to the Low-Pin-Count
interface implemented on Hisilicon Hip06/Hip07 SoC.
                        -----------
                        | LPC host|
                        |         |
                        -----------
                             |
                _____________V_______________LPC
                  |                       |
                  V                       V
                                     ------------
                                     |  BT(ipmi)|
                                     ------------

When master accesses those peripherals beneath the Hip06/Hip07 LPC, a specific
LPC driver is needed to make LPC host generate the standard LPC I/O cycles with
the target peripherals'I/O port addresses. But on curent arm64 world, there is
no real I/O accesses. All the I/O operations through in/out accessors are based
on MMIO ranges; on Hip06/Hip07 LPC the I/O accesses are performed through driver
specific accessors rather than MMIO.
To solve this issue and keep the relevant existing peripherals' drivers untouched,
this patchset:
   - introduces a generic I/O space management framework, LIBIO, to support I/O
     operations on host controllers operating either on MMIO buses or on buses
     requiring specific driver I/O accessors;
   - redefines the in/out accessors to provide a unified interface for both MMIO
     and driver specific I/O operations. Using LIBIO, th call of in/out() from
     the host children drivers, such as ipmi-si, will be redirected to the
     corresponding device-specific I/O hooks to perform the I/O accesses.

 Based on this patch-set, all the I/O accesses to Hip06/Hip07 LPC peripherals can
 be supported without any changes on the existing ipmi-si driver.

 The whole patchset has been tested on Hip07 D05 board both using DTB and ACPI.

Changes from v8:
  - Simplified LIB IO framewrok
  - Moved INDIRECT PIO ACPI framework under acpi/arm64
  - Renamed occurrences of "lib io" and "indirect io" to "lib pio" and
    "indirect pio" to keep the patchset nomenclature consistent
  - Removed Alignment reuqirements
  - Moved LPC specific code out of ACPI common framework
  - Now PIO indirect HW ranges can overlap
  - Changed HiSilicon LPC driver maintainer (Gabriele Paoloni now) and split
    maintaner file modifications in a separate commit
  - Removed the commit with the DT nodes support for hip06 and hip07 (to be
    pushed separately)
  - Added a checking on ioport_map() not to break that function as Arnd points
    out in V7 review thread;
  - fixed the compile issues on alpha, m68k;

Changes from V7:
  - Based on Arnd's comment, rename the LIBIO as LOGIC_PIO;
  - Improved the mapping process in LOGIC_PIO to gain better efficiency when
    redirecting the I/O accesses to right device driver;
  - To reduce the impact on PCI MMIO to a minimum, add a new
    CONFIG_INDIRECT_PIO for indirect-IO hosts/devices;
  - Added a new ACPI handler for indirect-IO hosts/devices;
  - Fixed the compile issues on V6;

Changes from V6:
  - According to the comments from Bjorn and Alex, merge PCI IO and indirect-IO
    into a generic I/O space management, LIBIO;
  - Adopted the '_DEP' to replace the platform bus notifier. In this way, we can
    ensure the LPC peripherals' I/O resources had been translated to logical IO
    before the LPC peripheral enumeration;
  - Replaced the rwlock with rcu list based on Alex's suggestion;
  - Applied relaxed write/read to LPC driver;
  - Some bugs fixing and some optimazations based on the comments of V6;

Changes from V5:
  - Made the extio driver more generic and locate in lib/;
  - Supported multiple indirect-IO bus instances;
  - Extended the pci_register_io_range() to support indirect-IO, then dropped
  the I/O reservation used in previous patchset;
  - Reimplemented the ACPI LPC support;
  - Fixed some bugs, including the compile error on other archs, the module
  building failure found by Ming Lei, etc;

Changes from V4:
  - Some revises based on the comments from Bjorn, Rob on V4;
  - Fixed the compile error on some platforms, such as openrisc;

Changes from V3:
  - UART support deferred to a separate patchset; This patchset only support
  ipmi device under LPC;
  - LPC bus I/O range is fixed to 0 ~ (PCIBIOS_MIN_IO - 1), which is separeted
  from PCI/PCIE PIO space;
  - Based on Arnd's remarks, removed the ranges property from Hip06 lpc dts and
  added a new fixup function, of_isa_indirect_io(), to get the I/O address
  directly from LPC dts configurations;
  - Support in(w,l)/out(w,l) for Hip06 lpc I/O;
  - Decouple the header file dependency on the gerenic io.h by defining in/out
  as normal functions in c file;
  - removed unused macro definitions in the LPC driver;

Changes from V2:
  - Support the PIO retrieval from the linux PIO generated by
  pci_address_to_pio. This method replace the 4K PIO reservation in V2;
  - Support the flat-tree earlycon;
  - Some revises based on Arnd's remarks;
  - Make sure the linux PIO range allocated to Hip06 LPC peripherals starts
  from non-ZERO;

Changes from V1:
  - Support the ACPI LPC device;
  - Optimize the dts LPC driver in ISA compatible mode;
  - Reserve the IO range below 4K in avoid the possible conflict with PCI host
  IO ranges;
  - Support the LPC uart and relevant earlycon;

V8 thread here: https://lkml.org/lkml/2017/3/30/619
V7 thread here: https://lkml.org/lkml/2017/3/12/279
v6 thread here: https://lkml.org/lkml/2017/1/24/25
v5 thread here: https://lkml.org/lkml/2016/11/7/955
v4 thread here: https://lkml.org/lkml/2016/10/20/149
v3 thread here: https://lkml.org/lkml/2016/9/14/326
v2 thread here: https://lkml.org/lkml/2016/9/7/356
v1 thread here: https://lkml.org/lkml/2015/12/29/154

Gabriele (1):
  ACPI: Translate the I/O range of non-MMIO devices before scanning

Gabriele Paoloni (1):
  MANTAINERS: Add maintainer for HiSilicon LPC driver

zhichang.yuan (5):
  LIB: Introduce a generic PIO mapping method
  PCI: Apply the new generic I/O management on PCI IO hosts
  OF: Add missing I/O range exception for indirect-IO devices
  LPC: Support the device-tree LPC host on Hip06/Hip07
  LPC: Add the ACPI LPC support

 .../arm/hisilicon/hisilicon-low-pin-count.txt      |  33 ++
 MAINTAINERS                                        |   8 +
 drivers/acpi/arm64/Makefile                        |   1 +
 drivers/acpi/arm64/acpi_indirect_pio.c             | 304 ++++++++++
 drivers/acpi/internal.h                            |   5 +
 drivers/acpi/pci_root.c                            |   8 +-
 drivers/acpi/scan.c                                |   1 +
 drivers/bus/Kconfig                                |   9 +
 drivers/bus/Makefile                               |   1 +
 drivers/bus/hisi_lpc.c                             | 609 +++++++++++++++++++++
 drivers/of/address.c                               |  95 +++-
 drivers/pci/pci.c                                  | 101 +---
 include/acpi/acpi_indirect_pio.h                   |  28 +
 include/asm-generic/io.h                           |  52 +-
 include/linux/logic_pio.h                          | 110 ++++
 include/linux/pci.h                                |   3 +-
 lib/Kconfig                                        |  26 +
 lib/Makefile                                       |   2 +
 lib/logic_pio.c                                    | 280 ++++++++++
 19 files changed, 1573 insertions(+), 103 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
 create mode 100644 drivers/acpi/arm64/acpi_indirect_pio.c
 create mode 100644 drivers/bus/hisi_lpc.c
 create mode 100644 include/acpi/acpi_indirect_pio.h
 create mode 100644 include/linux/logic_pio.h
 create mode 100644 lib/logic_pio.c

-- 
2.7.4

[toc] | [next] | [standalone]


#1650415 — [PATCH v9 7/7] MANTAINERS: Add maintainer for HiSilicon LPC driver

FromGabriele Paoloni <gabriele.paoloni@huawei.com>
Date2017-05-25 13:50 +0200
Subject[PATCH v9 7/7] MANTAINERS: Add maintainer for HiSilicon LPC driver
Message-ID<tKZrc-7Fs-5@gated-at.bofh.it>
In reply to#1650414
Added maintainer for drivers/bus/hisi_lpc.c

Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 MAINTAINERS | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 9e98464..8fb9006 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6061,6 +6061,14 @@ F:	include/uapi/linux/if_hippi.h
 F:	net/802/hippi.c
 F:	drivers/net/hippi/
 
+HISILICON LPC BUS DRIVER
+M:	Gabriele Paoloni <gabriele.paoloni@huawei.com>
+L:	linux-arm-kernel@lists.infradead.org
+W:	http://www.hisilicon.com
+S:	Maintained
+F:	drivers/bus/hisi_lpc.c
+F:	Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
+
 HISILICON NETWORK SUBSYSTEM DRIVER
 M:	Yisen Zhuang <yisen.zhuang@huawei.com>
 M:	Salil Mehta <salil.mehta@huawei.com>
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1650419 — [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts

FromGabriele Paoloni <gabriele.paoloni@huawei.com>
Date2017-05-25 13:50 +0200
Subject[PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts
Message-ID<tKZrc-7Fs-29@gated-at.bofh.it>
In reply to#1650414
From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

After introducing the new generic I/O space management(LOGIC_IO), the
original PCI MMIO relevant helpers need to be updated based on the new
interfaces defined in LOGIC_IO.
This patch adapts the corresponding code to match the changes introduced
by LOGIC_IO.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>        #earlier draft
---
 drivers/acpi/pci_root.c  |   8 ++--
 drivers/of/address.c     |   5 ++-
 drivers/pci/pci.c        | 101 ++++++++++-------------------------------------
 include/asm-generic/io.h |   2 +-
 include/linux/pci.h      |   3 +-
 5 files changed, 32 insertions(+), 87 deletions(-)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 919be0a..4d8cc24 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -730,7 +730,8 @@ static void acpi_pci_root_validate_resources(struct device *dev,
 	}
 }
 
-static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
+static void acpi_pci_root_remap_iospace(struct fwnode_handle *fwnode,
+			struct resource_entry *entry)
 {
 #ifdef PCI_IOBASE
 	struct resource *res = entry->res;
@@ -739,7 +740,7 @@ static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
 	resource_size_t length = resource_size(res);
 	unsigned long port;
 
-	if (pci_register_io_range(cpu_addr, length))
+	if (pci_register_io_range(fwnode, cpu_addr, length))
 		goto err;
 
 	port = pci_address_to_pio(cpu_addr);
@@ -781,7 +782,8 @@ int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
 	else {
 		resource_list_for_each_entry_safe(entry, tmp, list) {
 			if (entry->res->flags & IORESOURCE_IO)
-				acpi_pci_root_remap_iospace(entry);
+				acpi_pci_root_remap_iospace(&device->fwnode,
+						entry);
 
 			if (entry->res->flags & IORESOURCE_DISABLED)
 				resource_list_destroy_entry(entry);
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 72914cd..34a55e8 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -2,8 +2,10 @@
 #define pr_fmt(fmt)	"OF: " fmt
 
 #include <linux/device.h>
+#include <linux/fwnode.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
+#include <linux/logic_pio.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/pci.h>
@@ -323,7 +325,8 @@ int of_pci_range_to_resource(struct of_pci_range *range,
 
 	if (res->flags & IORESOURCE_IO) {
 		unsigned long port;
-		err = pci_register_io_range(range->cpu_addr, range->size);
+		err = pci_register_io_range(&np->fwnode, range->cpu_addr,
+				range->size);
 		if (err)
 			goto invalid_range;
 		port = pci_address_to_pio(range->cpu_addr);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index b01bd5b..c9fe12b 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -21,6 +21,7 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/log2.h>
+#include <linux/logic_pio.h>
 #include <linux/pci-aspm.h>
 #include <linux/pm_wakeup.h>
 #include <linux/interrupt.h>
@@ -3241,68 +3242,34 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
 }
 EXPORT_SYMBOL(pci_request_regions_exclusive);
 
-#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)
+int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
+			resource_size_t	size)
 {
-	int err = 0;
-
+	int ret = 0;
 #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) {
-			/* range already registered, bail out */
-			goto end_register;
-		}
-		allocated_size += range->size;
-	}
-
-	/* 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) {
-			err = -E2BIG;
-			goto end_register;
-		}
-
-		size = SZ_64K;
-		pr_warn("Requested IO range too big, new size set to 64K\n");
-	}
+	struct logic_pio_hwaddr *range;
 
-	/* add the range to the list */
-	range = kzalloc(sizeof(*range), GFP_ATOMIC);
-	if (!range) {
-		err = -ENOMEM;
-		goto end_register;
-	}
+	if (!size || addr + size < addr)
+		return -EINVAL;
 
-	range->start = addr;
+	range = kzalloc(sizeof(*range), GFP_KERNEL);
+	if (!range)
+		return -ENOMEM;
+	range->fwnode = fwnode;
 	range->size = size;
+	range->hw_start = addr;
+	range->flags = PIO_CPU_MMIO;
 
-	list_add_tail(&range->list, &io_range_list);
-
-end_register:
-	spin_unlock(&io_range_lock);
+	ret = logic_pio_register_range(range);
+	if (ret)
+		kfree(range);
 #endif
 
-	return err;
+	return ret;
 }
 
 phys_addr_t pci_pio_to_address(unsigned long pio)
@@ -3310,21 +3277,10 @@ 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)
+	if (pio >= MMIO_UPPER_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);
+	address = logic_pio_to_hwaddr(pio);
 #endif
 
 	return address;
@@ -3333,25 +3289,8 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
 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 = address - res->start + offset;
-			break;
-		}
-		offset += res->size;
-	}
-	spin_unlock(&io_range_lock);
-
-	return addr;
+	return logic_pio_trans_cpuaddr(address);
 #else
-	if (address > IO_SPACE_LIMIT)
-		return (unsigned long)-1;
-
 	return (unsigned long) address;
 #endif
 }
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index f7fbec3..41ecc09 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -949,7 +949,7 @@ static inline void iounmap(void __iomem *addr)
 #define ioport_map ioport_map
 static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
 {
-	return PCI_IOBASE + (port & IO_SPACE_LIMIT);
+	return PCI_IOBASE + (port & MMIO_UPPER_LIMIT);
 }
 #endif
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 33c2b0b..e420d03 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1188,7 +1188,8 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
 			void *alignf_data);
 
 
-int pci_register_io_range(phys_addr_t addr, resource_size_t size);
+int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
+			resource_size_t size);
 unsigned long pci_address_to_pio(phys_addr_t addr);
 phys_addr_t pci_pio_to_address(unsigned long pio);
 int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1651648 — Re: [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts

FromBjorn Helgaas <helgaas@kernel.org>
Date2017-05-27 03:30 +0200
SubjectRe: [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts
Message-ID<tLyIk-4Vw-97@gated-at.bofh.it>
In reply to#1650419
On Thu, May 25, 2017 at 12:37:23PM +0100, Gabriele Paoloni wrote:
> From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> 
> After introducing the new generic I/O space management(LOGIC_IO), the
> original PCI MMIO relevant helpers need to be updated based on the new
> interfaces defined in LOGIC_IO.
> This patch adapts the corresponding code to match the changes introduced
> by LOGIC_IO.
> 
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>        #earlier draft

Not sure how you plan to merge this, but here's my ack:

Acked-by: Bjorn Helgaas <bhelgaas@google.com>

If you split this as suggested below, add my ack to all three patches.

> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index b01bd5b..c9fe12b 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
>...

> -int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
> +int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
> +			resource_size_t	size)

It's trivial and nit-picky, but I would do the __weak removal in its
own patch.  It's obviously fine because there's only one
implementation, but it's unrelated to the main point of this patch.

I would split the signature change (fwnode addition) to a separate
patch, too, just to make the actual change more obvious, especially
since that's the only part that crosses subsystems (ACPI, PCI, OF).

>  {
> -	int err = 0;
> -
> +	int ret = 0;
>  #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) {
> -			/* range already registered, bail out */
> -			goto end_register;
> -		}
> -		allocated_size += range->size;
> -	}
> -
> -	/* 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) {
> -			err = -E2BIG;
> -			goto end_register;
> -		}
> -
> -		size = SZ_64K;
> -		pr_warn("Requested IO range too big, new size set to 64K\n");
> -	}
> +	struct logic_pio_hwaddr *range;
>  
> -	/* add the range to the list */
> -	range = kzalloc(sizeof(*range), GFP_ATOMIC);
> -	if (!range) {
> -		err = -ENOMEM;
> -		goto end_register;
> -	}
> +	if (!size || addr + size < addr)
> +		return -EINVAL;
>  
> -	range->start = addr;
> +	range = kzalloc(sizeof(*range), GFP_KERNEL);
> +	if (!range)
> +		return -ENOMEM;

Add a blank line here.

> +	range->fwnode = fwnode;
>  	range->size = size;
> +	range->hw_start = addr;
> +	range->flags = PIO_CPU_MMIO;
>  
> -	list_add_tail(&range->list, &io_range_list);
> -
> -end_register:
> -	spin_unlock(&io_range_lock);
> +	ret = logic_pio_register_range(range);
> +	if (ret)
> +		kfree(range);
>  #endif
>  
> -	return err;
> +	return ret;
>  }

[toc] | [prev] | [next] | [standalone]


#1652927 — RE: [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts

FromGabriele Paoloni <gabriele.paoloni@huawei.com>
Date2017-05-30 10:20 +0200
SubjectRE: [PATCH v9 2/7] PCI: Apply the new generic I/O management on PCI IO hosts
Message-ID<tMKxI-4OJ-5@gated-at.bofh.it>
In reply to#1651648
Hi Bjorn

> -----Original Message-----
> From: Bjorn Helgaas [mailto:helgaas@kernel.org]
> Sent: 26 May 2017 22:20
> To: Gabriele Paoloni
> Cc: catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> frowand.list@gmail.com; bhelgaas@google.com; rafael@kernel.org;
> arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> lorenzo.pieralisi@arm.com; mark.rutland@arm.com; minyard@acm.org;
> benh@kernel.crashing.org; John Garry; linux-kernel@vger.kernel.org;
> xuwei (O); Linuxarm; linux-acpi@vger.kernel.org; zhichang.yuan; linux-
> pci@vger.kernel.org; olof@lixom.net; brian.starkey@arm.com
> Subject: Re: [PATCH v9 2/7] PCI: Apply the new generic I/O management
> on PCI IO hosts
> 
> On Thu, May 25, 2017 at 12:37:23PM +0100, Gabriele Paoloni wrote:
> > From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
> >
> > After introducing the new generic I/O space management(LOGIC_IO), the
> > original PCI MMIO relevant helpers need to be updated based on the
> new
> > interfaces defined in LOGIC_IO.
> > This patch adapts the corresponding code to match the changes
> introduced
> > by LOGIC_IO.
> >
> > Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>        #earlier draft
> 
> Not sure how you plan to merge this, but here's my ack:
> 
> Acked-by: Bjorn Helgaas <bhelgaas@google.com>

Many thanks for your Ack :)

Maybe Arnd can take the whole patchset (or just the lib framework + DT part
leaving the ACPI part to Lorenzo)....?

> 
> If you split this as suggested below, add my ack to all three patches.

Sure I will

> 
> > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > index b01bd5b..c9fe12b 100644
> > --- a/drivers/pci/pci.c
> > +++ b/drivers/pci/pci.c
> >...
> 
> > -int __weak pci_register_io_range(phys_addr_t addr, resource_size_t
> size)
> > +int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t
> addr,
> > +			resource_size_t	size)
> 
> It's trivial and nit-picky, but I would do the __weak removal in its
> own patch.  It's obviously fine because there's only one
> implementation, but it's unrelated to the main point of this patch.

Agreed

> 
> I would split the signature change (fwnode addition) to a separate
> patch, too, just to make the actual change more obvious, especially
> since that's the only part that crosses subsystems (ACPI, PCI, OF).

Agreed too

> 
> >  {
> > -	int err = 0;
> > -
> > +	int ret = 0;
> >  #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) {
> > -			/* range already registered, bail out */
> > -			goto end_register;
> > -		}
> > -		allocated_size += range->size;
> > -	}
> > -
> > -	/* 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) {
> > -			err = -E2BIG;
> > -			goto end_register;
> > -		}
> > -
> > -		size = SZ_64K;
> > -		pr_warn("Requested IO range too big, new size set to
> 64K\n");
> > -	}
> > +	struct logic_pio_hwaddr *range;
> >
> > -	/* add the range to the list */
> > -	range = kzalloc(sizeof(*range), GFP_ATOMIC);
> > -	if (!range) {
> > -		err = -ENOMEM;
> > -		goto end_register;
> > -	}
> > +	if (!size || addr + size < addr)
> > +		return -EINVAL;
> >
> > -	range->start = addr;
> > +	range = kzalloc(sizeof(*range), GFP_KERNEL);
> > +	if (!range)
> > +		return -ENOMEM;
> 
> Add a blank line here.

Yep I will

Cheers
Gab

> 
> > +	range->fwnode = fwnode;
> >  	range->size = size;
> > +	range->hw_start = addr;
> > +	range->flags = PIO_CPU_MMIO;
> >
> > -	list_add_tail(&range->list, &io_range_list);
> > -
> > -end_register:
> > -	spin_unlock(&io_range_lock);
> > +	ret = logic_pio_register_range(range);
> > +	if (ret)
> > +		kfree(range);
> >  #endif
> >
> > -	return err;
> > +	return ret;
> >  }

[toc] | [prev] | [next] | [standalone]


#1650422 — [PATCH v9 3/7] OF: Add missing I/O range exception for indirect-IO devices

FromGabriele Paoloni <gabriele.paoloni@huawei.com>
Date2017-05-25 13:50 +0200
Subject[PATCH v9 3/7] OF: Add missing I/O range exception for indirect-IO devices
Message-ID<tKZrd-7Fs-39@gated-at.bofh.it>
In reply to#1650414
From: "zhichang.yuan" <yuanzhichang@hisilicon.com>

There are some special ISA/LPC devices that work on a specific I/O range
where it is not correct to specify a 'ranges' property in DTS parent node
as cpu addresses translated from DTS node are only for memory space on some
architectures, such as Arm64. Without the parent 'ranges' property, current
of_translate_address() return an error.
Here we add special handlings for this case.
During the OF address translation, some checkings will be perfromed to
identify whether the device node is registered as indirect-IO. If yes, the
I/O translation will be done in a different way from that one of PCI MMIO.
In this way, the I/O 'reg' property of the special ISA/LPC devices will be
parsed correctly.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>    #earlier draft
Acked-by: Rob Herring <robh@kernel.org>
---
 drivers/of/address.c | 90 ++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 74 insertions(+), 16 deletions(-)

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 34a55e8..c51de70 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -552,9 +552,14 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
  * that translation is impossible (that is we are not dealing with a value
  * that can be mapped to a cpu physical address). This is not really specified
  * that way, but this is traditionally the way IBM at least do things
+ *
+ * Whenever the translation fails, the *host pointer will be set to the
+ * device that had registered logical PIO mapping, and the return code is
+ * relative to that node.
  */
 static u64 __of_translate_address(struct device_node *dev,
-				  const __be32 *in_addr, const char *rprop)
+				  const __be32 *in_addr, const char *rprop,
+				  struct device_node **host)
 {
 	struct device_node *parent = NULL;
 	struct of_bus *bus, *pbus;
@@ -567,6 +572,7 @@ static u64 __of_translate_address(struct device_node *dev,
 	/* Increase refcount at current level */
 	of_node_get(dev);
 
+	*host = NULL;
 	/* Get parent & match bus type */
 	parent = of_get_parent(dev);
 	if (parent == NULL)
@@ -587,6 +593,8 @@ static u64 __of_translate_address(struct device_node *dev,
 
 	/* Translate */
 	for (;;) {
+		struct logic_pio_hwaddr *iorange;
+
 		/* Switch to parent bus */
 		of_node_put(dev);
 		dev = parent;
@@ -599,6 +607,19 @@ static u64 __of_translate_address(struct device_node *dev,
 			break;
 		}
 
+		/*
+		 * For indirectIO device which has no ranges property, get
+		 * the address from reg directly.
+		 */
+		iorange = find_io_range_by_fwnode(&dev->fwnode);
+		if (iorange && (iorange->flags != PIO_CPU_MMIO)) {
+			result = of_read_number(addr + 1, na - 1);
+			pr_debug("indirectIO matched(%s) 0x%llx\n",
+					of_node_full_name(dev), result);
+			*host = of_node_get(dev);
+			break;
+		}
+
 		/* Get new parent bus and counts */
 		pbus = of_match_bus(parent);
 		pbus->count_cells(dev, &pna, &pns);
@@ -631,13 +652,32 @@ static u64 __of_translate_address(struct device_node *dev,
 
 u64 of_translate_address(struct device_node *dev, const __be32 *in_addr)
 {
-	return __of_translate_address(dev, in_addr, "ranges");
+	struct device_node *host;
+	u64 ret;
+
+	ret =  __of_translate_address(dev, in_addr, "ranges", &host);
+	if (host) {
+		of_node_put(host);
+		return OF_BAD_ADDR;
+	}
+
+	return ret;
 }
 EXPORT_SYMBOL(of_translate_address);
 
 u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr)
 {
-	return __of_translate_address(dev, in_addr, "dma-ranges");
+	struct device_node *host;
+	u64 ret;
+
+	ret = __of_translate_address(dev, in_addr, "dma-ranges", &host);
+
+	if (host) {
+		of_node_put(host);
+		return OF_BAD_ADDR;
+	}
+
+	return ret;
 }
 EXPORT_SYMBOL(of_translate_dma_address);
 
@@ -679,29 +719,47 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
 }
 EXPORT_SYMBOL(of_get_address);
 
+static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr)
+{
+	u64 taddr;
+	unsigned long port;
+	struct device_node *host;
+
+	taddr = __of_translate_address(dev, in_addr, "ranges", &host);
+	if (host) {
+		/* host specific port access */
+		port = logic_pio_trans_hwaddr(&host->fwnode, taddr);
+		of_node_put(host);
+	} else {
+		/* memory mapped I/O range */
+		port = pci_address_to_pio(taddr);
+	}
+
+	if (port == (unsigned long)-1)
+		return OF_BAD_ADDR;
+
+	return port;
+}
+
 static int __of_address_to_resource(struct device_node *dev,
 		const __be32 *addrp, u64 size, unsigned int flags,
 		const char *name, struct resource *r)
 {
 	u64 taddr;
 
-	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
+	if (flags & IORESOURCE_MEM)
+		taddr = of_translate_address(dev, addrp);
+	else if (flags & IORESOURCE_IO)
+		taddr = of_translate_ioport(dev, addrp);
+	else
 		return -EINVAL;
-	taddr = of_translate_address(dev, addrp);
+
 	if (taddr == OF_BAD_ADDR)
 		return -EINVAL;
 	memset(r, 0, sizeof(struct resource));
-	if (flags & IORESOURCE_IO) {
-		unsigned long port;
-		port = pci_address_to_pio(taddr);
-		if (port == (unsigned long)-1)
-			return -EINVAL;
-		r->start = port;
-		r->end = port + size - 1;
-	} else {
-		r->start = taddr;
-		r->end = taddr + size - 1;
-	}
+
+	r->start = taddr;
+	r->end = taddr + size - 1;
 	r->flags = flags;
 	r->name = name ? name : dev->full_name;
 
-- 
2.7.4

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web