All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V5 0/3] ARM64 LPC: legacy ISA I/O support
@ 2016-11-08  3:47 ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-08  3:47 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, bhelgaas, mark.rutland,
	olof, arnd, linux-arm-kernel
  Cc: lorenzo.pieralisi, linux-kernel, linuxarm, devicetree, linux-pci,
	linux-serial, minyard, benh, liviu.dudau, zourongrong,
	john.garry, gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

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

When master accesses those periperals beneath the Hip06 LPC, a specific LPC
driver is needed to make LPC host generate the standard LPC I/O cycles with
the target periperals'I/O port addresses. But on curent arm64 world, there is
no real I/O accesses. All the I/O operations through in/out pair are based on
MMIO which is not satisfied the I/O mechanism on Hip06 LPC.
To solve this issue and keep the relevant existing peripherals' driver
unchanged, this patch set redefines the in/out pair to support both the IO
operations for Hip06 LPC and the original MMIO. The way specific to Hip06 is
named as indirect-IO in this patchset.

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;

Signed-off-by: Zhichang Yuan <yuanzhichang@hisilicon.com>

zhichang.yuan (3):
  ARM64 LPC: Indirect ISA port IO introduced
  ARM64 LPC: Add missing range exception for special ISA
  ARM64 LPC: LPC driver implementation on Hip06

 .../arm/hisilicon/hisilicon-low-pin-count.txt      |  31 ++
 MAINTAINERS                                        |   8 +
 arch/arm64/Kconfig                                 |   6 +
 arch/arm64/include/asm/extio.h                     |  94 ++++
 arch/arm64/include/asm/io.h                        |  35 ++
 arch/arm64/kernel/Makefile                         |   1 +
 arch/arm64/kernel/extio.c                          |  52 +++
 drivers/bus/Kconfig                                |   8 +
 drivers/bus/Makefile                               |   1 +
 drivers/bus/hisi_lpc.c                             | 501 +++++++++++++++++++++
 drivers/of/address.c                               |  56 ++-
 drivers/pci/pci.c                                  |   6 +-
 include/linux/of_address.h                         |  17 +
 include/linux/pci.h                                |   8 +
 14 files changed, 820 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
 create mode 100644 arch/arm64/include/asm/extio.h
 create mode 100644 arch/arm64/kernel/extio.c
 create mode 100644 drivers/bus/hisi_lpc.c

-- 
1.9.1

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

* [PATCH V5 0/3] ARM64 LPC: legacy ISA I/O support
@ 2016-11-08  3:47 ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-08  3:47 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, bhelgaas, mark.rutland,
	olof, arnd, linux-arm-kernel
  Cc: lorenzo.pieralisi, linux-kernel, linuxarm, devicetree, linux-pci,
	linux-serial, minyard, benh, liviu.dudau, zourongrong,
	john.garry, gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

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

When master accesses those periperals beneath the Hip06 LPC, a specific LPC
driver is needed to make LPC host generate the standard LPC I/O cycles with
the target periperals'I/O port addresses. But on curent arm64 world, there is
no real I/O accesses. All the I/O operations through in/out pair are based on
MMIO which is not satisfied the I/O mechanism on Hip06 LPC.
To solve this issue and keep the relevant existing peripherals' driver
unchanged, this patch set redefines the in/out pair to support both the IO
operations for Hip06 LPC and the original MMIO. The way specific to Hip06 is
named as indirect-IO in this patchset.

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;

Signed-off-by: Zhichang Yuan <yuanzhichang@hisilicon.com>

zhichang.yuan (3):
  ARM64 LPC: Indirect ISA port IO introduced
  ARM64 LPC: Add missing range exception for special ISA
  ARM64 LPC: LPC driver implementation on Hip06

 .../arm/hisilicon/hisilicon-low-pin-count.txt      |  31 ++
 MAINTAINERS                                        |   8 +
 arch/arm64/Kconfig                                 |   6 +
 arch/arm64/include/asm/extio.h                     |  94 ++++
 arch/arm64/include/asm/io.h                        |  35 ++
 arch/arm64/kernel/Makefile                         |   1 +
 arch/arm64/kernel/extio.c                          |  52 +++
 drivers/bus/Kconfig                                |   8 +
 drivers/bus/Makefile                               |   1 +
 drivers/bus/hisi_lpc.c                             | 501 +++++++++++++++++++++
 drivers/of/address.c                               |  56 ++-
 drivers/pci/pci.c                                  |   6 +-
 include/linux/of_address.h                         |  17 +
 include/linux/pci.h                                |   8 +
 14 files changed, 820 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
 create mode 100644 arch/arm64/include/asm/extio.h
 create mode 100644 arch/arm64/kernel/extio.c
 create mode 100644 drivers/bus/hisi_lpc.c

-- 
1.9.1

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

* [PATCH V5 0/3] ARM64 LPC: legacy ISA I/O support
@ 2016-11-08  3:47 ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-08  3:47 UTC (permalink / raw)
  To: linux-arm-kernel

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

When master accesses those periperals beneath the Hip06 LPC, a specific LPC
driver is needed to make LPC host generate the standard LPC I/O cycles with
the target periperals'I/O port addresses. But on curent arm64 world, there is
no real I/O accesses. All the I/O operations through in/out pair are based on
MMIO which is not satisfied the I/O mechanism on Hip06 LPC.
To solve this issue and keep the relevant existing peripherals' driver
unchanged, this patch set redefines the in/out pair to support both the IO
operations for Hip06 LPC and the original MMIO. The way specific to Hip06 is
named as indirect-IO in this patchset.

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;

Signed-off-by: Zhichang Yuan <yuanzhichang@hisilicon.com>

zhichang.yuan (3):
  ARM64 LPC: Indirect ISA port IO introduced
  ARM64 LPC: Add missing range exception for special ISA
  ARM64 LPC: LPC driver implementation on Hip06

 .../arm/hisilicon/hisilicon-low-pin-count.txt      |  31 ++
 MAINTAINERS                                        |   8 +
 arch/arm64/Kconfig                                 |   6 +
 arch/arm64/include/asm/extio.h                     |  94 ++++
 arch/arm64/include/asm/io.h                        |  35 ++
 arch/arm64/kernel/Makefile                         |   1 +
 arch/arm64/kernel/extio.c                          |  52 +++
 drivers/bus/Kconfig                                |   8 +
 drivers/bus/Makefile                               |   1 +
 drivers/bus/hisi_lpc.c                             | 501 +++++++++++++++++++++
 drivers/of/address.c                               |  56 ++-
 drivers/pci/pci.c                                  |   6 +-
 include/linux/of_address.h                         |  17 +
 include/linux/pci.h                                |   8 +
 14 files changed, 820 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
 create mode 100644 arch/arm64/include/asm/extio.h
 create mode 100644 arch/arm64/kernel/extio.c
 create mode 100644 drivers/bus/hisi_lpc.c

-- 
1.9.1

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08  3:47   ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-08  3:47 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, bhelgaas, mark.rutland,
	olof, arnd, linux-arm-kernel
  Cc: lorenzo.pieralisi, linux-kernel, linuxarm, devicetree, linux-pci,
	linux-serial, minyard, benh, liviu.dudau, zourongrong,
	john.garry, gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

For arm64, there is no I/O space as other architectural platforms, such as
X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
such as Hip06, when accessing some legacy ISA devices connected to LPC, those
known port addresses are used to control the corresponding target devices, for
example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
normal MMIO mode in using.

To drive these devices, this patch introduces a method named indirect-IO.
In this method the in/out pair in arch/arm64/include/asm/io.h will be
redefined. When upper layer drivers call in/out with those known legacy port
addresses to access the peripherals, the hooking functions corrresponding to
those target peripherals will be called. Through this way, those upper layer
drivers which depend on in/out can run on Hip06 without any changes.

Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 arch/arm64/Kconfig             |  6 +++
 arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
 arch/arm64/include/asm/io.h    | 29 +++++++++++++
 arch/arm64/kernel/Makefile     |  1 +
 arch/arm64/kernel/extio.c      | 27 ++++++++++++
 5 files changed, 157 insertions(+)
 create mode 100644 arch/arm64/include/asm/extio.h
 create mode 100644 arch/arm64/kernel/extio.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 969ef88..b44070b 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
 config ARCH_MMAP_RND_COMPAT_BITS_MAX
        default 16
 
+config ARM64_INDIRECT_PIO
+	bool "access peripherals with legacy I/O port"
+	help
+	  Support special accessors for ISA I/O devices. This is needed for
+	  SoCs that do not support standard read/write for the ISA range.
+
 config NO_IOPORT_MAP
 	def_bool y if !PCI
 
diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
new file mode 100644
index 0000000..6ae0787
--- /dev/null
+++ b/arch/arm64/include/asm/extio.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LINUX_EXTIO_H
+#define __LINUX_EXTIO_H
+
+struct extio_ops {
+	unsigned long start;/* inclusive, sys io addr */
+	unsigned long end;/* inclusive, sys io addr */
+
+	u64 (*pfin)(void *devobj, unsigned long ptaddr,	size_t dlen);
+	void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
+					size_t dlen);
+	u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
+				size_t dlen, unsigned int count);
+	void (*pfouts)(void *devobj, unsigned long ptaddr,
+				const void *outbuf, size_t dlen,
+				unsigned int count);
+	void *devpara;
+};
+
+extern struct extio_ops *arm64_extio_ops;
+
+#define DECLARE_EXTIO(bw, type)						\
+extern type in##bw(unsigned long addr);					\
+extern void out##bw(type value, unsigned long addr);			\
+extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
+extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
+
+#define BUILD_EXTIO(bw, type)						\
+type in##bw(unsigned long addr)						\
+{									\
+	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
+			arm64_extio_ops->end < addr)			\
+		return read##bw(PCI_IOBASE + addr);			\
+	return arm64_extio_ops->pfin ?					\
+		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
+			addr, sizeof(type)) : -1;			\
+}									\
+									\
+void out##bw(type value, unsigned long addr)				\
+{									\
+	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
+			arm64_extio_ops->end < addr)			\
+		write##bw(value, PCI_IOBASE + addr);			\
+	else								\
+		if (arm64_extio_ops->pfout)				\
+			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
+				addr, value, sizeof(type));		\
+}									\
+									\
+void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
+{									\
+	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
+			arm64_extio_ops->end < addr)			\
+		reads##bw(PCI_IOBASE + addr, buffer, count);		\
+	else								\
+		if (arm64_extio_ops->pfins)				\
+			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
+				addr, buffer, sizeof(type), count);	\
+}									\
+									\
+void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
+{									\
+	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
+			arm64_extio_ops->end < addr)			\
+		writes##bw(PCI_IOBASE + addr, buffer, count);		\
+	else								\
+		if (arm64_extio_ops->pfouts)				\
+			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
+				addr, buffer, sizeof(type), count);	\
+}
+
+static inline void arm64_set_extops(struct extio_ops *ops)
+{
+	if (ops)
+		WRITE_ONCE(arm64_extio_ops, ops);
+}
+
+#endif /* __LINUX_EXTIO_H*/
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 0bba427..136735d 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -31,6 +31,7 @@
 #include <asm/early_ioremap.h>
 #include <asm/alternative.h>
 #include <asm/cpufeature.h>
+#include <asm/extio.h>
 
 #include <xen/xen.h>
 
@@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
 #define IO_SPACE_LIMIT		(PCI_IO_SIZE - 1)
 #define PCI_IOBASE		((void __iomem *)PCI_IO_START)
 
+
+/*
+ * redefine the in(s)b/out(s)b for indirect-IO.
+ */
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+#define inb inb
+#define outb outb
+#define insb insb
+#define outsb outsb
+/* external declaration */
+DECLARE_EXTIO(b, u8)
+
+#define inw inw
+#define outw outw
+#define insw insw
+#define outsw outsw
+
+DECLARE_EXTIO(w, u16)
+
+#define inl inl
+#define outl outl
+#define insl insl
+#define outsl outsl
+
+DECLARE_EXTIO(l, u32)
+#endif
+
+
 /*
  * String version of I/O memory access operations.
  */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 7d66bba..60e0482 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o entry32.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
+arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO)	+= extio.o
 arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
 arm64-obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o perf_callchain.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
new file mode 100644
index 0000000..647b3fa
--- /dev/null
+++ b/arch/arm64/kernel/extio.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/io.h>
+
+struct extio_ops *arm64_extio_ops;
+
+
+BUILD_EXTIO(b, u8)
+
+BUILD_EXTIO(w, u16)
+
+BUILD_EXTIO(l, u32)
-- 
1.9.1

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08  3:47   ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-08  3:47 UTC (permalink / raw)
  To: catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, bhelgaas-hpIqsD4AKlfQT0dZR+AlfA,
	mark.rutland-5wv7dgnIgG8, olof-nZhT3qVonbNeoWH0uzbU5w,
	arnd-r2nGTMty4D4,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: lorenzo.pieralisi-5wv7dgnIgG8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linuxarm-hv44wF8Li93QT0dZR+AlfA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, minyard-HInyCGIudOg,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, liviu.dudau-5wv7dgnIgG8,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
	john.garry-hv44wF8Li93QT0dZR+AlfA,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w, kantyzc-9Onoh4P/yGk,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q, zhichang.yuan

For arm64, there is no I/O space as other architectural platforms, such as
X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
such as Hip06, when accessing some legacy ISA devices connected to LPC, those
known port addresses are used to control the corresponding target devices, for
example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
normal MMIO mode in using.

To drive these devices, this patch introduces a method named indirect-IO.
In this method the in/out pair in arch/arm64/include/asm/io.h will be
redefined. When upper layer drivers call in/out with those known legacy port
addresses to access the peripherals, the hooking functions corrresponding to
those target peripherals will be called. Through this way, those upper layer
drivers which depend on in/out can run on Hip06 without any changes.

Cc: Catalin Marinas <catalin.marinas-5wv7dgnIgG8@public.gmane.org>
Cc: Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org>
Signed-off-by: zhichang.yuan <yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
---
 arch/arm64/Kconfig             |  6 +++
 arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
 arch/arm64/include/asm/io.h    | 29 +++++++++++++
 arch/arm64/kernel/Makefile     |  1 +
 arch/arm64/kernel/extio.c      | 27 ++++++++++++
 5 files changed, 157 insertions(+)
 create mode 100644 arch/arm64/include/asm/extio.h
 create mode 100644 arch/arm64/kernel/extio.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 969ef88..b44070b 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
 config ARCH_MMAP_RND_COMPAT_BITS_MAX
        default 16
 
+config ARM64_INDIRECT_PIO
+	bool "access peripherals with legacy I/O port"
+	help
+	  Support special accessors for ISA I/O devices. This is needed for
+	  SoCs that do not support standard read/write for the ISA range.
+
 config NO_IOPORT_MAP
 	def_bool y if !PCI
 
diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
new file mode 100644
index 0000000..6ae0787
--- /dev/null
+++ b/arch/arm64/include/asm/extio.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LINUX_EXTIO_H
+#define __LINUX_EXTIO_H
+
+struct extio_ops {
+	unsigned long start;/* inclusive, sys io addr */
+	unsigned long end;/* inclusive, sys io addr */
+
+	u64 (*pfin)(void *devobj, unsigned long ptaddr,	size_t dlen);
+	void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
+					size_t dlen);
+	u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
+				size_t dlen, unsigned int count);
+	void (*pfouts)(void *devobj, unsigned long ptaddr,
+				const void *outbuf, size_t dlen,
+				unsigned int count);
+	void *devpara;
+};
+
+extern struct extio_ops *arm64_extio_ops;
+
+#define DECLARE_EXTIO(bw, type)						\
+extern type in##bw(unsigned long addr);					\
+extern void out##bw(type value, unsigned long addr);			\
+extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
+extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
+
+#define BUILD_EXTIO(bw, type)						\
+type in##bw(unsigned long addr)						\
+{									\
+	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
+			arm64_extio_ops->end < addr)			\
+		return read##bw(PCI_IOBASE + addr);			\
+	return arm64_extio_ops->pfin ?					\
+		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
+			addr, sizeof(type)) : -1;			\
+}									\
+									\
+void out##bw(type value, unsigned long addr)				\
+{									\
+	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
+			arm64_extio_ops->end < addr)			\
+		write##bw(value, PCI_IOBASE + addr);			\
+	else								\
+		if (arm64_extio_ops->pfout)				\
+			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
+				addr, value, sizeof(type));		\
+}									\
+									\
+void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
+{									\
+	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
+			arm64_extio_ops->end < addr)			\
+		reads##bw(PCI_IOBASE + addr, buffer, count);		\
+	else								\
+		if (arm64_extio_ops->pfins)				\
+			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
+				addr, buffer, sizeof(type), count);	\
+}									\
+									\
+void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
+{									\
+	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
+			arm64_extio_ops->end < addr)			\
+		writes##bw(PCI_IOBASE + addr, buffer, count);		\
+	else								\
+		if (arm64_extio_ops->pfouts)				\
+			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
+				addr, buffer, sizeof(type), count);	\
+}
+
+static inline void arm64_set_extops(struct extio_ops *ops)
+{
+	if (ops)
+		WRITE_ONCE(arm64_extio_ops, ops);
+}
+
+#endif /* __LINUX_EXTIO_H*/
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 0bba427..136735d 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -31,6 +31,7 @@
 #include <asm/early_ioremap.h>
 #include <asm/alternative.h>
 #include <asm/cpufeature.h>
+#include <asm/extio.h>
 
 #include <xen/xen.h>
 
@@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
 #define IO_SPACE_LIMIT		(PCI_IO_SIZE - 1)
 #define PCI_IOBASE		((void __iomem *)PCI_IO_START)
 
+
+/*
+ * redefine the in(s)b/out(s)b for indirect-IO.
+ */
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+#define inb inb
+#define outb outb
+#define insb insb
+#define outsb outsb
+/* external declaration */
+DECLARE_EXTIO(b, u8)
+
+#define inw inw
+#define outw outw
+#define insw insw
+#define outsw outsw
+
+DECLARE_EXTIO(w, u16)
+
+#define inl inl
+#define outl outl
+#define insl insl
+#define outsl outsl
+
+DECLARE_EXTIO(l, u32)
+#endif
+
+
 /*
  * String version of I/O memory access operations.
  */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 7d66bba..60e0482 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o entry32.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
+arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO)	+= extio.o
 arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
 arm64-obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o perf_callchain.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
new file mode 100644
index 0000000..647b3fa
--- /dev/null
+++ b/arch/arm64/kernel/extio.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/io.h>
+
+struct extio_ops *arm64_extio_ops;
+
+
+BUILD_EXTIO(b, u8)
+
+BUILD_EXTIO(w, u16)
+
+BUILD_EXTIO(l, u32)
-- 
1.9.1

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

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08  3:47   ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-08  3:47 UTC (permalink / raw)
  To: linux-arm-kernel

For arm64, there is no I/O space as other architectural platforms, such as
X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
such as Hip06, when accessing some legacy ISA devices connected to LPC, those
known port addresses are used to control the corresponding target devices, for
example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
normal MMIO mode in using.

To drive these devices, this patch introduces a method named indirect-IO.
In this method the in/out pair in arch/arm64/include/asm/io.h will be
redefined. When upper layer drivers call in/out with those known legacy port
addresses to access the peripherals, the hooking functions corrresponding to
those target peripherals will be called. Through this way, those upper layer
drivers which depend on in/out can run on Hip06 without any changes.

Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 arch/arm64/Kconfig             |  6 +++
 arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
 arch/arm64/include/asm/io.h    | 29 +++++++++++++
 arch/arm64/kernel/Makefile     |  1 +
 arch/arm64/kernel/extio.c      | 27 ++++++++++++
 5 files changed, 157 insertions(+)
 create mode 100644 arch/arm64/include/asm/extio.h
 create mode 100644 arch/arm64/kernel/extio.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 969ef88..b44070b 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
 config ARCH_MMAP_RND_COMPAT_BITS_MAX
        default 16
 
+config ARM64_INDIRECT_PIO
+	bool "access peripherals with legacy I/O port"
+	help
+	  Support special accessors for ISA I/O devices. This is needed for
+	  SoCs that do not support standard read/write for the ISA range.
+
 config NO_IOPORT_MAP
 	def_bool y if !PCI
 
diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
new file mode 100644
index 0000000..6ae0787
--- /dev/null
+++ b/arch/arm64/include/asm/extio.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LINUX_EXTIO_H
+#define __LINUX_EXTIO_H
+
+struct extio_ops {
+	unsigned long start;/* inclusive, sys io addr */
+	unsigned long end;/* inclusive, sys io addr */
+
+	u64 (*pfin)(void *devobj, unsigned long ptaddr,	size_t dlen);
+	void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
+					size_t dlen);
+	u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
+				size_t dlen, unsigned int count);
+	void (*pfouts)(void *devobj, unsigned long ptaddr,
+				const void *outbuf, size_t dlen,
+				unsigned int count);
+	void *devpara;
+};
+
+extern struct extio_ops *arm64_extio_ops;
+
+#define DECLARE_EXTIO(bw, type)						\
+extern type in##bw(unsigned long addr);					\
+extern void out##bw(type value, unsigned long addr);			\
+extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
+extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
+
+#define BUILD_EXTIO(bw, type)						\
+type in##bw(unsigned long addr)						\
+{									\
+	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
+			arm64_extio_ops->end < addr)			\
+		return read##bw(PCI_IOBASE + addr);			\
+	return arm64_extio_ops->pfin ?					\
+		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
+			addr, sizeof(type)) : -1;			\
+}									\
+									\
+void out##bw(type value, unsigned long addr)				\
+{									\
+	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
+			arm64_extio_ops->end < addr)			\
+		write##bw(value, PCI_IOBASE + addr);			\
+	else								\
+		if (arm64_extio_ops->pfout)				\
+			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
+				addr, value, sizeof(type));		\
+}									\
+									\
+void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
+{									\
+	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
+			arm64_extio_ops->end < addr)			\
+		reads##bw(PCI_IOBASE + addr, buffer, count);		\
+	else								\
+		if (arm64_extio_ops->pfins)				\
+			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
+				addr, buffer, sizeof(type), count);	\
+}									\
+									\
+void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
+{									\
+	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
+			arm64_extio_ops->end < addr)			\
+		writes##bw(PCI_IOBASE + addr, buffer, count);		\
+	else								\
+		if (arm64_extio_ops->pfouts)				\
+			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
+				addr, buffer, sizeof(type), count);	\
+}
+
+static inline void arm64_set_extops(struct extio_ops *ops)
+{
+	if (ops)
+		WRITE_ONCE(arm64_extio_ops, ops);
+}
+
+#endif /* __LINUX_EXTIO_H*/
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 0bba427..136735d 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -31,6 +31,7 @@
 #include <asm/early_ioremap.h>
 #include <asm/alternative.h>
 #include <asm/cpufeature.h>
+#include <asm/extio.h>
 
 #include <xen/xen.h>
 
@@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
 #define IO_SPACE_LIMIT		(PCI_IO_SIZE - 1)
 #define PCI_IOBASE		((void __iomem *)PCI_IO_START)
 
+
+/*
+ * redefine the in(s)b/out(s)b for indirect-IO.
+ */
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+#define inb inb
+#define outb outb
+#define insb insb
+#define outsb outsb
+/* external declaration */
+DECLARE_EXTIO(b, u8)
+
+#define inw inw
+#define outw outw
+#define insw insw
+#define outsw outsw
+
+DECLARE_EXTIO(w, u16)
+
+#define inl inl
+#define outl outl
+#define insl insl
+#define outsl outsl
+
+DECLARE_EXTIO(l, u32)
+#endif
+
+
 /*
  * String version of I/O memory access operations.
  */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 7d66bba..60e0482 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o entry32.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
+arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO)	+= extio.o
 arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
 arm64-obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o perf_callchain.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
new file mode 100644
index 0000000..647b3fa
--- /dev/null
+++ b/arch/arm64/kernel/extio.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/io.h>
+
+struct extio_ops *arm64_extio_ops;
+
+
+BUILD_EXTIO(b, u8)
+
+BUILD_EXTIO(w, u16)
+
+BUILD_EXTIO(l, u32)
-- 
1.9.1

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

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
  2016-11-08  3:47 ` zhichang.yuan
  (?)
@ 2016-11-08  3:47   ` zhichang.yuan
  -1 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-08  3:47 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, bhelgaas, mark.rutland,
	olof, arnd, linux-arm-kernel
  Cc: lorenzo.pieralisi, linux-kernel, linuxarm, devicetree, linux-pci,
	linux-serial, minyard, benh, liviu.dudau, zourongrong,
	john.garry, gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

This patch solves two issues:
1) parse and get the right I/O range from DTS node whose parent does not
define the corresponding ranges property;

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 a fixup function, of_get_isa_indirect_io(). During the OF address
translation, this fixup will be called to check the 'reg' address to be
translating is for those sepcial ISA/LPC devices and get the I/O range
directly from the 'reg' property.

2) eliminate the I/O range conflict risk with PCI/PCIE leagecy I/O device;

The current __of_address_to_resource() always translates the I/O range to PIO.
But this processing is not suitable for our ISA/LPC devices whose I/O range is
not cpu address(Arnd had stressed this in his comments on V2,V3 patch-set).
Here, we bypass the mapping between cpu address and PIO for the special
ISA/LPC devices. But to drive these ISA/LPC devices, a I/O port address below
PCIBIOS_MIN_IO is needed by in*/out*(). Which means there is conflict risk
between I/O range of [0, PCIBIOS_MIN_IO) and PCI/PCIE legacy I/O range of [0,
IO_SPACE_LIMIT).
To avoid the I/O conflict, this patch reserve the I/O range below
PCIBIOS_MIN_IO.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 .../arm/hisilicon/hisilicon-low-pin-count.txt      | 31 ++++++++++++
 arch/arm64/include/asm/io.h                        |  6 +++
 arch/arm64/kernel/extio.c                          | 25 ++++++++++
 drivers/of/address.c                               | 56 +++++++++++++++++++++-
 drivers/pci/pci.c                                  |  6 +--
 include/linux/of_address.h                         | 17 +++++++
 include/linux/pci.h                                |  8 ++++
 7 files changed, 145 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
new file mode 100644
index 0000000..13c8ddd
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
@@ -0,0 +1,31 @@
+Hisilicon Hip06 low-pin-count device
+  Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
+  locate on LPC bus can be accessed direclty. But some SoCs have independent
+  LPC controller, and access the legacy ports by triggering LPC I/O cycles.
+  Hisilicon Hip06 implements this LPC device.
+
+Required properties:
+- compatible: should be "hisilicon,low-pin-count"
+- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
+- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
+- reg: base memory range where the register set of this device is mapped.
+
+Note:
+  The node name before '@' must be "isa" to represent the binding stick to the
+  ISA/EISA binding specification.
+
+Example:
+
+isa@a01b0000 {
+	compatible = "hisilicom,low-pin-count";
+	#address-cells = <2>;
+	#size-cells = <1>;
+	reg = <0x0 0xa01b0000 0x0 0x1000>;
+
+	ipmi0: bt@e4 {
+		compatible = "ipmi-bt";
+		device_type = "ipmi";
+		reg = <0x01 0xe4 0x04>;
+		status = "disabled";
+	};
+};
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 136735d..c26b7cc 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -175,6 +175,12 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
 #define outsl outsl
 
 DECLARE_EXTIO(l, u32)
+
+#define indirect_io_enabled indirect_io_enabled
+extern bool indirect_io_enabled(void);
+
+#define addr_is_indirect_io addr_is_indirect_io
+extern int addr_is_indirect_io(u64 taddr);
 #endif
 
 
diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
index 647b3fa..3d45fa8 100644
--- a/arch/arm64/kernel/extio.c
+++ b/arch/arm64/kernel/extio.c
@@ -19,6 +19,31 @@
 
 struct extio_ops *arm64_extio_ops;
 
+/**
+ * indirect_io_enabled - check whether indirectIO is enabled.
+ *	arm64_extio_ops will be set only when indirectIO mechanism had been
+ *	initialized.
+ *
+ * Returns true when indirectIO is enabled.
+ */
+bool indirect_io_enabled(void)
+{
+	return arm64_extio_ops ? true : false;
+}
+
+/**
+ * addr_is_indirect_io - check whether the input taddr is for indirectIO.
+ * @taddr: the io address to be checked.
+ *
+ * Returns 1 when taddr is in the range; otherwise return 0.
+ */
+int addr_is_indirect_io(u64 taddr)
+{
+	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end < taddr)
+		return 0;
+
+	return 1;
+}
 
 BUILD_EXTIO(b, u8)
 
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 02b2903..cc2a05d 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct device_node *np)
 	return false;
 }
 
+
+/*
+ * of_isa_indirect_io - get the IO address from some isa reg property value.
+ *	For some isa/lpc devices, no ranges property in ancestor node.
+ *	The device addresses are described directly in their regs property.
+ *	This fixup function will be called to get the IO address of isa/lpc
+ *	devices when the normal of_translation failed.
+ *
+ * @parent:	points to the parent dts node;
+ * @bus:		points to the of_bus which can be used to parse address;
+ * @addr:	the address from reg property;
+ * @na:		the address cell counter of @addr;
+ * @presult:	store the address paresed from @addr;
+ *
+ * return 1 when successfully get the I/O address;
+ * 0 will return for some failures.
+ */
+static int of_get_isa_indirect_io(struct device_node *parent,
+				struct of_bus *bus, __be32 *addr,
+				int na, u64 *presult)
+{
+	unsigned int flags;
+	unsigned int rlen;
+
+	/* whether support indirectIO */
+	if (!indirect_io_enabled())
+		return 0;
+
+	if (!of_bus_isa_match(parent))
+		return 0;
+
+	flags = bus->get_flags(addr);
+	if (!(flags & IORESOURCE_IO))
+		return 0;
+
+	/* there is ranges property, apply the normal translation directly. */
+	if (of_get_property(parent, "ranges", &rlen))
+		return 0;
+
+	*presult = of_read_number(addr + 1, na - 1);
+	/* this fixup is only valid for specific I/O range. */
+	return addr_is_indirect_io(*presult);
+}
+
 static int of_translate_one(struct device_node *parent, struct of_bus *bus,
 			    struct of_bus *pbus, __be32 *addr,
 			    int na, int ns, int pna, const char *rprop)
@@ -595,6 +639,15 @@ static u64 __of_translate_address(struct device_node *dev,
 			result = of_read_number(addr, na);
 			break;
 		}
+		/*
+		 * For indirectIO device which has no ranges property, get
+		 * the address from reg directly.
+		 */
+		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
+			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
+				of_node_full_name(dev), result);
+			break;
+		}
 
 		/* Get new parent bus and counts */
 		pbus = of_match_bus(parent);
@@ -688,8 +741,9 @@ static int __of_address_to_resource(struct device_node *dev,
 	if (taddr == OF_BAD_ADDR)
 		return -EINVAL;
 	memset(r, 0, sizeof(struct resource));
-	if (flags & IORESOURCE_IO) {
+	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
 		unsigned long port;
+
 		port = pci_address_to_pio(taddr);
 		if (port == (unsigned long)-1)
 			return -EINVAL;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index ba34907..1a08511 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3263,7 +3263,7 @@ 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;
+	resource_size_t allocated_size = PCIBIOS_MIN_IO;
 
 	/* check if the range hasn't been previously recorded */
 	spin_lock(&io_range_lock);
@@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
 
 #ifdef PCI_IOBASE
 	struct io_range *range;
-	resource_size_t allocated_size = 0;
+	resource_size_t allocated_size = PCIBIOS_MIN_IO;
 
 	if (pio > IO_SPACE_LIMIT)
 		return address;
@@ -3335,7 +3335,7 @@ unsigned long __weak pci_address_to_pio(phys_addr_t address)
 {
 #ifdef PCI_IOBASE
 	struct io_range *res;
-	resource_size_t offset = 0;
+	resource_size_t offset = PCIBIOS_MIN_IO;
 	unsigned long addr = -1;
 
 	spin_lock(&io_range_lock);
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 3786473..deec469 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -24,6 +24,23 @@ struct of_pci_range {
 #define for_each_of_pci_range(parser, range) \
 	for (; of_pci_range_parser_one(parser, range);)
 
+
+#ifndef indirect_io_enabled
+#define indirect_io_enabled indirect_io_enabled
+static inline bool indirect_io_enabled(void)
+{
+	return false;
+}
+#endif
+
+#ifndef addr_is_indirect_io
+#define addr_is_indirect_io addr_is_indirect_io
+static inline int addr_is_indirect_io(u64 taddr)
+{
+	return 0;
+}
+#endif
+
 /* Translate a DMA address from device space to CPU space */
 extern u64 of_translate_dma_address(struct device_node *dev,
 				    const __be32 *in_addr);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 0e49f70..7f6bbb6 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct pci_bus *bus)
 /* provide the legacy pci_dma_* API */
 #include <linux/pci-dma-compat.h>
 
+/*
+ * define this macro here to refrain from compilation error for some
+ * platforms. Please keep this macro at the end of this header file.
+ */
+#ifndef PCIBIOS_MIN_IO
+#define PCIBIOS_MIN_IO		0
+#endif
+
 #endif /* LINUX_PCI_H */
-- 
1.9.1

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

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-08  3:47   ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-08  3:47 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, bhelgaas, mark.rutland,
	olof, arnd, linux-arm-kernel
  Cc: lorenzo.pieralisi, linux-kernel, linuxarm, devicetree, linux-pci,
	linux-serial, minyard, benh, liviu.dudau, zourongrong,
	john.garry, gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

This patch solves two issues:
1) parse and get the right I/O range from DTS node whose parent does not
define the corresponding ranges property;

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 a fixup function, of_get_isa_indirect_io(). During the OF address
translation, this fixup will be called to check the 'reg' address to be
translating is for those sepcial ISA/LPC devices and get the I/O range
directly from the 'reg' property.

2) eliminate the I/O range conflict risk with PCI/PCIE leagecy I/O device;

The current __of_address_to_resource() always translates the I/O range to PIO.
But this processing is not suitable for our ISA/LPC devices whose I/O range is
not cpu address(Arnd had stressed this in his comments on V2,V3 patch-set).
Here, we bypass the mapping between cpu address and PIO for the special
ISA/LPC devices. But to drive these ISA/LPC devices, a I/O port address below
PCIBIOS_MIN_IO is needed by in*/out*(). Which means there is conflict risk
between I/O range of [0, PCIBIOS_MIN_IO) and PCI/PCIE legacy I/O range of [0,
IO_SPACE_LIMIT).
To avoid the I/O conflict, this patch reserve the I/O range below
PCIBIOS_MIN_IO.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 .../arm/hisilicon/hisilicon-low-pin-count.txt      | 31 ++++++++++++
 arch/arm64/include/asm/io.h                        |  6 +++
 arch/arm64/kernel/extio.c                          | 25 ++++++++++
 drivers/of/address.c                               | 56 +++++++++++++++++++++-
 drivers/pci/pci.c                                  |  6 +--
 include/linux/of_address.h                         | 17 +++++++
 include/linux/pci.h                                |  8 ++++
 7 files changed, 145 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
new file mode 100644
index 0000000..13c8ddd
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
@@ -0,0 +1,31 @@
+Hisilicon Hip06 low-pin-count device
+  Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
+  locate on LPC bus can be accessed direclty. But some SoCs have independent
+  LPC controller, and access the legacy ports by triggering LPC I/O cycles.
+  Hisilicon Hip06 implements this LPC device.
+
+Required properties:
+- compatible: should be "hisilicon,low-pin-count"
+- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
+- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
+- reg: base memory range where the register set of this device is mapped.
+
+Note:
+  The node name before '@' must be "isa" to represent the binding stick to the
+  ISA/EISA binding specification.
+
+Example:
+
+isa@a01b0000 {
+	compatible = "hisilicom,low-pin-count";
+	#address-cells = <2>;
+	#size-cells = <1>;
+	reg = <0x0 0xa01b0000 0x0 0x1000>;
+
+	ipmi0: bt@e4 {
+		compatible = "ipmi-bt";
+		device_type = "ipmi";
+		reg = <0x01 0xe4 0x04>;
+		status = "disabled";
+	};
+};
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 136735d..c26b7cc 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -175,6 +175,12 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
 #define outsl outsl
 
 DECLARE_EXTIO(l, u32)
+
+#define indirect_io_enabled indirect_io_enabled
+extern bool indirect_io_enabled(void);
+
+#define addr_is_indirect_io addr_is_indirect_io
+extern int addr_is_indirect_io(u64 taddr);
 #endif
 
 
diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
index 647b3fa..3d45fa8 100644
--- a/arch/arm64/kernel/extio.c
+++ b/arch/arm64/kernel/extio.c
@@ -19,6 +19,31 @@
 
 struct extio_ops *arm64_extio_ops;
 
+/**
+ * indirect_io_enabled - check whether indirectIO is enabled.
+ *	arm64_extio_ops will be set only when indirectIO mechanism had been
+ *	initialized.
+ *
+ * Returns true when indirectIO is enabled.
+ */
+bool indirect_io_enabled(void)
+{
+	return arm64_extio_ops ? true : false;
+}
+
+/**
+ * addr_is_indirect_io - check whether the input taddr is for indirectIO.
+ * @taddr: the io address to be checked.
+ *
+ * Returns 1 when taddr is in the range; otherwise return 0.
+ */
+int addr_is_indirect_io(u64 taddr)
+{
+	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end < taddr)
+		return 0;
+
+	return 1;
+}
 
 BUILD_EXTIO(b, u8)
 
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 02b2903..cc2a05d 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct device_node *np)
 	return false;
 }
 
+
+/*
+ * of_isa_indirect_io - get the IO address from some isa reg property value.
+ *	For some isa/lpc devices, no ranges property in ancestor node.
+ *	The device addresses are described directly in their regs property.
+ *	This fixup function will be called to get the IO address of isa/lpc
+ *	devices when the normal of_translation failed.
+ *
+ * @parent:	points to the parent dts node;
+ * @bus:		points to the of_bus which can be used to parse address;
+ * @addr:	the address from reg property;
+ * @na:		the address cell counter of @addr;
+ * @presult:	store the address paresed from @addr;
+ *
+ * return 1 when successfully get the I/O address;
+ * 0 will return for some failures.
+ */
+static int of_get_isa_indirect_io(struct device_node *parent,
+				struct of_bus *bus, __be32 *addr,
+				int na, u64 *presult)
+{
+	unsigned int flags;
+	unsigned int rlen;
+
+	/* whether support indirectIO */
+	if (!indirect_io_enabled())
+		return 0;
+
+	if (!of_bus_isa_match(parent))
+		return 0;
+
+	flags = bus->get_flags(addr);
+	if (!(flags & IORESOURCE_IO))
+		return 0;
+
+	/* there is ranges property, apply the normal translation directly. */
+	if (of_get_property(parent, "ranges", &rlen))
+		return 0;
+
+	*presult = of_read_number(addr + 1, na - 1);
+	/* this fixup is only valid for specific I/O range. */
+	return addr_is_indirect_io(*presult);
+}
+
 static int of_translate_one(struct device_node *parent, struct of_bus *bus,
 			    struct of_bus *pbus, __be32 *addr,
 			    int na, int ns, int pna, const char *rprop)
@@ -595,6 +639,15 @@ static u64 __of_translate_address(struct device_node *dev,
 			result = of_read_number(addr, na);
 			break;
 		}
+		/*
+		 * For indirectIO device which has no ranges property, get
+		 * the address from reg directly.
+		 */
+		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
+			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
+				of_node_full_name(dev), result);
+			break;
+		}
 
 		/* Get new parent bus and counts */
 		pbus = of_match_bus(parent);
@@ -688,8 +741,9 @@ static int __of_address_to_resource(struct device_node *dev,
 	if (taddr == OF_BAD_ADDR)
 		return -EINVAL;
 	memset(r, 0, sizeof(struct resource));
-	if (flags & IORESOURCE_IO) {
+	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
 		unsigned long port;
+
 		port = pci_address_to_pio(taddr);
 		if (port == (unsigned long)-1)
 			return -EINVAL;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index ba34907..1a08511 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3263,7 +3263,7 @@ 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;
+	resource_size_t allocated_size = PCIBIOS_MIN_IO;
 
 	/* check if the range hasn't been previously recorded */
 	spin_lock(&io_range_lock);
@@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
 
 #ifdef PCI_IOBASE
 	struct io_range *range;
-	resource_size_t allocated_size = 0;
+	resource_size_t allocated_size = PCIBIOS_MIN_IO;
 
 	if (pio > IO_SPACE_LIMIT)
 		return address;
@@ -3335,7 +3335,7 @@ unsigned long __weak pci_address_to_pio(phys_addr_t address)
 {
 #ifdef PCI_IOBASE
 	struct io_range *res;
-	resource_size_t offset = 0;
+	resource_size_t offset = PCIBIOS_MIN_IO;
 	unsigned long addr = -1;
 
 	spin_lock(&io_range_lock);
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 3786473..deec469 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -24,6 +24,23 @@ struct of_pci_range {
 #define for_each_of_pci_range(parser, range) \
 	for (; of_pci_range_parser_one(parser, range);)
 
+
+#ifndef indirect_io_enabled
+#define indirect_io_enabled indirect_io_enabled
+static inline bool indirect_io_enabled(void)
+{
+	return false;
+}
+#endif
+
+#ifndef addr_is_indirect_io
+#define addr_is_indirect_io addr_is_indirect_io
+static inline int addr_is_indirect_io(u64 taddr)
+{
+	return 0;
+}
+#endif
+
 /* Translate a DMA address from device space to CPU space */
 extern u64 of_translate_dma_address(struct device_node *dev,
 				    const __be32 *in_addr);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 0e49f70..7f6bbb6 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct pci_bus *bus)
 /* provide the legacy pci_dma_* API */
 #include <linux/pci-dma-compat.h>
 
+/*
+ * define this macro here to refrain from compilation error for some
+ * platforms. Please keep this macro at the end of this header file.
+ */
+#ifndef PCIBIOS_MIN_IO
+#define PCIBIOS_MIN_IO		0
+#endif
+
 #endif /* LINUX_PCI_H */
-- 
1.9.1

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

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-08  3:47   ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-08  3:47 UTC (permalink / raw)
  To: linux-arm-kernel

This patch solves two issues:
1) parse and get the right I/O range from DTS node whose parent does not
define the corresponding ranges property;

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 a fixup function, of_get_isa_indirect_io(). During the OF address
translation, this fixup will be called to check the 'reg' address to be
translating is for those sepcial ISA/LPC devices and get the I/O range
directly from the 'reg' property.

2) eliminate the I/O range conflict risk with PCI/PCIE leagecy I/O device;

The current __of_address_to_resource() always translates the I/O range to PIO.
But this processing is not suitable for our ISA/LPC devices whose I/O range is
not cpu address(Arnd had stressed this in his comments on V2,V3 patch-set).
Here, we bypass the mapping between cpu address and PIO for the special
ISA/LPC devices. But to drive these ISA/LPC devices, a I/O port address below
PCIBIOS_MIN_IO is needed by in*/out*(). Which means there is conflict risk
between I/O range of [0, PCIBIOS_MIN_IO) and PCI/PCIE legacy I/O range of [0,
IO_SPACE_LIMIT).
To avoid the I/O conflict, this patch reserve the I/O range below
PCIBIOS_MIN_IO.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 .../arm/hisilicon/hisilicon-low-pin-count.txt      | 31 ++++++++++++
 arch/arm64/include/asm/io.h                        |  6 +++
 arch/arm64/kernel/extio.c                          | 25 ++++++++++
 drivers/of/address.c                               | 56 +++++++++++++++++++++-
 drivers/pci/pci.c                                  |  6 +--
 include/linux/of_address.h                         | 17 +++++++
 include/linux/pci.h                                |  8 ++++
 7 files changed, 145 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
new file mode 100644
index 0000000..13c8ddd
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
@@ -0,0 +1,31 @@
+Hisilicon Hip06 low-pin-count device
+  Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
+  locate on LPC bus can be accessed direclty. But some SoCs have independent
+  LPC controller, and access the legacy ports by triggering LPC I/O cycles.
+  Hisilicon Hip06 implements this LPC device.
+
+Required properties:
+- compatible: should be "hisilicon,low-pin-count"
+- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
+- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
+- reg: base memory range where the register set of this device is mapped.
+
+Note:
+  The node name before '@' must be "isa" to represent the binding stick to the
+  ISA/EISA binding specification.
+
+Example:
+
+isa at a01b0000 {
+	compatible = "hisilicom,low-pin-count";
+	#address-cells = <2>;
+	#size-cells = <1>;
+	reg = <0x0 0xa01b0000 0x0 0x1000>;
+
+	ipmi0: bt at e4 {
+		compatible = "ipmi-bt";
+		device_type = "ipmi";
+		reg = <0x01 0xe4 0x04>;
+		status = "disabled";
+	};
+};
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 136735d..c26b7cc 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -175,6 +175,12 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
 #define outsl outsl
 
 DECLARE_EXTIO(l, u32)
+
+#define indirect_io_enabled indirect_io_enabled
+extern bool indirect_io_enabled(void);
+
+#define addr_is_indirect_io addr_is_indirect_io
+extern int addr_is_indirect_io(u64 taddr);
 #endif
 
 
diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
index 647b3fa..3d45fa8 100644
--- a/arch/arm64/kernel/extio.c
+++ b/arch/arm64/kernel/extio.c
@@ -19,6 +19,31 @@
 
 struct extio_ops *arm64_extio_ops;
 
+/**
+ * indirect_io_enabled - check whether indirectIO is enabled.
+ *	arm64_extio_ops will be set only when indirectIO mechanism had been
+ *	initialized.
+ *
+ * Returns true when indirectIO is enabled.
+ */
+bool indirect_io_enabled(void)
+{
+	return arm64_extio_ops ? true : false;
+}
+
+/**
+ * addr_is_indirect_io - check whether the input taddr is for indirectIO.
+ * @taddr: the io address to be checked.
+ *
+ * Returns 1 when taddr is in the range; otherwise return 0.
+ */
+int addr_is_indirect_io(u64 taddr)
+{
+	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end < taddr)
+		return 0;
+
+	return 1;
+}
 
 BUILD_EXTIO(b, u8)
 
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 02b2903..cc2a05d 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct device_node *np)
 	return false;
 }
 
+
+/*
+ * of_isa_indirect_io - get the IO address from some isa reg property value.
+ *	For some isa/lpc devices, no ranges property in ancestor node.
+ *	The device addresses are described directly in their regs property.
+ *	This fixup function will be called to get the IO address of isa/lpc
+ *	devices when the normal of_translation failed.
+ *
+ * @parent:	points to the parent dts node;
+ * @bus:		points to the of_bus which can be used to parse address;
+ * @addr:	the address from reg property;
+ * @na:		the address cell counter of @addr;
+ * @presult:	store the address paresed from @addr;
+ *
+ * return 1 when successfully get the I/O address;
+ * 0 will return for some failures.
+ */
+static int of_get_isa_indirect_io(struct device_node *parent,
+				struct of_bus *bus, __be32 *addr,
+				int na, u64 *presult)
+{
+	unsigned int flags;
+	unsigned int rlen;
+
+	/* whether support indirectIO */
+	if (!indirect_io_enabled())
+		return 0;
+
+	if (!of_bus_isa_match(parent))
+		return 0;
+
+	flags = bus->get_flags(addr);
+	if (!(flags & IORESOURCE_IO))
+		return 0;
+
+	/* there is ranges property, apply the normal translation directly. */
+	if (of_get_property(parent, "ranges", &rlen))
+		return 0;
+
+	*presult = of_read_number(addr + 1, na - 1);
+	/* this fixup is only valid for specific I/O range. */
+	return addr_is_indirect_io(*presult);
+}
+
 static int of_translate_one(struct device_node *parent, struct of_bus *bus,
 			    struct of_bus *pbus, __be32 *addr,
 			    int na, int ns, int pna, const char *rprop)
@@ -595,6 +639,15 @@ static u64 __of_translate_address(struct device_node *dev,
 			result = of_read_number(addr, na);
 			break;
 		}
+		/*
+		 * For indirectIO device which has no ranges property, get
+		 * the address from reg directly.
+		 */
+		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
+			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
+				of_node_full_name(dev), result);
+			break;
+		}
 
 		/* Get new parent bus and counts */
 		pbus = of_match_bus(parent);
@@ -688,8 +741,9 @@ static int __of_address_to_resource(struct device_node *dev,
 	if (taddr == OF_BAD_ADDR)
 		return -EINVAL;
 	memset(r, 0, sizeof(struct resource));
-	if (flags & IORESOURCE_IO) {
+	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
 		unsigned long port;
+
 		port = pci_address_to_pio(taddr);
 		if (port == (unsigned long)-1)
 			return -EINVAL;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index ba34907..1a08511 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3263,7 +3263,7 @@ 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;
+	resource_size_t allocated_size = PCIBIOS_MIN_IO;
 
 	/* check if the range hasn't been previously recorded */
 	spin_lock(&io_range_lock);
@@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
 
 #ifdef PCI_IOBASE
 	struct io_range *range;
-	resource_size_t allocated_size = 0;
+	resource_size_t allocated_size = PCIBIOS_MIN_IO;
 
 	if (pio > IO_SPACE_LIMIT)
 		return address;
@@ -3335,7 +3335,7 @@ unsigned long __weak pci_address_to_pio(phys_addr_t address)
 {
 #ifdef PCI_IOBASE
 	struct io_range *res;
-	resource_size_t offset = 0;
+	resource_size_t offset = PCIBIOS_MIN_IO;
 	unsigned long addr = -1;
 
 	spin_lock(&io_range_lock);
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 3786473..deec469 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -24,6 +24,23 @@ struct of_pci_range {
 #define for_each_of_pci_range(parser, range) \
 	for (; of_pci_range_parser_one(parser, range);)
 
+
+#ifndef indirect_io_enabled
+#define indirect_io_enabled indirect_io_enabled
+static inline bool indirect_io_enabled(void)
+{
+	return false;
+}
+#endif
+
+#ifndef addr_is_indirect_io
+#define addr_is_indirect_io addr_is_indirect_io
+static inline int addr_is_indirect_io(u64 taddr)
+{
+	return 0;
+}
+#endif
+
 /* Translate a DMA address from device space to CPU space */
 extern u64 of_translate_dma_address(struct device_node *dev,
 				    const __be32 *in_addr);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 0e49f70..7f6bbb6 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct pci_bus *bus)
 /* provide the legacy pci_dma_* API */
 #include <linux/pci-dma-compat.h>
 
+/*
+ * define this macro here to refrain from compilation error for some
+ * platforms. Please keep this macro at the end of this header file.
+ */
+#ifndef PCIBIOS_MIN_IO
+#define PCIBIOS_MIN_IO		0
+#endif
+
 #endif /* LINUX_PCI_H */
-- 
1.9.1

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-08  3:47 ` zhichang.yuan
  (?)
@ 2016-11-08  3:47   ` zhichang.yuan
  -1 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-08  3:47 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, bhelgaas, mark.rutland,
	olof, arnd, linux-arm-kernel
  Cc: lorenzo.pieralisi, linux-kernel, linuxarm, devicetree, linux-pci,
	linux-serial, minyard, benh, liviu.dudau, zourongrong,
	john.garry, gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

On hip06, the accesses to LPC peripherals work in an indirect way. A
corresponding LPC driver configure some registers in LPC master at first, then
the real accesses on LPC slave devices are finished by the LPC master, which
is transparent to LPC driver.
This patch implement the relevant driver for Hip06 LPC. Cooperating with
indirect-IO, ipmi messages is in service without any changes on ipmi driver.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 MAINTAINERS            |   8 +
 drivers/bus/Kconfig    |   8 +
 drivers/bus/Makefile   |   1 +
 drivers/bus/hisi_lpc.c | 501 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 518 insertions(+)
 create mode 100644 drivers/bus/hisi_lpc.c

diff --git a/MAINTAINERS b/MAINTAINERS
index ccae35b..4c7a350 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5729,6 +5729,14 @@ F:	include/uapi/linux/if_hippi.h
 F:	net/802/hippi.c
 F:	drivers/net/hippi/
 
+HISILICON LPC BUS DRIVER
+M:	Zhichang Yuan <yuanzhichang@hisilicon.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>
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 7875105..4fa8ab4 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -64,6 +64,14 @@ config BRCMSTB_GISB_ARB
 	  arbiter. This driver provides timeout and target abort error handling
 	  and internal bus master decoding.
 
+config HISILICON_LPC
+	bool "Workaround for nonstandard ISA I/O space on Hisilicon Hip0X"
+	depends on (ARCH_HISI || COMPILE_TEST) && ARM64
+	select ARM64_INDIRECT_PIO
+	help
+	  Driver needed for some legacy ISA devices attached to Low-Pin-Count
+	  on Hisilicon Hip0X SoC.
+
 config IMX_WEIM
 	bool "Freescale EIM DRIVER"
 	depends on ARCH_MXC
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index c6cfa6b..10b4983 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_ARM_CCI)		+= arm-cci.o
 obj-$(CONFIG_ARM_CCN)		+= arm-ccn.o
 
 obj-$(CONFIG_BRCMSTB_GISB_ARB)	+= brcmstb_gisb.o
+obj-$(CONFIG_HISILICON_LPC)	+= hisi_lpc.o
 obj-$(CONFIG_IMX_WEIM)		+= imx-weim.o
 obj-$(CONFIG_MIPS_CDMM)		+= mips_cdmm.o
 obj-$(CONFIG_MVEBU_MBUS) 	+= mvebu-mbus.o
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
new file mode 100644
index 0000000..47dc081
--- /dev/null
+++ b/drivers/bus/hisi_lpc.c
@@ -0,0 +1,501 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <zourongrong@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/acpi.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+/*
+ * setting this bit means each IO operation will target to different port address;
+ * 0 means repeatly IO operations will be sticked on the same port, such as BT;
+ */
+#define FG_INCRADDR_LPC		0x02
+
+struct lpc_cycle_para {
+	unsigned int opflags;
+	unsigned int csize; /* the data length of each operation */
+};
+
+struct hisilpc_dev {
+	spinlock_t cycle_lock;
+	void __iomem  *membase;
+	struct extio_ops io_ops;
+};
+
+
+/* The maximum continous operations*/
+#define LPC_MAX_OPCNT	16
+/* only support IO data unit length is four at maximum */
+#define LPC_MAX_DULEN	4
+#if LPC_MAX_DULEN > LPC_MAX_OPCNT
+#error "LPC.. MAX_DULEN must be not bigger than MAX_OPCNT!"
+#endif
+
+#define LPC_REG_START		0x00 /* start a new LPC cycle */
+#define LPC_REG_OP_STATUS	0x04 /* the current LPC status */
+#define LPC_REG_IRQ_ST		0x08 /* interrupt enable&status */
+#define LPC_REG_OP_LEN		0x10 /* how many LPC cycles each start */
+#define LPC_REG_CMD		0x14 /* command for the required LPC cycle */
+#define LPC_REG_ADDR		0x20 /* LPC target address */
+#define LPC_REG_WDATA		0x24 /* data to be written */
+#define LPC_REG_RDATA		0x28 /* data coming from peer */
+
+
+/* The command register fields*/
+#define LPC_CMD_SAMEADDR	0x08
+#define LPC_CMD_TYPE_IO		0x00
+#define LPC_CMD_WRITE		0x01
+#define LPC_CMD_READ		0x00
+/* the bit attribute is W1C. 1 represents OK. */
+#define LPC_STAT_BYIRQ		0x02
+
+#define LPC_STATUS_IDLE		0x01
+#define LPC_OP_FINISHED		0x02
+
+#define START_WORK		0x01
+
+/*
+ * The minimal waiting interval... Suggest it is not less than 10.
+ * Bigger value probably will lower the performance.
+ */
+#define LPC_NSEC_PERWAIT	100
+/*
+ * The maximum waiting time is about 128us.
+ * The fastest IO cycle time is about 390ns, but the worst case will wait
+ * for extra 256 lpc clocks, so (256 + 13) * 30ns = 8 us. The maximum
+ * burst cycles is 16. So, the maximum waiting time is about 128us under
+ * worst case.
+ * choose 1300 as the maximum.
+ */
+#define LPC_MAX_WAITCNT		1300
+/* About 10us. This is specfic for single IO operation, such as inb. */
+#define LPC_PEROP_WAITCNT	100
+
+
+static inline int wait_lpc_idle(unsigned char *mbase,
+				unsigned int waitcnt) {
+	u32 opstatus;
+
+	while (waitcnt--) {
+		ndelay(LPC_NSEC_PERWAIT);
+		opstatus = readl(mbase + LPC_REG_OP_STATUS);
+		if (opstatus & LPC_STATUS_IDLE)
+			return (opstatus & LPC_OP_FINISHED) ? 0 : (-EIO);
+	}
+	return -ETIME;
+}
+
+/**
+ * hisilpc_target_in - trigger a series of lpc cycles to read required data
+ *		  from target periperal.
+ * @pdev: pointer to hisi lpc device
+ * @para: some paramerters used to control the lpc I/O operations
+ * @ptaddr: the lpc I/O target port address
+ * @buf: where the read back data is stored
+ * @opcnt: how many I/O operations required in this calling
+ *
+ * only one byte data is read each I/O operation.
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int hisilpc_target_in(struct hisilpc_dev *lpcdev,
+				struct lpc_cycle_para *para,
+				unsigned long ptaddr, unsigned char *buf,
+				unsigned long opcnt)
+{
+	unsigned long cnt_per_trans;
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int ret;
+
+	if (!buf || !opcnt || !para || !para->csize || !lpcdev)
+		return -EINVAL;
+
+	if (opcnt  > LPC_MAX_OPCNT)
+		return -EINVAL;
+
+	cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_READ;
+	waitcnt = (LPC_PEROP_WAITCNT);
+	if (!(para->opflags & FG_INCRADDR_LPC)) {
+		cmd_word |= LPC_CMD_SAMEADDR;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	ret = 0;
+	cnt_per_trans = (para->csize == 1) ? opcnt : para->csize;
+	for (; opcnt && !ret; cnt_per_trans = para->csize) {
+		unsigned long flags;
+
+		/* whole operation must be atomic */
+		spin_lock_irqsave(&lpcdev->cycle_lock, flags);
+
+		writel(cnt_per_trans, lpcdev->membase + LPC_REG_OP_LEN);
+
+		writel(cmd_word, lpcdev->membase + LPC_REG_CMD);
+
+		writel(ptaddr, lpcdev->membase + LPC_REG_ADDR);
+
+		writel(START_WORK, lpcdev->membase + LPC_REG_START);
+
+		/* whether the operation is finished */
+		ret = wait_lpc_idle(lpcdev->membase, waitcnt);
+		if (!ret) {
+			opcnt -= cnt_per_trans;
+			for (; cnt_per_trans--; buf++)
+				*buf = readl(lpcdev->membase + LPC_REG_RDATA);
+		}
+
+		spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
+	}
+
+	return ret;
+}
+
+/**
+ * hisilpc_target_out - trigger a series of lpc cycles to write required data
+ *		  to target periperal.
+ * @pdev: pointer to hisi lpc device
+ * @para: some paramerters used to control the lpc I/O operations
+ * @ptaddr: the lpc I/O target port address
+ * @buf: where the data to be written is stored
+ * @opcnt: how many I/O operations required
+ *
+ * only one byte data is read each I/O operation.
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int hisilpc_target_out(struct hisilpc_dev *lpcdev,
+				struct lpc_cycle_para *para,
+				unsigned long ptaddr,
+				const unsigned char *buf,
+				unsigned long opcnt)
+{
+	unsigned long cnt_per_trans;
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int ret;
+
+	if (!buf || !opcnt || !para || !lpcdev)
+		return -EINVAL;
+
+	if (opcnt > LPC_MAX_OPCNT)
+		return -EINVAL;
+	/* default is increasing address */
+	cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_WRITE;
+	waitcnt = (LPC_PEROP_WAITCNT);
+	if (!(para->opflags & FG_INCRADDR_LPC)) {
+		cmd_word |= LPC_CMD_SAMEADDR;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	ret = 0;
+	cnt_per_trans = (para->csize == 1) ? opcnt : para->csize;
+	for (; opcnt && !ret; cnt_per_trans = para->csize) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&lpcdev->cycle_lock, flags);
+
+		writel(cnt_per_trans, lpcdev->membase + LPC_REG_OP_LEN);
+		opcnt -= cnt_per_trans;
+		for (; cnt_per_trans--; buf++)
+			writel(*buf, lpcdev->membase + LPC_REG_WDATA);
+
+		writel(cmd_word, lpcdev->membase + LPC_REG_CMD);
+
+		writel(ptaddr, lpcdev->membase + LPC_REG_ADDR);
+
+		writel(START_WORK, lpcdev->membase + LPC_REG_START);
+
+		/* whether the operation is finished */
+		ret = wait_lpc_idle(lpcdev->membase, waitcnt);
+
+		spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
+	}
+
+	return ret;
+}
+
+/**
+ * hisilpc_comm_in - read/input the data from the I/O peripheral through LPC.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @ptaddr: the target I/O port address.
+ * @dlen: the data length required to read from the target I/O port.
+ *
+ * when succeed, the data read back is stored in buffer pointed by inbuf.
+ * For inb, return the data read from I/O or -1 when error occur.
+ */
+static u64 hisilpc_comm_in(void *devobj, unsigned long ptaddr, size_t dlen)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	u32 rd_data;
+	unsigned char *newbuf;
+	int ret = 0;
+
+	if (!devobj || !dlen || dlen > LPC_MAX_DULEN ||	(dlen & (dlen - 1)))
+		return -1;
+
+	/* the local buffer must be enough for one data unit */
+	if (sizeof(rd_data) < dlen)
+		return -1;
+
+	newbuf = (unsigned char *)&rd_data;
+
+	lpcdev = (struct hisilpc_dev *)devobj;
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	ret = hisilpc_target_in(lpcdev, &iopara, ptaddr, newbuf, dlen);
+	if (ret)
+		return -1;
+
+	return le32_to_cpu(rd_data);
+}
+
+/**
+ * hisilpc_comm_out - write/output the data whose maximal length is four bytes to
+ *		the I/O peripheral through LPC.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @outval: a value to be outputed from caller, maximum is four bytes.
+ * @ptaddr: the target I/O port address.
+ * @dlen: the data length required writing to the target I/O port .
+ *
+ * This function is corresponding to out(b,w,l) only
+ *
+ */
+static void hisilpc_comm_out(void *devobj, unsigned long ptaddr,
+				u32 outval, size_t dlen)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	const unsigned char *newbuf;
+
+	if (!devobj || !dlen || dlen > LPC_MAX_DULEN)
+		return;
+
+	if (sizeof(outval) < dlen)
+		return;
+
+	outval = cpu_to_le32(outval);
+
+	newbuf = (const unsigned char *)&outval;
+	lpcdev = (struct hisilpc_dev *)devobj;
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	hisilpc_target_out(lpcdev, &iopara, ptaddr, newbuf, dlen);
+}
+
+/**
+ * hisilpc_comm_ins - read/input the data in buffer to the I/O peripheral
+ *		    through LPC, it corresponds to ins(b,w,l)
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @ptaddr: the target I/O port address.
+ * @inbuf: a buffer where read/input data bytes are stored.
+ * @dlen: the data length required writing to the target I/O port.
+ * @count: how many data units whose length is dlen will be read.
+ *
+ */
+static u64 hisilpc_comm_ins(void *devobj, unsigned long ptaddr,
+			void *inbuf, size_t dlen, unsigned int count)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	unsigned char *newbuf;
+	unsigned int loopcnt, cntleft;
+	unsigned int max_perburst;
+	int ret = 0;
+
+	if (!devobj || !inbuf || !count || !dlen ||
+			dlen > LPC_MAX_DULEN || (dlen & (dlen - 1)))
+		return -1;
+
+	iopara.opflags = 0;
+	if (dlen > 1)
+		iopara.opflags |= FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	lpcdev = (struct hisilpc_dev *)devobj;
+	newbuf = (unsigned char *)inbuf;
+	/*
+	 * ensure data stream whose length is multiple of dlen to be processed
+	 * each IO input
+	 */
+	max_perburst = LPC_MAX_OPCNT & (~(dlen - 1));
+	cntleft = count * dlen;
+	do {
+		loopcnt = (cntleft >= max_perburst) ? max_perburst : cntleft;
+		ret = hisilpc_target_in(lpcdev, &iopara, ptaddr, newbuf,
+						loopcnt);
+		if (ret)
+			break;
+		newbuf += loopcnt;
+		cntleft -= loopcnt;
+	} while (cntleft);
+
+	return ret;
+}
+
+/**
+ * hisilpc_comm_outs - write/output the data in buffer to the I/O peripheral
+ *		    through LPC, it corresponds to outs(b,w,l)
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @ptaddr: the target I/O port address.
+ * @outbuf: a buffer where write/output data bytes are stored.
+ * @dlen: the data length required writing to the target I/O port .
+ * @count: how many data units whose length is dlen will be written.
+ *
+ */
+static void hisilpc_comm_outs(void *devobj, unsigned long ptaddr,
+			const void *outbuf, size_t dlen, unsigned int count)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	const unsigned char *newbuf;
+	unsigned int loopcnt, cntleft;
+	unsigned int max_perburst;
+	int ret = 0;
+
+	if (!devobj || !outbuf || !count || !dlen ||
+			dlen > LPC_MAX_DULEN || (dlen & (dlen - 1)))
+		return;
+
+	iopara.opflags = 0;
+	if (dlen > 1)
+		iopara.opflags |= FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	lpcdev = (struct hisilpc_dev *)devobj;
+	newbuf = (unsigned char *)outbuf;
+	/*
+	 * ensure data stream whose lenght is multiple of dlen to be processed
+	 * each IO input
+	 */
+	max_perburst = LPC_MAX_OPCNT & (~(dlen - 1));
+	cntleft = count * dlen;
+	do {
+		loopcnt = (cntleft >= max_perburst) ? max_perburst : cntleft;
+		ret = hisilpc_target_out(lpcdev, &iopara, ptaddr, newbuf,
+						loopcnt);
+		if (ret)
+			break;
+		newbuf += loopcnt;
+		cntleft -= loopcnt;
+	} while (cntleft);
+}
+
+/**
+ * hisilpc_probe - the probe callback function for hisi lpc device,
+ *		will finish all the intialization.
+ * @pdev: the platform device corresponding to hisi lpc
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int hisilpc_probe(struct platform_device *pdev)
+{
+	struct resource *iores;
+	struct hisilpc_dev *lpcdev;
+	int ret;
+
+	dev_info(&pdev->dev, "probing hslpc...\n");
+
+	lpcdev = devm_kzalloc(&pdev->dev,
+				sizeof(struct hisilpc_dev), GFP_KERNEL);
+	if (!lpcdev)
+		return -ENOMEM;
+
+	spin_lock_init(&lpcdev->cycle_lock);
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	lpcdev->membase = devm_ioremap_resource(&pdev->dev, iores);
+	if (IS_ERR(lpcdev->membase)) {
+		dev_err(&pdev->dev, "ioremap memory FAIL(%d)!\n",
+				PTR_ERR(lpcdev->membase));
+		return PTR_ERR(lpcdev->membase);
+	}
+	/*
+	 * The first PCIBIOS_MIN_IO is reserved specifically for indirectIO.
+	 * It will separate indirectIO range from pci host bridge to
+	 * avoid the possible PIO conflict.
+	 * Set the indirectIO range directly here.
+	 */
+	lpcdev->io_ops.start = 0;
+	lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
+	lpcdev->io_ops.devpara = lpcdev;
+	lpcdev->io_ops.pfin = hisilpc_comm_in;
+	lpcdev->io_ops.pfout = hisilpc_comm_out;
+	lpcdev->io_ops.pfins = hisilpc_comm_ins;
+	lpcdev->io_ops.pfouts = hisilpc_comm_outs;
+
+	platform_set_drvdata(pdev, lpcdev);
+
+	arm64_set_extops(&lpcdev->io_ops);
+
+	/*
+	 * The children scanning is only for dts mode. For ACPI children,
+	 * the corresponding devices had be created during acpi scanning.
+	 */
+	ret = 0;
+	if (!has_acpi_companion(&pdev->dev))
+		ret = of_platform_populate(pdev->dev.of_node, NULL, NULL,
+				&pdev->dev);
+
+	if (!ret)
+		dev_info(&pdev->dev, "hslpc end probing. range[0x%lx - %lx]\n",
+			arm64_extio_ops->start, arm64_extio_ops->end);
+	else
+		dev_info(&pdev->dev, "hslpc probing is fail(%d)\n", ret);
+
+	return ret;
+}
+
+static const struct of_device_id hisilpc_of_match[] = {
+	{
+		.compatible = "hisilicon,hip06-lpc",
+	},
+	{},
+};
+
+static const struct acpi_device_id hisilpc_acpi_match[] = {
+	{"HISI0191", },
+	{},
+};
+
+static struct platform_driver hisilpc_driver = {
+	.driver = {
+		.name           = "hisi_lpc",
+		.of_match_table = hisilpc_of_match,
+		.acpi_match_table = hisilpc_acpi_match,
+	},
+	.probe = hisilpc_probe,
+};
+
+
+builtin_platform_driver(hisilpc_driver);
-- 
1.9.1

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-08  3:47   ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-08  3:47 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, bhelgaas, mark.rutland,
	olof, arnd, linux-arm-kernel
  Cc: devicetree, lorenzo.pieralisi, gabriele.paoloni, minyard,
	linux-pci, john.garry, liviu.dudau, linux-kernel, xuwei5,
	linuxarm, zhichang.yuan, linux-serial, benh, zourongrong,
	kantyzc, zhichang.yuan02

On hip06, the accesses to LPC peripherals work in an indirect way. A
corresponding LPC driver configure some registers in LPC master at first, then
the real accesses on LPC slave devices are finished by the LPC master, which
is transparent to LPC driver.
This patch implement the relevant driver for Hip06 LPC. Cooperating with
indirect-IO, ipmi messages is in service without any changes on ipmi driver.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 MAINTAINERS            |   8 +
 drivers/bus/Kconfig    |   8 +
 drivers/bus/Makefile   |   1 +
 drivers/bus/hisi_lpc.c | 501 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 518 insertions(+)
 create mode 100644 drivers/bus/hisi_lpc.c

diff --git a/MAINTAINERS b/MAINTAINERS
index ccae35b..4c7a350 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5729,6 +5729,14 @@ F:	include/uapi/linux/if_hippi.h
 F:	net/802/hippi.c
 F:	drivers/net/hippi/
 
+HISILICON LPC BUS DRIVER
+M:	Zhichang Yuan <yuanzhichang@hisilicon.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>
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 7875105..4fa8ab4 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -64,6 +64,14 @@ config BRCMSTB_GISB_ARB
 	  arbiter. This driver provides timeout and target abort error handling
 	  and internal bus master decoding.
 
+config HISILICON_LPC
+	bool "Workaround for nonstandard ISA I/O space on Hisilicon Hip0X"
+	depends on (ARCH_HISI || COMPILE_TEST) && ARM64
+	select ARM64_INDIRECT_PIO
+	help
+	  Driver needed for some legacy ISA devices attached to Low-Pin-Count
+	  on Hisilicon Hip0X SoC.
+
 config IMX_WEIM
 	bool "Freescale EIM DRIVER"
 	depends on ARCH_MXC
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index c6cfa6b..10b4983 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_ARM_CCI)		+= arm-cci.o
 obj-$(CONFIG_ARM_CCN)		+= arm-ccn.o
 
 obj-$(CONFIG_BRCMSTB_GISB_ARB)	+= brcmstb_gisb.o
+obj-$(CONFIG_HISILICON_LPC)	+= hisi_lpc.o
 obj-$(CONFIG_IMX_WEIM)		+= imx-weim.o
 obj-$(CONFIG_MIPS_CDMM)		+= mips_cdmm.o
 obj-$(CONFIG_MVEBU_MBUS) 	+= mvebu-mbus.o
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
new file mode 100644
index 0000000..47dc081
--- /dev/null
+++ b/drivers/bus/hisi_lpc.c
@@ -0,0 +1,501 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <zourongrong@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/acpi.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+/*
+ * setting this bit means each IO operation will target to different port address;
+ * 0 means repeatly IO operations will be sticked on the same port, such as BT;
+ */
+#define FG_INCRADDR_LPC		0x02
+
+struct lpc_cycle_para {
+	unsigned int opflags;
+	unsigned int csize; /* the data length of each operation */
+};
+
+struct hisilpc_dev {
+	spinlock_t cycle_lock;
+	void __iomem  *membase;
+	struct extio_ops io_ops;
+};
+
+
+/* The maximum continous operations*/
+#define LPC_MAX_OPCNT	16
+/* only support IO data unit length is four at maximum */
+#define LPC_MAX_DULEN	4
+#if LPC_MAX_DULEN > LPC_MAX_OPCNT
+#error "LPC.. MAX_DULEN must be not bigger than MAX_OPCNT!"
+#endif
+
+#define LPC_REG_START		0x00 /* start a new LPC cycle */
+#define LPC_REG_OP_STATUS	0x04 /* the current LPC status */
+#define LPC_REG_IRQ_ST		0x08 /* interrupt enable&status */
+#define LPC_REG_OP_LEN		0x10 /* how many LPC cycles each start */
+#define LPC_REG_CMD		0x14 /* command for the required LPC cycle */
+#define LPC_REG_ADDR		0x20 /* LPC target address */
+#define LPC_REG_WDATA		0x24 /* data to be written */
+#define LPC_REG_RDATA		0x28 /* data coming from peer */
+
+
+/* The command register fields*/
+#define LPC_CMD_SAMEADDR	0x08
+#define LPC_CMD_TYPE_IO		0x00
+#define LPC_CMD_WRITE		0x01
+#define LPC_CMD_READ		0x00
+/* the bit attribute is W1C. 1 represents OK. */
+#define LPC_STAT_BYIRQ		0x02
+
+#define LPC_STATUS_IDLE		0x01
+#define LPC_OP_FINISHED		0x02
+
+#define START_WORK		0x01
+
+/*
+ * The minimal waiting interval... Suggest it is not less than 10.
+ * Bigger value probably will lower the performance.
+ */
+#define LPC_NSEC_PERWAIT	100
+/*
+ * The maximum waiting time is about 128us.
+ * The fastest IO cycle time is about 390ns, but the worst case will wait
+ * for extra 256 lpc clocks, so (256 + 13) * 30ns = 8 us. The maximum
+ * burst cycles is 16. So, the maximum waiting time is about 128us under
+ * worst case.
+ * choose 1300 as the maximum.
+ */
+#define LPC_MAX_WAITCNT		1300
+/* About 10us. This is specfic for single IO operation, such as inb. */
+#define LPC_PEROP_WAITCNT	100
+
+
+static inline int wait_lpc_idle(unsigned char *mbase,
+				unsigned int waitcnt) {
+	u32 opstatus;
+
+	while (waitcnt--) {
+		ndelay(LPC_NSEC_PERWAIT);
+		opstatus = readl(mbase + LPC_REG_OP_STATUS);
+		if (opstatus & LPC_STATUS_IDLE)
+			return (opstatus & LPC_OP_FINISHED) ? 0 : (-EIO);
+	}
+	return -ETIME;
+}
+
+/**
+ * hisilpc_target_in - trigger a series of lpc cycles to read required data
+ *		  from target periperal.
+ * @pdev: pointer to hisi lpc device
+ * @para: some paramerters used to control the lpc I/O operations
+ * @ptaddr: the lpc I/O target port address
+ * @buf: where the read back data is stored
+ * @opcnt: how many I/O operations required in this calling
+ *
+ * only one byte data is read each I/O operation.
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int hisilpc_target_in(struct hisilpc_dev *lpcdev,
+				struct lpc_cycle_para *para,
+				unsigned long ptaddr, unsigned char *buf,
+				unsigned long opcnt)
+{
+	unsigned long cnt_per_trans;
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int ret;
+
+	if (!buf || !opcnt || !para || !para->csize || !lpcdev)
+		return -EINVAL;
+
+	if (opcnt  > LPC_MAX_OPCNT)
+		return -EINVAL;
+
+	cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_READ;
+	waitcnt = (LPC_PEROP_WAITCNT);
+	if (!(para->opflags & FG_INCRADDR_LPC)) {
+		cmd_word |= LPC_CMD_SAMEADDR;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	ret = 0;
+	cnt_per_trans = (para->csize == 1) ? opcnt : para->csize;
+	for (; opcnt && !ret; cnt_per_trans = para->csize) {
+		unsigned long flags;
+
+		/* whole operation must be atomic */
+		spin_lock_irqsave(&lpcdev->cycle_lock, flags);
+
+		writel(cnt_per_trans, lpcdev->membase + LPC_REG_OP_LEN);
+
+		writel(cmd_word, lpcdev->membase + LPC_REG_CMD);
+
+		writel(ptaddr, lpcdev->membase + LPC_REG_ADDR);
+
+		writel(START_WORK, lpcdev->membase + LPC_REG_START);
+
+		/* whether the operation is finished */
+		ret = wait_lpc_idle(lpcdev->membase, waitcnt);
+		if (!ret) {
+			opcnt -= cnt_per_trans;
+			for (; cnt_per_trans--; buf++)
+				*buf = readl(lpcdev->membase + LPC_REG_RDATA);
+		}
+
+		spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
+	}
+
+	return ret;
+}
+
+/**
+ * hisilpc_target_out - trigger a series of lpc cycles to write required data
+ *		  to target periperal.
+ * @pdev: pointer to hisi lpc device
+ * @para: some paramerters used to control the lpc I/O operations
+ * @ptaddr: the lpc I/O target port address
+ * @buf: where the data to be written is stored
+ * @opcnt: how many I/O operations required
+ *
+ * only one byte data is read each I/O operation.
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int hisilpc_target_out(struct hisilpc_dev *lpcdev,
+				struct lpc_cycle_para *para,
+				unsigned long ptaddr,
+				const unsigned char *buf,
+				unsigned long opcnt)
+{
+	unsigned long cnt_per_trans;
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int ret;
+
+	if (!buf || !opcnt || !para || !lpcdev)
+		return -EINVAL;
+
+	if (opcnt > LPC_MAX_OPCNT)
+		return -EINVAL;
+	/* default is increasing address */
+	cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_WRITE;
+	waitcnt = (LPC_PEROP_WAITCNT);
+	if (!(para->opflags & FG_INCRADDR_LPC)) {
+		cmd_word |= LPC_CMD_SAMEADDR;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	ret = 0;
+	cnt_per_trans = (para->csize == 1) ? opcnt : para->csize;
+	for (; opcnt && !ret; cnt_per_trans = para->csize) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&lpcdev->cycle_lock, flags);
+
+		writel(cnt_per_trans, lpcdev->membase + LPC_REG_OP_LEN);
+		opcnt -= cnt_per_trans;
+		for (; cnt_per_trans--; buf++)
+			writel(*buf, lpcdev->membase + LPC_REG_WDATA);
+
+		writel(cmd_word, lpcdev->membase + LPC_REG_CMD);
+
+		writel(ptaddr, lpcdev->membase + LPC_REG_ADDR);
+
+		writel(START_WORK, lpcdev->membase + LPC_REG_START);
+
+		/* whether the operation is finished */
+		ret = wait_lpc_idle(lpcdev->membase, waitcnt);
+
+		spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
+	}
+
+	return ret;
+}
+
+/**
+ * hisilpc_comm_in - read/input the data from the I/O peripheral through LPC.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @ptaddr: the target I/O port address.
+ * @dlen: the data length required to read from the target I/O port.
+ *
+ * when succeed, the data read back is stored in buffer pointed by inbuf.
+ * For inb, return the data read from I/O or -1 when error occur.
+ */
+static u64 hisilpc_comm_in(void *devobj, unsigned long ptaddr, size_t dlen)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	u32 rd_data;
+	unsigned char *newbuf;
+	int ret = 0;
+
+	if (!devobj || !dlen || dlen > LPC_MAX_DULEN ||	(dlen & (dlen - 1)))
+		return -1;
+
+	/* the local buffer must be enough for one data unit */
+	if (sizeof(rd_data) < dlen)
+		return -1;
+
+	newbuf = (unsigned char *)&rd_data;
+
+	lpcdev = (struct hisilpc_dev *)devobj;
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	ret = hisilpc_target_in(lpcdev, &iopara, ptaddr, newbuf, dlen);
+	if (ret)
+		return -1;
+
+	return le32_to_cpu(rd_data);
+}
+
+/**
+ * hisilpc_comm_out - write/output the data whose maximal length is four bytes to
+ *		the I/O peripheral through LPC.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @outval: a value to be outputed from caller, maximum is four bytes.
+ * @ptaddr: the target I/O port address.
+ * @dlen: the data length required writing to the target I/O port .
+ *
+ * This function is corresponding to out(b,w,l) only
+ *
+ */
+static void hisilpc_comm_out(void *devobj, unsigned long ptaddr,
+				u32 outval, size_t dlen)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	const unsigned char *newbuf;
+
+	if (!devobj || !dlen || dlen > LPC_MAX_DULEN)
+		return;
+
+	if (sizeof(outval) < dlen)
+		return;
+
+	outval = cpu_to_le32(outval);
+
+	newbuf = (const unsigned char *)&outval;
+	lpcdev = (struct hisilpc_dev *)devobj;
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	hisilpc_target_out(lpcdev, &iopara, ptaddr, newbuf, dlen);
+}
+
+/**
+ * hisilpc_comm_ins - read/input the data in buffer to the I/O peripheral
+ *		    through LPC, it corresponds to ins(b,w,l)
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @ptaddr: the target I/O port address.
+ * @inbuf: a buffer where read/input data bytes are stored.
+ * @dlen: the data length required writing to the target I/O port.
+ * @count: how many data units whose length is dlen will be read.
+ *
+ */
+static u64 hisilpc_comm_ins(void *devobj, unsigned long ptaddr,
+			void *inbuf, size_t dlen, unsigned int count)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	unsigned char *newbuf;
+	unsigned int loopcnt, cntleft;
+	unsigned int max_perburst;
+	int ret = 0;
+
+	if (!devobj || !inbuf || !count || !dlen ||
+			dlen > LPC_MAX_DULEN || (dlen & (dlen - 1)))
+		return -1;
+
+	iopara.opflags = 0;
+	if (dlen > 1)
+		iopara.opflags |= FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	lpcdev = (struct hisilpc_dev *)devobj;
+	newbuf = (unsigned char *)inbuf;
+	/*
+	 * ensure data stream whose length is multiple of dlen to be processed
+	 * each IO input
+	 */
+	max_perburst = LPC_MAX_OPCNT & (~(dlen - 1));
+	cntleft = count * dlen;
+	do {
+		loopcnt = (cntleft >= max_perburst) ? max_perburst : cntleft;
+		ret = hisilpc_target_in(lpcdev, &iopara, ptaddr, newbuf,
+						loopcnt);
+		if (ret)
+			break;
+		newbuf += loopcnt;
+		cntleft -= loopcnt;
+	} while (cntleft);
+
+	return ret;
+}
+
+/**
+ * hisilpc_comm_outs - write/output the data in buffer to the I/O peripheral
+ *		    through LPC, it corresponds to outs(b,w,l)
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @ptaddr: the target I/O port address.
+ * @outbuf: a buffer where write/output data bytes are stored.
+ * @dlen: the data length required writing to the target I/O port .
+ * @count: how many data units whose length is dlen will be written.
+ *
+ */
+static void hisilpc_comm_outs(void *devobj, unsigned long ptaddr,
+			const void *outbuf, size_t dlen, unsigned int count)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	const unsigned char *newbuf;
+	unsigned int loopcnt, cntleft;
+	unsigned int max_perburst;
+	int ret = 0;
+
+	if (!devobj || !outbuf || !count || !dlen ||
+			dlen > LPC_MAX_DULEN || (dlen & (dlen - 1)))
+		return;
+
+	iopara.opflags = 0;
+	if (dlen > 1)
+		iopara.opflags |= FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	lpcdev = (struct hisilpc_dev *)devobj;
+	newbuf = (unsigned char *)outbuf;
+	/*
+	 * ensure data stream whose lenght is multiple of dlen to be processed
+	 * each IO input
+	 */
+	max_perburst = LPC_MAX_OPCNT & (~(dlen - 1));
+	cntleft = count * dlen;
+	do {
+		loopcnt = (cntleft >= max_perburst) ? max_perburst : cntleft;
+		ret = hisilpc_target_out(lpcdev, &iopara, ptaddr, newbuf,
+						loopcnt);
+		if (ret)
+			break;
+		newbuf += loopcnt;
+		cntleft -= loopcnt;
+	} while (cntleft);
+}
+
+/**
+ * hisilpc_probe - the probe callback function for hisi lpc device,
+ *		will finish all the intialization.
+ * @pdev: the platform device corresponding to hisi lpc
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int hisilpc_probe(struct platform_device *pdev)
+{
+	struct resource *iores;
+	struct hisilpc_dev *lpcdev;
+	int ret;
+
+	dev_info(&pdev->dev, "probing hslpc...\n");
+
+	lpcdev = devm_kzalloc(&pdev->dev,
+				sizeof(struct hisilpc_dev), GFP_KERNEL);
+	if (!lpcdev)
+		return -ENOMEM;
+
+	spin_lock_init(&lpcdev->cycle_lock);
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	lpcdev->membase = devm_ioremap_resource(&pdev->dev, iores);
+	if (IS_ERR(lpcdev->membase)) {
+		dev_err(&pdev->dev, "ioremap memory FAIL(%d)!\n",
+				PTR_ERR(lpcdev->membase));
+		return PTR_ERR(lpcdev->membase);
+	}
+	/*
+	 * The first PCIBIOS_MIN_IO is reserved specifically for indirectIO.
+	 * It will separate indirectIO range from pci host bridge to
+	 * avoid the possible PIO conflict.
+	 * Set the indirectIO range directly here.
+	 */
+	lpcdev->io_ops.start = 0;
+	lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
+	lpcdev->io_ops.devpara = lpcdev;
+	lpcdev->io_ops.pfin = hisilpc_comm_in;
+	lpcdev->io_ops.pfout = hisilpc_comm_out;
+	lpcdev->io_ops.pfins = hisilpc_comm_ins;
+	lpcdev->io_ops.pfouts = hisilpc_comm_outs;
+
+	platform_set_drvdata(pdev, lpcdev);
+
+	arm64_set_extops(&lpcdev->io_ops);
+
+	/*
+	 * The children scanning is only for dts mode. For ACPI children,
+	 * the corresponding devices had be created during acpi scanning.
+	 */
+	ret = 0;
+	if (!has_acpi_companion(&pdev->dev))
+		ret = of_platform_populate(pdev->dev.of_node, NULL, NULL,
+				&pdev->dev);
+
+	if (!ret)
+		dev_info(&pdev->dev, "hslpc end probing. range[0x%lx - %lx]\n",
+			arm64_extio_ops->start, arm64_extio_ops->end);
+	else
+		dev_info(&pdev->dev, "hslpc probing is fail(%d)\n", ret);
+
+	return ret;
+}
+
+static const struct of_device_id hisilpc_of_match[] = {
+	{
+		.compatible = "hisilicon,hip06-lpc",
+	},
+	{},
+};
+
+static const struct acpi_device_id hisilpc_acpi_match[] = {
+	{"HISI0191", },
+	{},
+};
+
+static struct platform_driver hisilpc_driver = {
+	.driver = {
+		.name           = "hisi_lpc",
+		.of_match_table = hisilpc_of_match,
+		.acpi_match_table = hisilpc_acpi_match,
+	},
+	.probe = hisilpc_probe,
+};
+
+
+builtin_platform_driver(hisilpc_driver);
-- 
1.9.1

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-08  3:47   ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-08  3:47 UTC (permalink / raw)
  To: linux-arm-kernel

On hip06, the accesses to LPC peripherals work in an indirect way. A
corresponding LPC driver configure some registers in LPC master at first, then
the real accesses on LPC slave devices are finished by the LPC master, which
is transparent to LPC driver.
This patch implement the relevant driver for Hip06 LPC. Cooperating with
indirect-IO, ipmi messages is in service without any changes on ipmi driver.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 MAINTAINERS            |   8 +
 drivers/bus/Kconfig    |   8 +
 drivers/bus/Makefile   |   1 +
 drivers/bus/hisi_lpc.c | 501 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 518 insertions(+)
 create mode 100644 drivers/bus/hisi_lpc.c

diff --git a/MAINTAINERS b/MAINTAINERS
index ccae35b..4c7a350 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5729,6 +5729,14 @@ F:	include/uapi/linux/if_hippi.h
 F:	net/802/hippi.c
 F:	drivers/net/hippi/
 
+HISILICON LPC BUS DRIVER
+M:	Zhichang Yuan <yuanzhichang@hisilicon.com>
+L:	linux-arm-kernel at 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>
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 7875105..4fa8ab4 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -64,6 +64,14 @@ config BRCMSTB_GISB_ARB
 	  arbiter. This driver provides timeout and target abort error handling
 	  and internal bus master decoding.
 
+config HISILICON_LPC
+	bool "Workaround for nonstandard ISA I/O space on Hisilicon Hip0X"
+	depends on (ARCH_HISI || COMPILE_TEST) && ARM64
+	select ARM64_INDIRECT_PIO
+	help
+	  Driver needed for some legacy ISA devices attached to Low-Pin-Count
+	  on Hisilicon Hip0X SoC.
+
 config IMX_WEIM
 	bool "Freescale EIM DRIVER"
 	depends on ARCH_MXC
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index c6cfa6b..10b4983 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_ARM_CCI)		+= arm-cci.o
 obj-$(CONFIG_ARM_CCN)		+= arm-ccn.o
 
 obj-$(CONFIG_BRCMSTB_GISB_ARB)	+= brcmstb_gisb.o
+obj-$(CONFIG_HISILICON_LPC)	+= hisi_lpc.o
 obj-$(CONFIG_IMX_WEIM)		+= imx-weim.o
 obj-$(CONFIG_MIPS_CDMM)		+= mips_cdmm.o
 obj-$(CONFIG_MVEBU_MBUS) 	+= mvebu-mbus.o
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
new file mode 100644
index 0000000..47dc081
--- /dev/null
+++ b/drivers/bus/hisi_lpc.c
@@ -0,0 +1,501 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <zourongrong@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/acpi.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+/*
+ * setting this bit means each IO operation will target to different port address;
+ * 0 means repeatly IO operations will be sticked on the same port, such as BT;
+ */
+#define FG_INCRADDR_LPC		0x02
+
+struct lpc_cycle_para {
+	unsigned int opflags;
+	unsigned int csize; /* the data length of each operation */
+};
+
+struct hisilpc_dev {
+	spinlock_t cycle_lock;
+	void __iomem  *membase;
+	struct extio_ops io_ops;
+};
+
+
+/* The maximum continous operations*/
+#define LPC_MAX_OPCNT	16
+/* only support IO data unit length is four at maximum */
+#define LPC_MAX_DULEN	4
+#if LPC_MAX_DULEN > LPC_MAX_OPCNT
+#error "LPC.. MAX_DULEN must be not bigger than MAX_OPCNT!"
+#endif
+
+#define LPC_REG_START		0x00 /* start a new LPC cycle */
+#define LPC_REG_OP_STATUS	0x04 /* the current LPC status */
+#define LPC_REG_IRQ_ST		0x08 /* interrupt enable&status */
+#define LPC_REG_OP_LEN		0x10 /* how many LPC cycles each start */
+#define LPC_REG_CMD		0x14 /* command for the required LPC cycle */
+#define LPC_REG_ADDR		0x20 /* LPC target address */
+#define LPC_REG_WDATA		0x24 /* data to be written */
+#define LPC_REG_RDATA		0x28 /* data coming from peer */
+
+
+/* The command register fields*/
+#define LPC_CMD_SAMEADDR	0x08
+#define LPC_CMD_TYPE_IO		0x00
+#define LPC_CMD_WRITE		0x01
+#define LPC_CMD_READ		0x00
+/* the bit attribute is W1C. 1 represents OK. */
+#define LPC_STAT_BYIRQ		0x02
+
+#define LPC_STATUS_IDLE		0x01
+#define LPC_OP_FINISHED		0x02
+
+#define START_WORK		0x01
+
+/*
+ * The minimal waiting interval... Suggest it is not less than 10.
+ * Bigger value probably will lower the performance.
+ */
+#define LPC_NSEC_PERWAIT	100
+/*
+ * The maximum waiting time is about 128us.
+ * The fastest IO cycle time is about 390ns, but the worst case will wait
+ * for extra 256 lpc clocks, so (256 + 13) * 30ns = 8 us. The maximum
+ * burst cycles is 16. So, the maximum waiting time is about 128us under
+ * worst case.
+ * choose 1300 as the maximum.
+ */
+#define LPC_MAX_WAITCNT		1300
+/* About 10us. This is specfic for single IO operation, such as inb. */
+#define LPC_PEROP_WAITCNT	100
+
+
+static inline int wait_lpc_idle(unsigned char *mbase,
+				unsigned int waitcnt) {
+	u32 opstatus;
+
+	while (waitcnt--) {
+		ndelay(LPC_NSEC_PERWAIT);
+		opstatus = readl(mbase + LPC_REG_OP_STATUS);
+		if (opstatus & LPC_STATUS_IDLE)
+			return (opstatus & LPC_OP_FINISHED) ? 0 : (-EIO);
+	}
+	return -ETIME;
+}
+
+/**
+ * hisilpc_target_in - trigger a series of lpc cycles to read required data
+ *		  from target periperal.
+ * @pdev: pointer to hisi lpc device
+ * @para: some paramerters used to control the lpc I/O operations
+ * @ptaddr: the lpc I/O target port address
+ * @buf: where the read back data is stored
+ * @opcnt: how many I/O operations required in this calling
+ *
+ * only one byte data is read each I/O operation.
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int hisilpc_target_in(struct hisilpc_dev *lpcdev,
+				struct lpc_cycle_para *para,
+				unsigned long ptaddr, unsigned char *buf,
+				unsigned long opcnt)
+{
+	unsigned long cnt_per_trans;
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int ret;
+
+	if (!buf || !opcnt || !para || !para->csize || !lpcdev)
+		return -EINVAL;
+
+	if (opcnt  > LPC_MAX_OPCNT)
+		return -EINVAL;
+
+	cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_READ;
+	waitcnt = (LPC_PEROP_WAITCNT);
+	if (!(para->opflags & FG_INCRADDR_LPC)) {
+		cmd_word |= LPC_CMD_SAMEADDR;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	ret = 0;
+	cnt_per_trans = (para->csize == 1) ? opcnt : para->csize;
+	for (; opcnt && !ret; cnt_per_trans = para->csize) {
+		unsigned long flags;
+
+		/* whole operation must be atomic */
+		spin_lock_irqsave(&lpcdev->cycle_lock, flags);
+
+		writel(cnt_per_trans, lpcdev->membase + LPC_REG_OP_LEN);
+
+		writel(cmd_word, lpcdev->membase + LPC_REG_CMD);
+
+		writel(ptaddr, lpcdev->membase + LPC_REG_ADDR);
+
+		writel(START_WORK, lpcdev->membase + LPC_REG_START);
+
+		/* whether the operation is finished */
+		ret = wait_lpc_idle(lpcdev->membase, waitcnt);
+		if (!ret) {
+			opcnt -= cnt_per_trans;
+			for (; cnt_per_trans--; buf++)
+				*buf = readl(lpcdev->membase + LPC_REG_RDATA);
+		}
+
+		spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
+	}
+
+	return ret;
+}
+
+/**
+ * hisilpc_target_out - trigger a series of lpc cycles to write required data
+ *		  to target periperal.
+ * @pdev: pointer to hisi lpc device
+ * @para: some paramerters used to control the lpc I/O operations
+ * @ptaddr: the lpc I/O target port address
+ * @buf: where the data to be written is stored
+ * @opcnt: how many I/O operations required
+ *
+ * only one byte data is read each I/O operation.
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int hisilpc_target_out(struct hisilpc_dev *lpcdev,
+				struct lpc_cycle_para *para,
+				unsigned long ptaddr,
+				const unsigned char *buf,
+				unsigned long opcnt)
+{
+	unsigned long cnt_per_trans;
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int ret;
+
+	if (!buf || !opcnt || !para || !lpcdev)
+		return -EINVAL;
+
+	if (opcnt > LPC_MAX_OPCNT)
+		return -EINVAL;
+	/* default is increasing address */
+	cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_WRITE;
+	waitcnt = (LPC_PEROP_WAITCNT);
+	if (!(para->opflags & FG_INCRADDR_LPC)) {
+		cmd_word |= LPC_CMD_SAMEADDR;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	ret = 0;
+	cnt_per_trans = (para->csize == 1) ? opcnt : para->csize;
+	for (; opcnt && !ret; cnt_per_trans = para->csize) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&lpcdev->cycle_lock, flags);
+
+		writel(cnt_per_trans, lpcdev->membase + LPC_REG_OP_LEN);
+		opcnt -= cnt_per_trans;
+		for (; cnt_per_trans--; buf++)
+			writel(*buf, lpcdev->membase + LPC_REG_WDATA);
+
+		writel(cmd_word, lpcdev->membase + LPC_REG_CMD);
+
+		writel(ptaddr, lpcdev->membase + LPC_REG_ADDR);
+
+		writel(START_WORK, lpcdev->membase + LPC_REG_START);
+
+		/* whether the operation is finished */
+		ret = wait_lpc_idle(lpcdev->membase, waitcnt);
+
+		spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
+	}
+
+	return ret;
+}
+
+/**
+ * hisilpc_comm_in - read/input the data from the I/O peripheral through LPC.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @ptaddr: the target I/O port address.
+ * @dlen: the data length required to read from the target I/O port.
+ *
+ * when succeed, the data read back is stored in buffer pointed by inbuf.
+ * For inb, return the data read from I/O or -1 when error occur.
+ */
+static u64 hisilpc_comm_in(void *devobj, unsigned long ptaddr, size_t dlen)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	u32 rd_data;
+	unsigned char *newbuf;
+	int ret = 0;
+
+	if (!devobj || !dlen || dlen > LPC_MAX_DULEN ||	(dlen & (dlen - 1)))
+		return -1;
+
+	/* the local buffer must be enough for one data unit */
+	if (sizeof(rd_data) < dlen)
+		return -1;
+
+	newbuf = (unsigned char *)&rd_data;
+
+	lpcdev = (struct hisilpc_dev *)devobj;
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	ret = hisilpc_target_in(lpcdev, &iopara, ptaddr, newbuf, dlen);
+	if (ret)
+		return -1;
+
+	return le32_to_cpu(rd_data);
+}
+
+/**
+ * hisilpc_comm_out - write/output the data whose maximal length is four bytes to
+ *		the I/O peripheral through LPC.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @outval: a value to be outputed from caller, maximum is four bytes.
+ * @ptaddr: the target I/O port address.
+ * @dlen: the data length required writing to the target I/O port .
+ *
+ * This function is corresponding to out(b,w,l) only
+ *
+ */
+static void hisilpc_comm_out(void *devobj, unsigned long ptaddr,
+				u32 outval, size_t dlen)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	const unsigned char *newbuf;
+
+	if (!devobj || !dlen || dlen > LPC_MAX_DULEN)
+		return;
+
+	if (sizeof(outval) < dlen)
+		return;
+
+	outval = cpu_to_le32(outval);
+
+	newbuf = (const unsigned char *)&outval;
+	lpcdev = (struct hisilpc_dev *)devobj;
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	hisilpc_target_out(lpcdev, &iopara, ptaddr, newbuf, dlen);
+}
+
+/**
+ * hisilpc_comm_ins - read/input the data in buffer to the I/O peripheral
+ *		    through LPC, it corresponds to ins(b,w,l)
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @ptaddr: the target I/O port address.
+ * @inbuf: a buffer where read/input data bytes are stored.
+ * @dlen: the data length required writing to the target I/O port.
+ * @count: how many data units whose length is dlen will be read.
+ *
+ */
+static u64 hisilpc_comm_ins(void *devobj, unsigned long ptaddr,
+			void *inbuf, size_t dlen, unsigned int count)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	unsigned char *newbuf;
+	unsigned int loopcnt, cntleft;
+	unsigned int max_perburst;
+	int ret = 0;
+
+	if (!devobj || !inbuf || !count || !dlen ||
+			dlen > LPC_MAX_DULEN || (dlen & (dlen - 1)))
+		return -1;
+
+	iopara.opflags = 0;
+	if (dlen > 1)
+		iopara.opflags |= FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	lpcdev = (struct hisilpc_dev *)devobj;
+	newbuf = (unsigned char *)inbuf;
+	/*
+	 * ensure data stream whose length is multiple of dlen to be processed
+	 * each IO input
+	 */
+	max_perburst = LPC_MAX_OPCNT & (~(dlen - 1));
+	cntleft = count * dlen;
+	do {
+		loopcnt = (cntleft >= max_perburst) ? max_perburst : cntleft;
+		ret = hisilpc_target_in(lpcdev, &iopara, ptaddr, newbuf,
+						loopcnt);
+		if (ret)
+			break;
+		newbuf += loopcnt;
+		cntleft -= loopcnt;
+	} while (cntleft);
+
+	return ret;
+}
+
+/**
+ * hisilpc_comm_outs - write/output the data in buffer to the I/O peripheral
+ *		    through LPC, it corresponds to outs(b,w,l)
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @ptaddr: the target I/O port address.
+ * @outbuf: a buffer where write/output data bytes are stored.
+ * @dlen: the data length required writing to the target I/O port .
+ * @count: how many data units whose length is dlen will be written.
+ *
+ */
+static void hisilpc_comm_outs(void *devobj, unsigned long ptaddr,
+			const void *outbuf, size_t dlen, unsigned int count)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	const unsigned char *newbuf;
+	unsigned int loopcnt, cntleft;
+	unsigned int max_perburst;
+	int ret = 0;
+
+	if (!devobj || !outbuf || !count || !dlen ||
+			dlen > LPC_MAX_DULEN || (dlen & (dlen - 1)))
+		return;
+
+	iopara.opflags = 0;
+	if (dlen > 1)
+		iopara.opflags |= FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	lpcdev = (struct hisilpc_dev *)devobj;
+	newbuf = (unsigned char *)outbuf;
+	/*
+	 * ensure data stream whose lenght is multiple of dlen to be processed
+	 * each IO input
+	 */
+	max_perburst = LPC_MAX_OPCNT & (~(dlen - 1));
+	cntleft = count * dlen;
+	do {
+		loopcnt = (cntleft >= max_perburst) ? max_perburst : cntleft;
+		ret = hisilpc_target_out(lpcdev, &iopara, ptaddr, newbuf,
+						loopcnt);
+		if (ret)
+			break;
+		newbuf += loopcnt;
+		cntleft -= loopcnt;
+	} while (cntleft);
+}
+
+/**
+ * hisilpc_probe - the probe callback function for hisi lpc device,
+ *		will finish all the intialization.
+ * @pdev: the platform device corresponding to hisi lpc
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int hisilpc_probe(struct platform_device *pdev)
+{
+	struct resource *iores;
+	struct hisilpc_dev *lpcdev;
+	int ret;
+
+	dev_info(&pdev->dev, "probing hslpc...\n");
+
+	lpcdev = devm_kzalloc(&pdev->dev,
+				sizeof(struct hisilpc_dev), GFP_KERNEL);
+	if (!lpcdev)
+		return -ENOMEM;
+
+	spin_lock_init(&lpcdev->cycle_lock);
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	lpcdev->membase = devm_ioremap_resource(&pdev->dev, iores);
+	if (IS_ERR(lpcdev->membase)) {
+		dev_err(&pdev->dev, "ioremap memory FAIL(%d)!\n",
+				PTR_ERR(lpcdev->membase));
+		return PTR_ERR(lpcdev->membase);
+	}
+	/*
+	 * The first PCIBIOS_MIN_IO is reserved specifically for indirectIO.
+	 * It will separate indirectIO range from pci host bridge to
+	 * avoid the possible PIO conflict.
+	 * Set the indirectIO range directly here.
+	 */
+	lpcdev->io_ops.start = 0;
+	lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
+	lpcdev->io_ops.devpara = lpcdev;
+	lpcdev->io_ops.pfin = hisilpc_comm_in;
+	lpcdev->io_ops.pfout = hisilpc_comm_out;
+	lpcdev->io_ops.pfins = hisilpc_comm_ins;
+	lpcdev->io_ops.pfouts = hisilpc_comm_outs;
+
+	platform_set_drvdata(pdev, lpcdev);
+
+	arm64_set_extops(&lpcdev->io_ops);
+
+	/*
+	 * The children scanning is only for dts mode. For ACPI children,
+	 * the corresponding devices had be created during acpi scanning.
+	 */
+	ret = 0;
+	if (!has_acpi_companion(&pdev->dev))
+		ret = of_platform_populate(pdev->dev.of_node, NULL, NULL,
+				&pdev->dev);
+
+	if (!ret)
+		dev_info(&pdev->dev, "hslpc end probing. range[0x%lx - %lx]\n",
+			arm64_extio_ops->start, arm64_extio_ops->end);
+	else
+		dev_info(&pdev->dev, "hslpc probing is fail(%d)\n", ret);
+
+	return ret;
+}
+
+static const struct of_device_id hisilpc_of_match[] = {
+	{
+		.compatible = "hisilicon,hip06-lpc",
+	},
+	{},
+};
+
+static const struct acpi_device_id hisilpc_acpi_match[] = {
+	{"HISI0191", },
+	{},
+};
+
+static struct platform_driver hisilpc_driver = {
+	.driver = {
+		.name           = "hisi_lpc",
+		.of_match_table = hisilpc_of_match,
+		.acpi_match_table = hisilpc_acpi_match,
+	},
+	.probe = hisilpc_probe,
+};
+
+
+builtin_platform_driver(hisilpc_driver);
-- 
1.9.1

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
  2016-11-08  3:47   ` zhichang.yuan
  (?)
  (?)
@ 2016-11-08  5:17     ` kbuild test robot
  -1 siblings, 0 replies; 286+ messages in thread
From: kbuild test robot @ 2016-11-08  5:17 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: kbuild-all, catalin.marinas, will.deacon, robh+dt, bhelgaas,
	mark.rutland, olof, arnd, linux-arm-kernel, lorenzo.pieralisi,
	linux-kernel, linuxarm, devicetree, linux-pci, linux-serial,
	minyard, benh, liviu.dudau, zourongrong, john.garry,
	gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

[-- Attachment #1: Type: text/plain, Size: 3113 bytes --]

Hi zhichang.yuan,

[auto build test ERROR on arm64/for-next/core]
[also build test ERROR on v4.9-rc4 next-20161028]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/zhichang-yuan/ARM64-LPC-legacy-ISA-I-O-support/20161108-114742
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
config: mips-ath25_defconfig (attached as .config)
compiler: mips-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=mips 

All error/warnings (new ones prefixed by >>):

   In file included from arch/mips/pci/pci.c:18:0:
>> include/linux/pci.h:2113:25: error: expected identifier or '(' before numeric constant
    #define PCIBIOS_MIN_IO  0
                            ^
>> arch/mips/pci/pci.c:34:15: note: in expansion of macro 'PCIBIOS_MIN_IO'
    unsigned long PCIBIOS_MIN_IO;
                  ^~~~~~~~~~~~~~
   In file included from include/linux/linkage.h:6:0,
                    from include/linux/kernel.h:6,
                    from include/asm-generic/bug.h:13,
                    from arch/mips/include/asm/bug.h:41,
                    from include/linux/bug.h:4,
                    from arch/mips/pci/pci.c:11:
>> include/linux/pci.h:2113:25: error: expected identifier or '(' before numeric constant
    #define PCIBIOS_MIN_IO  0
                            ^
   include/linux/export.h:57:21: note: in definition of macro '___EXPORT_SYMBOL'
     extern typeof(sym) sym;     \
                        ^~~
>> arch/mips/pci/pci.c:326:1: note: in expansion of macro 'EXPORT_SYMBOL'
    EXPORT_SYMBOL(PCIBIOS_MIN_IO);
    ^~~~~~~~~~~~~
   arch/mips/pci/pci.c:326:15: note: in expansion of macro 'PCIBIOS_MIN_IO'
    EXPORT_SYMBOL(PCIBIOS_MIN_IO);
                  ^~~~~~~~~~~~~~
>> include/linux/export.h:66:21: error: lvalue required as unary '&' operand
     = { (unsigned long)&sym, __kstrtab_##sym }
                        ^
>> include/linux/export.h:94:25: note: in expansion of macro '___EXPORT_SYMBOL'
    #define __EXPORT_SYMBOL ___EXPORT_SYMBOL
                            ^~~~~~~~~~~~~~~~
   include/linux/export.h:98:2: note: in expansion of macro '__EXPORT_SYMBOL'
     __EXPORT_SYMBOL(sym, "")
     ^~~~~~~~~~~~~~~
>> arch/mips/pci/pci.c:326:1: note: in expansion of macro 'EXPORT_SYMBOL'
    EXPORT_SYMBOL(PCIBIOS_MIN_IO);
    ^~~~~~~~~~~~~

vim +2113 include/linux/pci.h

  2107	
  2108	/*
  2109	 * define this macro here to refrain from compilation error for some
  2110	 * platforms. Please keep this macro at the end of this header file.
  2111	 */
  2112	#ifndef PCIBIOS_MIN_IO
> 2113	#define PCIBIOS_MIN_IO		0
  2114	#endif
  2115	
  2116	#endif /* LINUX_PCI_H */

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 11431 bytes --]

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-08  5:17     ` kbuild test robot
  0 siblings, 0 replies; 286+ messages in thread
From: kbuild test robot @ 2016-11-08  5:17 UTC (permalink / raw)
  Cc: mark.rutland, gabriele.paoloni, benh, will.deacon, linuxarm,
	lorenzo.pieralisi, arnd, xuwei5, linux-serial, catalin.marinas,
	devicetree, minyard, liviu.dudau, john.garry, olof, robh+dt,
	bhelgaas, kantyzc, zhichang.yuan02, linux-arm-kernel, linux-pci,
	linux-kernel, zhichang.yuan, kbuild-all, zourongrong

[-- Attachment #1: Type: text/plain, Size: 3113 bytes --]

Hi zhichang.yuan,

[auto build test ERROR on arm64/for-next/core]
[also build test ERROR on v4.9-rc4 next-20161028]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/zhichang-yuan/ARM64-LPC-legacy-ISA-I-O-support/20161108-114742
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
config: mips-ath25_defconfig (attached as .config)
compiler: mips-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=mips 

All error/warnings (new ones prefixed by >>):

   In file included from arch/mips/pci/pci.c:18:0:
>> include/linux/pci.h:2113:25: error: expected identifier or '(' before numeric constant
    #define PCIBIOS_MIN_IO  0
                            ^
>> arch/mips/pci/pci.c:34:15: note: in expansion of macro 'PCIBIOS_MIN_IO'
    unsigned long PCIBIOS_MIN_IO;
                  ^~~~~~~~~~~~~~
   In file included from include/linux/linkage.h:6:0,
                    from include/linux/kernel.h:6,
                    from include/asm-generic/bug.h:13,
                    from arch/mips/include/asm/bug.h:41,
                    from include/linux/bug.h:4,
                    from arch/mips/pci/pci.c:11:
>> include/linux/pci.h:2113:25: error: expected identifier or '(' before numeric constant
    #define PCIBIOS_MIN_IO  0
                            ^
   include/linux/export.h:57:21: note: in definition of macro '___EXPORT_SYMBOL'
     extern typeof(sym) sym;     \
                        ^~~
>> arch/mips/pci/pci.c:326:1: note: in expansion of macro 'EXPORT_SYMBOL'
    EXPORT_SYMBOL(PCIBIOS_MIN_IO);
    ^~~~~~~~~~~~~
   arch/mips/pci/pci.c:326:15: note: in expansion of macro 'PCIBIOS_MIN_IO'
    EXPORT_SYMBOL(PCIBIOS_MIN_IO);
                  ^~~~~~~~~~~~~~
>> include/linux/export.h:66:21: error: lvalue required as unary '&' operand
     = { (unsigned long)&sym, __kstrtab_##sym }
                        ^
>> include/linux/export.h:94:25: note: in expansion of macro '___EXPORT_SYMBOL'
    #define __EXPORT_SYMBOL ___EXPORT_SYMBOL
                            ^~~~~~~~~~~~~~~~
   include/linux/export.h:98:2: note: in expansion of macro '__EXPORT_SYMBOL'
     __EXPORT_SYMBOL(sym, "")
     ^~~~~~~~~~~~~~~
>> arch/mips/pci/pci.c:326:1: note: in expansion of macro 'EXPORT_SYMBOL'
    EXPORT_SYMBOL(PCIBIOS_MIN_IO);
    ^~~~~~~~~~~~~

vim +2113 include/linux/pci.h

  2107	
  2108	/*
  2109	 * define this macro here to refrain from compilation error for some
  2110	 * platforms. Please keep this macro at the end of this header file.
  2111	 */
  2112	#ifndef PCIBIOS_MIN_IO
> 2113	#define PCIBIOS_MIN_IO		0
  2114	#endif
  2115	
  2116	#endif /* LINUX_PCI_H */

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 11431 bytes --]

[-- Attachment #3: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-08  5:17     ` kbuild test robot
  0 siblings, 0 replies; 286+ messages in thread
From: kbuild test robot @ 2016-11-08  5:17 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: mark.rutland, gabriele.paoloni, benh, will.deacon, linuxarm,
	lorenzo.pieralisi, arnd, xuwei5, linux-serial, catalin.marinas,
	devicetree, minyard, liviu.dudau, john.garry, olof, robh+dt,
	bhelgaas, kantyzc, zhichang.yuan02, linux-arm-kernel, linux-pci,
	linux-kernel, zhichang.yuan, kbuild-all, zourongrong

[-- Attachment #1: Type: text/plain, Size: 3113 bytes --]

Hi zhichang.yuan,

[auto build test ERROR on arm64/for-next/core]
[also build test ERROR on v4.9-rc4 next-20161028]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/zhichang-yuan/ARM64-LPC-legacy-ISA-I-O-support/20161108-114742
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
config: mips-ath25_defconfig (attached as .config)
compiler: mips-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=mips 

All error/warnings (new ones prefixed by >>):

   In file included from arch/mips/pci/pci.c:18:0:
>> include/linux/pci.h:2113:25: error: expected identifier or '(' before numeric constant
    #define PCIBIOS_MIN_IO  0
                            ^
>> arch/mips/pci/pci.c:34:15: note: in expansion of macro 'PCIBIOS_MIN_IO'
    unsigned long PCIBIOS_MIN_IO;
                  ^~~~~~~~~~~~~~
   In file included from include/linux/linkage.h:6:0,
                    from include/linux/kernel.h:6,
                    from include/asm-generic/bug.h:13,
                    from arch/mips/include/asm/bug.h:41,
                    from include/linux/bug.h:4,
                    from arch/mips/pci/pci.c:11:
>> include/linux/pci.h:2113:25: error: expected identifier or '(' before numeric constant
    #define PCIBIOS_MIN_IO  0
                            ^
   include/linux/export.h:57:21: note: in definition of macro '___EXPORT_SYMBOL'
     extern typeof(sym) sym;     \
                        ^~~
>> arch/mips/pci/pci.c:326:1: note: in expansion of macro 'EXPORT_SYMBOL'
    EXPORT_SYMBOL(PCIBIOS_MIN_IO);
    ^~~~~~~~~~~~~
   arch/mips/pci/pci.c:326:15: note: in expansion of macro 'PCIBIOS_MIN_IO'
    EXPORT_SYMBOL(PCIBIOS_MIN_IO);
                  ^~~~~~~~~~~~~~
>> include/linux/export.h:66:21: error: lvalue required as unary '&' operand
     = { (unsigned long)&sym, __kstrtab_##sym }
                        ^
>> include/linux/export.h:94:25: note: in expansion of macro '___EXPORT_SYMBOL'
    #define __EXPORT_SYMBOL ___EXPORT_SYMBOL
                            ^~~~~~~~~~~~~~~~
   include/linux/export.h:98:2: note: in expansion of macro '__EXPORT_SYMBOL'
     __EXPORT_SYMBOL(sym, "")
     ^~~~~~~~~~~~~~~
>> arch/mips/pci/pci.c:326:1: note: in expansion of macro 'EXPORT_SYMBOL'
    EXPORT_SYMBOL(PCIBIOS_MIN_IO);
    ^~~~~~~~~~~~~

vim +2113 include/linux/pci.h

  2107	
  2108	/*
  2109	 * define this macro here to refrain from compilation error for some
  2110	 * platforms. Please keep this macro at the end of this header file.
  2111	 */
  2112	#ifndef PCIBIOS_MIN_IO
> 2113	#define PCIBIOS_MIN_IO		0
  2114	#endif
  2115	
  2116	#endif /* LINUX_PCI_H */

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 11431 bytes --]

[-- Attachment #3: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-08  5:17     ` kbuild test robot
  0 siblings, 0 replies; 286+ messages in thread
From: kbuild test robot @ 2016-11-08  5:17 UTC (permalink / raw)
  To: linux-arm-kernel

Hi zhichang.yuan,

[auto build test ERROR on arm64/for-next/core]
[also build test ERROR on v4.9-rc4 next-20161028]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/zhichang-yuan/ARM64-LPC-legacy-ISA-I-O-support/20161108-114742
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
config: mips-ath25_defconfig (attached as .config)
compiler: mips-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=mips 

All error/warnings (new ones prefixed by >>):

   In file included from arch/mips/pci/pci.c:18:0:
>> include/linux/pci.h:2113:25: error: expected identifier or '(' before numeric constant
    #define PCIBIOS_MIN_IO  0
                            ^
>> arch/mips/pci/pci.c:34:15: note: in expansion of macro 'PCIBIOS_MIN_IO'
    unsigned long PCIBIOS_MIN_IO;
                  ^~~~~~~~~~~~~~
   In file included from include/linux/linkage.h:6:0,
                    from include/linux/kernel.h:6,
                    from include/asm-generic/bug.h:13,
                    from arch/mips/include/asm/bug.h:41,
                    from include/linux/bug.h:4,
                    from arch/mips/pci/pci.c:11:
>> include/linux/pci.h:2113:25: error: expected identifier or '(' before numeric constant
    #define PCIBIOS_MIN_IO  0
                            ^
   include/linux/export.h:57:21: note: in definition of macro '___EXPORT_SYMBOL'
     extern typeof(sym) sym;     \
                        ^~~
>> arch/mips/pci/pci.c:326:1: note: in expansion of macro 'EXPORT_SYMBOL'
    EXPORT_SYMBOL(PCIBIOS_MIN_IO);
    ^~~~~~~~~~~~~
   arch/mips/pci/pci.c:326:15: note: in expansion of macro 'PCIBIOS_MIN_IO'
    EXPORT_SYMBOL(PCIBIOS_MIN_IO);
                  ^~~~~~~~~~~~~~
>> include/linux/export.h:66:21: error: lvalue required as unary '&' operand
     = { (unsigned long)&sym, __kstrtab_##sym }
                        ^
>> include/linux/export.h:94:25: note: in expansion of macro '___EXPORT_SYMBOL'
    #define __EXPORT_SYMBOL ___EXPORT_SYMBOL
                            ^~~~~~~~~~~~~~~~
   include/linux/export.h:98:2: note: in expansion of macro '__EXPORT_SYMBOL'
     __EXPORT_SYMBOL(sym, "")
     ^~~~~~~~~~~~~~~
>> arch/mips/pci/pci.c:326:1: note: in expansion of macro 'EXPORT_SYMBOL'
    EXPORT_SYMBOL(PCIBIOS_MIN_IO);
    ^~~~~~~~~~~~~

vim +2113 include/linux/pci.h

  2107	
  2108	/*
  2109	 * define this macro here to refrain from compilation error for some
  2110	 * platforms. Please keep this macro at the end of this header file.
  2111	 */
  2112	#ifndef PCIBIOS_MIN_IO
> 2113	#define PCIBIOS_MIN_IO		0
  2114	#endif
  2115	
  2116	#endif /* LINUX_PCI_H */

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 11431 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161108/33074cfc/attachment-0001.gz>

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-08  5:27     ` kbuild test robot
  0 siblings, 0 replies; 286+ messages in thread
From: kbuild test robot @ 2016-11-08  5:27 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: kbuild-all, catalin.marinas, will.deacon, robh+dt, bhelgaas,
	mark.rutland, olof, arnd, linux-arm-kernel, lorenzo.pieralisi,
	linux-kernel, linuxarm, devicetree, linux-pci, linux-serial,
	minyard, benh, liviu.dudau, zourongrong, john.garry,
	gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

[-- Attachment #1: Type: text/plain, Size: 1184 bytes --]

Hi zhichang.yuan,

[auto build test ERROR on arm64/for-next/core]
[also build test ERROR on v4.9-rc4 next-20161028]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/zhichang-yuan/ARM64-LPC-legacy-ISA-I-O-support/20161108-114742
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
config: arm-sunxi_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `of_address_to_resource':
>> sunxi_sid.c:(.text+0x18af5c): undefined reference to `pcibios_min_io'
   sunxi_sid.c:(.text+0x18af60): undefined reference to `pcibios_min_io'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 20012 bytes --]

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-08  5:27     ` kbuild test robot
  0 siblings, 0 replies; 286+ messages in thread
From: kbuild test robot @ 2016-11-08  5:27 UTC (permalink / raw)
  Cc: kbuild-all-JC7UmRfGjtg, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, mark.rutland-5wv7dgnIgG8,
	olof-nZhT3qVonbNeoWH0uzbU5w, arnd-r2nGTMty4D4,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	lorenzo.pieralisi-5wv7dgnIgG8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linuxarm-hv44wF8Li93QT0dZR+AlfA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, minyard-HInyCGIudOg,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, liviu.dudau-5wv7dgnIgG8,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
	john.garry-hv44wF8Li93QT0dZR+AlfA,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w, kantyzc-9Onoh4P/yGk,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q, zhichang.yuan

[-- Attachment #1: Type: text/plain, Size: 1184 bytes --]

Hi zhichang.yuan,

[auto build test ERROR on arm64/for-next/core]
[also build test ERROR on v4.9-rc4 next-20161028]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/zhichang-yuan/ARM64-LPC-legacy-ISA-I-O-support/20161108-114742
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
config: arm-sunxi_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `of_address_to_resource':
>> sunxi_sid.c:(.text+0x18af5c): undefined reference to `pcibios_min_io'
   sunxi_sid.c:(.text+0x18af60): undefined reference to `pcibios_min_io'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 20012 bytes --]

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

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-08  5:27     ` kbuild test robot
  0 siblings, 0 replies; 286+ messages in thread
From: kbuild test robot @ 2016-11-08  5:27 UTC (permalink / raw)
  To: linux-arm-kernel

Hi zhichang.yuan,

[auto build test ERROR on arm64/for-next/core]
[also build test ERROR on v4.9-rc4 next-20161028]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/zhichang-yuan/ARM64-LPC-legacy-ISA-I-O-support/20161108-114742
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
config: arm-sunxi_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `of_address_to_resource':
>> sunxi_sid.c:(.text+0x18af5c): undefined reference to `pcibios_min_io'
   sunxi_sid.c:(.text+0x18af60): undefined reference to `pcibios_min_io'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 20012 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161108/cbd550e2/attachment-0001.gz>

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-08  3:47   ` zhichang.yuan
  (?)
@ 2016-11-08  6:11     ` kbuild test robot
  -1 siblings, 0 replies; 286+ messages in thread
From: kbuild test robot @ 2016-11-08  6:11 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: kbuild-all, catalin.marinas, will.deacon, robh+dt, bhelgaas,
	mark.rutland, olof, arnd, linux-arm-kernel, lorenzo.pieralisi,
	linux-kernel, linuxarm, devicetree, linux-pci, linux-serial,
	minyard, benh, liviu.dudau, zourongrong, john.garry,
	gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

[-- Attachment #1: Type: text/plain, Size: 2241 bytes --]

Hi zhichang.yuan,

[auto build test WARNING on arm64/for-next/core]
[also build test WARNING on v4.9-rc4 next-20161028]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/zhichang-yuan/ARM64-LPC-legacy-ISA-I-O-support/20161108-114742
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
config: arm64-allmodconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

All warnings (new ones prefixed by >>):

   drivers/bus/hisi_lpc.c: In function 'hisilpc_probe':
>> drivers/bus/hisi_lpc.c:439:45: warning: format '%d' expects argument of type 'int', but argument 3 has type 'long int' [-Wformat=]
      dev_err(&pdev->dev, "ioremap memory FAIL(%d)!\n",
                                                ^

vim +439 drivers/bus/hisi_lpc.c

   423	{
   424		struct resource *iores;
   425		struct hisilpc_dev *lpcdev;
   426		int ret;
   427	
   428		dev_info(&pdev->dev, "probing hslpc...\n");
   429	
   430		lpcdev = devm_kzalloc(&pdev->dev,
   431					sizeof(struct hisilpc_dev), GFP_KERNEL);
   432		if (!lpcdev)
   433			return -ENOMEM;
   434	
   435		spin_lock_init(&lpcdev->cycle_lock);
   436		iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
   437		lpcdev->membase = devm_ioremap_resource(&pdev->dev, iores);
   438		if (IS_ERR(lpcdev->membase)) {
 > 439			dev_err(&pdev->dev, "ioremap memory FAIL(%d)!\n",
   440					PTR_ERR(lpcdev->membase));
   441			return PTR_ERR(lpcdev->membase);
   442		}
   443		/*
   444		 * The first PCIBIOS_MIN_IO is reserved specifically for indirectIO.
   445		 * It will separate indirectIO range from pci host bridge to
   446		 * avoid the possible PIO conflict.
   447		 * Set the indirectIO range directly here.

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 51464 bytes --]

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-08  6:11     ` kbuild test robot
  0 siblings, 0 replies; 286+ messages in thread
From: kbuild test robot @ 2016-11-08  6:11 UTC (permalink / raw)
  Cc: kbuild-all, catalin.marinas, will.deacon, robh+dt, bhelgaas,
	mark.rutland, olof, arnd, linux-arm-kernel, lorenzo.pieralisi,
	linux-kernel, linuxarm, devicetree, linux-pci, linux-serial,
	minyard, benh, liviu.dudau, zourongrong, john.garry,
	gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	zhichang.yuan

[-- Attachment #1: Type: text/plain, Size: 2241 bytes --]

Hi zhichang.yuan,

[auto build test WARNING on arm64/for-next/core]
[also build test WARNING on v4.9-rc4 next-20161028]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/zhichang-yuan/ARM64-LPC-legacy-ISA-I-O-support/20161108-114742
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
config: arm64-allmodconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

All warnings (new ones prefixed by >>):

   drivers/bus/hisi_lpc.c: In function 'hisilpc_probe':
>> drivers/bus/hisi_lpc.c:439:45: warning: format '%d' expects argument of type 'int', but argument 3 has type 'long int' [-Wformat=]
      dev_err(&pdev->dev, "ioremap memory FAIL(%d)!\n",
                                                ^

vim +439 drivers/bus/hisi_lpc.c

   423	{
   424		struct resource *iores;
   425		struct hisilpc_dev *lpcdev;
   426		int ret;
   427	
   428		dev_info(&pdev->dev, "probing hslpc...\n");
   429	
   430		lpcdev = devm_kzalloc(&pdev->dev,
   431					sizeof(struct hisilpc_dev), GFP_KERNEL);
   432		if (!lpcdev)
   433			return -ENOMEM;
   434	
   435		spin_lock_init(&lpcdev->cycle_lock);
   436		iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
   437		lpcdev->membase = devm_ioremap_resource(&pdev->dev, iores);
   438		if (IS_ERR(lpcdev->membase)) {
 > 439			dev_err(&pdev->dev, "ioremap memory FAIL(%d)!\n",
   440					PTR_ERR(lpcdev->membase));
   441			return PTR_ERR(lpcdev->membase);
   442		}
   443		/*
   444		 * The first PCIBIOS_MIN_IO is reserved specifically for indirectIO.
   445		 * It will separate indirectIO range from pci host bridge to
   446		 * avoid the possible PIO conflict.
   447		 * Set the indirectIO range directly here.

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 51464 bytes --]

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-08  6:11     ` kbuild test robot
  0 siblings, 0 replies; 286+ messages in thread
From: kbuild test robot @ 2016-11-08  6:11 UTC (permalink / raw)
  To: linux-arm-kernel

Hi zhichang.yuan,

[auto build test WARNING on arm64/for-next/core]
[also build test WARNING on v4.9-rc4 next-20161028]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/zhichang-yuan/ARM64-LPC-legacy-ISA-I-O-support/20161108-114742
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
config: arm64-allmodconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

All warnings (new ones prefixed by >>):

   drivers/bus/hisi_lpc.c: In function 'hisilpc_probe':
>> drivers/bus/hisi_lpc.c:439:45: warning: format '%d' expects argument of type 'int', but argument 3 has type 'long int' [-Wformat=]
      dev_err(&pdev->dev, "ioremap memory FAIL(%d)!\n",
                                                ^

vim +439 drivers/bus/hisi_lpc.c

   423	{
   424		struct resource *iores;
   425		struct hisilpc_dev *lpcdev;
   426		int ret;
   427	
   428		dev_info(&pdev->dev, "probing hslpc...\n");
   429	
   430		lpcdev = devm_kzalloc(&pdev->dev,
   431					sizeof(struct hisilpc_dev), GFP_KERNEL);
   432		if (!lpcdev)
   433			return -ENOMEM;
   434	
   435		spin_lock_init(&lpcdev->cycle_lock);
   436		iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
   437		lpcdev->membase = devm_ioremap_resource(&pdev->dev, iores);
   438		if (IS_ERR(lpcdev->membase)) {
 > 439			dev_err(&pdev->dev, "ioremap memory FAIL(%d)!\n",
   440					PTR_ERR(lpcdev->membase));
   441			return PTR_ERR(lpcdev->membase);
   442		}
   443		/*
   444		 * The first PCIBIOS_MIN_IO is reserved specifically for indirectIO.
   445		 * It will separate indirectIO range from pci host bridge to
   446		 * avoid the possible PIO conflict.
   447		 * Set the indirectIO range directly here.

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 51464 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161108/819b59bc/attachment-0001.gz>

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
  2016-11-08  3:47   ` zhichang.yuan
@ 2016-11-08 11:49     ` Mark Rutland
  -1 siblings, 0 replies; 286+ messages in thread
From: Mark Rutland @ 2016-11-08 11:49 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, olof, arnd,
	linux-arm-kernel, lorenzo.pieralisi, linux-kernel, linuxarm,
	devicetree, linux-pci, linux-serial, minyard, benh, liviu.dudau,
	zourongrong, john.garry, gabriele.paoloni, zhichang.yuan02,
	kantyzc, xuwei5, marc.zyngier

On Tue, Nov 08, 2016 at 11:47:08AM +0800, zhichang.yuan wrote:
> +Hisilicon Hip06 low-pin-count device
> +  Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
> +  locate on LPC bus can be accessed direclty. But some SoCs have independent
> +  LPC controller, and access the legacy ports by triggering LPC I/O cycles.
> +  Hisilicon Hip06 implements this LPC device.

s/direclty/directly/

My understanding of ISA (which may be flawed) is that it's not part of
the PCI host bridge, but rather on x86 it happens to share the IO space
with PCI.

So, how about this becomes:

  Hisilicon Hip06 SoCs implement a Low Pin Count (LPC) controller, which
  provides access to some legacy ISA devices.

I believe that we could theoretically have multiple independent LPC/ISA
busses, as is possible with PCI on !x86 systems. If the current ISA code
assumes a singleton bus, I think that's something that needs to be fixed
up more generically.

I don't see why we should need any architecture-specific code here. Why
can we not fix up the ISA bus code in drivers/of/address.c such that it
handles multiple ISA bus instances, and translates all sub-device
addresses relative to the specific bus instance?

> +Required properties:
> +- compatible: should be "hisilicon,low-pin-count"

This would be better as something like:

	"hisilicon,hip06-lpc-controller"

If it's reused in other SoCs, we can add more strings as we usually do.

> +- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
> +- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
> +- reg: base memory range where the register set of this device is mapped.
> +
> +Note:
> +  The node name before '@' must be "isa" to represent the binding stick to the
> +  ISA/EISA binding specification.
> +
> +Example:
> +
> +isa@a01b0000 {
> +	compatible = "hisilicom,low-pin-count";

s/hisilicom/hisilicon/

My comment above on the compatible string also applies.

> +	#address-cells = <2>;
> +	#size-cells = <1>;
> +	reg = <0x0 0xa01b0000 0x0 0x1000>;
> +
> +	ipmi0: bt@e4 {
> +		compatible = "ipmi-bt";
> +		device_type = "ipmi";
> +		reg = <0x01 0xe4 0x04>;
> +		status = "disabled";
> +	};
> +};

Please remove the status property; it's irrelevant to the example.

[...]

> +/**
> + * indirect_io_enabled - check whether indirectIO is enabled.
> + *	arm64_extio_ops will be set only when indirectIO mechanism had been
> + *	initialized.
> + *
> + * Returns true when indirectIO is enabled.
> + */
> +bool indirect_io_enabled(void)
> +{
> +	return arm64_extio_ops ? true : false;
> +}

	return !!arm64_extio_ops;

> +/**
> + * addr_is_indirect_io - check whether the input taddr is for indirectIO.
> + * @taddr: the io address to be checked.
> + *
> + * Returns 1 when taddr is in the range; otherwise return 0.
> + */
> +int addr_is_indirect_io(u64 taddr)
> +{
> +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end < taddr)
> +		return 0;
> +
> +	return 1;
> +}

Why not bool?

I don't think this is the right thing to do, regardless.

> + * of_isa_indirect_io - get the IO address from some isa reg property value.
> + *	For some isa/lpc devices, no ranges property in ancestor node.
> + *	The device addresses are described directly in their regs property.
> + *	This fixup function will be called to get the IO address of isa/lpc
> + *	devices when the normal of_translation failed.
> + *
> + * @parent:	points to the parent dts node;
> + * @bus:		points to the of_bus which can be used to parse address;
> + * @addr:	the address from reg property;
> + * @na:		the address cell counter of @addr;
> + * @presult:	store the address paresed from @addr;
> + *
> + * return 1 when successfully get the I/O address;
> + * 0 will return for some failures.
> + */
> +static int of_get_isa_indirect_io(struct device_node *parent,
> +				struct of_bus *bus, __be32 *addr,
> +				int na, u64 *presult)
> +{
> +	unsigned int flags;
> +	unsigned int rlen;
> +
> +	/* whether support indirectIO */
> +	if (!indirect_io_enabled())
> +		return 0;
> +
> +	if (!of_bus_isa_match(parent))
> +		return 0;
> +
> +	flags = bus->get_flags(addr);
> +	if (!(flags & IORESOURCE_IO))
> +		return 0;
> +
> +	/* there is ranges property, apply the normal translation directly. */
> +	if (of_get_property(parent, "ranges", &rlen))
> +		return 0;
> +
> +	*presult = of_read_number(addr + 1, na - 1);
> +	/* this fixup is only valid for specific I/O range. */
> +	return addr_is_indirect_io(*presult);
> +}
> +
>  static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>  			    struct of_bus *pbus, __be32 *addr,
>  			    int na, int ns, int pna, const char *rprop)
> @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct device_node *dev,
>  			result = of_read_number(addr, na);
>  			break;
>  		}
> +		/*
> +		 * For indirectIO device which has no ranges property, get
> +		 * the address from reg directly.
> +		 */
> +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> +			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
> +				of_node_full_name(dev), result);
> +			break;
> +		}

I don't believe this is the right place for this to live. This should
live in the isa of_bus, matched in the usual way with of_match_bus(),
and used in pbus->translate() in of_translate_one().

If we need to extend the prototypes of those functions, we should do so.

If we need to be able to register instance-specific translations or
indirection, we should build the infrastructure for that rather than
forcing a singleton translation in here.

Thanks,
Mark.

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

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-08 11:49     ` Mark Rutland
  0 siblings, 0 replies; 286+ messages in thread
From: Mark Rutland @ 2016-11-08 11:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Nov 08, 2016 at 11:47:08AM +0800, zhichang.yuan wrote:
> +Hisilicon Hip06 low-pin-count device
> +  Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
> +  locate on LPC bus can be accessed direclty. But some SoCs have independent
> +  LPC controller, and access the legacy ports by triggering LPC I/O cycles.
> +  Hisilicon Hip06 implements this LPC device.

s/direclty/directly/

My understanding of ISA (which may be flawed) is that it's not part of
the PCI host bridge, but rather on x86 it happens to share the IO space
with PCI.

So, how about this becomes:

  Hisilicon Hip06 SoCs implement a Low Pin Count (LPC) controller, which
  provides access to some legacy ISA devices.

I believe that we could theoretically have multiple independent LPC/ISA
busses, as is possible with PCI on !x86 systems. If the current ISA code
assumes a singleton bus, I think that's something that needs to be fixed
up more generically.

I don't see why we should need any architecture-specific code here. Why
can we not fix up the ISA bus code in drivers/of/address.c such that it
handles multiple ISA bus instances, and translates all sub-device
addresses relative to the specific bus instance?

> +Required properties:
> +- compatible: should be "hisilicon,low-pin-count"

This would be better as something like:

	"hisilicon,hip06-lpc-controller"

If it's reused in other SoCs, we can add more strings as we usually do.

> +- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
> +- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
> +- reg: base memory range where the register set of this device is mapped.
> +
> +Note:
> +  The node name before '@' must be "isa" to represent the binding stick to the
> +  ISA/EISA binding specification.
> +
> +Example:
> +
> +isa at a01b0000 {
> +	compatible = "hisilicom,low-pin-count";

s/hisilicom/hisilicon/

My comment above on the compatible string also applies.

> +	#address-cells = <2>;
> +	#size-cells = <1>;
> +	reg = <0x0 0xa01b0000 0x0 0x1000>;
> +
> +	ipmi0: bt at e4 {
> +		compatible = "ipmi-bt";
> +		device_type = "ipmi";
> +		reg = <0x01 0xe4 0x04>;
> +		status = "disabled";
> +	};
> +};

Please remove the status property; it's irrelevant to the example.

[...]

> +/**
> + * indirect_io_enabled - check whether indirectIO is enabled.
> + *	arm64_extio_ops will be set only when indirectIO mechanism had been
> + *	initialized.
> + *
> + * Returns true when indirectIO is enabled.
> + */
> +bool indirect_io_enabled(void)
> +{
> +	return arm64_extio_ops ? true : false;
> +}

	return !!arm64_extio_ops;

> +/**
> + * addr_is_indirect_io - check whether the input taddr is for indirectIO.
> + * @taddr: the io address to be checked.
> + *
> + * Returns 1 when taddr is in the range; otherwise return 0.
> + */
> +int addr_is_indirect_io(u64 taddr)
> +{
> +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end < taddr)
> +		return 0;
> +
> +	return 1;
> +}

Why not bool?

I don't think this is the right thing to do, regardless.

> + * of_isa_indirect_io - get the IO address from some isa reg property value.
> + *	For some isa/lpc devices, no ranges property in ancestor node.
> + *	The device addresses are described directly in their regs property.
> + *	This fixup function will be called to get the IO address of isa/lpc
> + *	devices when the normal of_translation failed.
> + *
> + * @parent:	points to the parent dts node;
> + * @bus:		points to the of_bus which can be used to parse address;
> + * @addr:	the address from reg property;
> + * @na:		the address cell counter of @addr;
> + * @presult:	store the address paresed from @addr;
> + *
> + * return 1 when successfully get the I/O address;
> + * 0 will return for some failures.
> + */
> +static int of_get_isa_indirect_io(struct device_node *parent,
> +				struct of_bus *bus, __be32 *addr,
> +				int na, u64 *presult)
> +{
> +	unsigned int flags;
> +	unsigned int rlen;
> +
> +	/* whether support indirectIO */
> +	if (!indirect_io_enabled())
> +		return 0;
> +
> +	if (!of_bus_isa_match(parent))
> +		return 0;
> +
> +	flags = bus->get_flags(addr);
> +	if (!(flags & IORESOURCE_IO))
> +		return 0;
> +
> +	/* there is ranges property, apply the normal translation directly. */
> +	if (of_get_property(parent, "ranges", &rlen))
> +		return 0;
> +
> +	*presult = of_read_number(addr + 1, na - 1);
> +	/* this fixup is only valid for specific I/O range. */
> +	return addr_is_indirect_io(*presult);
> +}
> +
>  static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>  			    struct of_bus *pbus, __be32 *addr,
>  			    int na, int ns, int pna, const char *rprop)
> @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct device_node *dev,
>  			result = of_read_number(addr, na);
>  			break;
>  		}
> +		/*
> +		 * For indirectIO device which has no ranges property, get
> +		 * the address from reg directly.
> +		 */
> +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> +			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
> +				of_node_full_name(dev), result);
> +			break;
> +		}

I don't believe this is the right place for this to live. This should
live in the isa of_bus, matched in the usual way with of_match_bus(),
and used in pbus->translate() in of_translate_one().

If we need to extend the prototypes of those functions, we should do so.

If we need to be able to register instance-specific translations or
indirection, we should build the infrastructure for that rather than
forcing a singleton translation in here.

Thanks,
Mark.

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08 12:03     ` Mark Rutland
  0 siblings, 0 replies; 286+ messages in thread
From: Mark Rutland @ 2016-11-08 12:03 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, olof, arnd,
	linux-arm-kernel, lorenzo.pieralisi, linux-kernel, linuxarm,
	devicetree, linux-pci, linux-serial, minyard, benh, liviu.dudau,
	zourongrong, john.garry, gabriele.paoloni, zhichang.yuan02,
	kantyzc, xuwei5, marc.zyngier

On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> For arm64, there is no I/O space as other architectural platforms, such as
> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> known port addresses are used to control the corresponding target devices, for
> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> normal MMIO mode in using.

This has nothing to do with arm64. Hardware with this kind of indirect
bus access could be integrated with a variety of CPU architectures. It
simply hasn't been, yet.

> To drive these devices, this patch introduces a method named indirect-IO.
> In this method the in/out pair in arch/arm64/include/asm/io.h will be
> redefined. When upper layer drivers call in/out with those known legacy port
> addresses to access the peripherals, the hooking functions corrresponding to
> those target peripherals will be called. Through this way, those upper layer
> drivers which depend on in/out can run on Hip06 without any changes.

As above, this has nothing to do with arm64, and as such, should live in
generic code, exactly as we would do if we had higher-level ISA
accessor ops.

Regardless, given the multi-instance case, I don't think this is
sufficient in general (and I think we need higher-level ISA accessors
to handle the indirection).

[...]

> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
> new file mode 100644
> index 0000000..6ae0787
> --- /dev/null
> +++ b/arch/arm64/include/asm/extio.h

> +#ifndef __LINUX_EXTIO_H
> +#define __LINUX_EXTIO_H

This doesn't match the file naming, __ASM_EXTIO_H would be consistent
with other arm64 headers.

> +
> +struct extio_ops {
> +	unsigned long start;/* inclusive, sys io addr */
> +	unsigned long end;/* inclusive, sys io addr */

Please put whitespace before inline comments.

[...]

> +type in##bw(unsigned long addr)						\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		return read##bw(PCI_IOBASE + addr);			\
> +	return arm64_extio_ops->pfin ?					\
> +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
> +			addr, sizeof(type)) : -1;			\
> +}									\
> +									\
> +void out##bw(type value, unsigned long addr)				\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		write##bw(value, PCI_IOBASE + addr);			\
> +	else								\
> +		if (arm64_extio_ops->pfout)				\
> +			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> +				addr, value, sizeof(type));		\
> +}									\
> +									\
> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		reads##bw(PCI_IOBASE + addr, buffer, count);		\
> +	else								\
> +		if (arm64_extio_ops->pfins)				\
> +			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
> +				addr, buffer, sizeof(type), count);	\
> +}									\
> +									\
> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		writes##bw(PCI_IOBASE + addr, buffer, count);		\
> +	else								\
> +		if (arm64_extio_ops->pfouts)				\
> +			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
> +				addr, buffer, sizeof(type), count);	\
> +}
> +

So all PCI I/O will be slowed down by irrelevant checks when this is
enabled?

[...]

> +static inline void arm64_set_extops(struct extio_ops *ops)
> +{
> +	if (ops)
> +		WRITE_ONCE(arm64_extio_ops, ops);
> +}

Why WRITE_ONCE()?

Is this not protected/propagated by some synchronisation mechanism?

WRITE_ONCE() is not sufficient to ensure that this is consistently
observed by readers, and regardless, I don't see READ_ONCE() anywhere in
this patch.

This looks very suspicious.

Thanks,
Mark.

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08 12:03     ` Mark Rutland
  0 siblings, 0 replies; 286+ messages in thread
From: Mark Rutland @ 2016-11-08 12:03 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, bhelgaas-hpIqsD4AKlfQT0dZR+AlfA,
	olof-nZhT3qVonbNeoWH0uzbU5w, arnd-r2nGTMty4D4,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	lorenzo.pieralisi-5wv7dgnIgG8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linuxarm-hv44wF8Li93QT0dZR+AlfA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, minyard-HInyCGIudOg,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, liviu.dudau-5wv7dgnIgG8,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
	john.garry-hv44wF8Li93QT0dZR+AlfA,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w, kantyzc-9Onoh4P/yGk,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q, marc.zyngier-5wv7dgnIgG8

On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> For arm64, there is no I/O space as other architectural platforms, such as
> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> known port addresses are used to control the corresponding target devices, for
> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> normal MMIO mode in using.

This has nothing to do with arm64. Hardware with this kind of indirect
bus access could be integrated with a variety of CPU architectures. It
simply hasn't been, yet.

> To drive these devices, this patch introduces a method named indirect-IO.
> In this method the in/out pair in arch/arm64/include/asm/io.h will be
> redefined. When upper layer drivers call in/out with those known legacy port
> addresses to access the peripherals, the hooking functions corrresponding to
> those target peripherals will be called. Through this way, those upper layer
> drivers which depend on in/out can run on Hip06 without any changes.

As above, this has nothing to do with arm64, and as such, should live in
generic code, exactly as we would do if we had higher-level ISA
accessor ops.

Regardless, given the multi-instance case, I don't think this is
sufficient in general (and I think we need higher-level ISA accessors
to handle the indirection).

[...]

> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
> new file mode 100644
> index 0000000..6ae0787
> --- /dev/null
> +++ b/arch/arm64/include/asm/extio.h

> +#ifndef __LINUX_EXTIO_H
> +#define __LINUX_EXTIO_H

This doesn't match the file naming, __ASM_EXTIO_H would be consistent
with other arm64 headers.

> +
> +struct extio_ops {
> +	unsigned long start;/* inclusive, sys io addr */
> +	unsigned long end;/* inclusive, sys io addr */

Please put whitespace before inline comments.

[...]

> +type in##bw(unsigned long addr)						\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		return read##bw(PCI_IOBASE + addr);			\
> +	return arm64_extio_ops->pfin ?					\
> +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
> +			addr, sizeof(type)) : -1;			\
> +}									\
> +									\
> +void out##bw(type value, unsigned long addr)				\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		write##bw(value, PCI_IOBASE + addr);			\
> +	else								\
> +		if (arm64_extio_ops->pfout)				\
> +			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> +				addr, value, sizeof(type));		\
> +}									\
> +									\
> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		reads##bw(PCI_IOBASE + addr, buffer, count);		\
> +	else								\
> +		if (arm64_extio_ops->pfins)				\
> +			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
> +				addr, buffer, sizeof(type), count);	\
> +}									\
> +									\
> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		writes##bw(PCI_IOBASE + addr, buffer, count);		\
> +	else								\
> +		if (arm64_extio_ops->pfouts)				\
> +			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
> +				addr, buffer, sizeof(type), count);	\
> +}
> +

So all PCI I/O will be slowed down by irrelevant checks when this is
enabled?

[...]

> +static inline void arm64_set_extops(struct extio_ops *ops)
> +{
> +	if (ops)
> +		WRITE_ONCE(arm64_extio_ops, ops);
> +}

Why WRITE_ONCE()?

Is this not protected/propagated by some synchronisation mechanism?

WRITE_ONCE() is not sufficient to ensure that this is consistently
observed by readers, and regardless, I don't see READ_ONCE() anywhere in
this patch.

This looks very suspicious.

Thanks,
Mark.
--
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] 286+ messages in thread

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08 12:03     ` Mark Rutland
  0 siblings, 0 replies; 286+ messages in thread
From: Mark Rutland @ 2016-11-08 12:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> For arm64, there is no I/O space as other architectural platforms, such as
> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> known port addresses are used to control the corresponding target devices, for
> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> normal MMIO mode in using.

This has nothing to do with arm64. Hardware with this kind of indirect
bus access could be integrated with a variety of CPU architectures. It
simply hasn't been, yet.

> To drive these devices, this patch introduces a method named indirect-IO.
> In this method the in/out pair in arch/arm64/include/asm/io.h will be
> redefined. When upper layer drivers call in/out with those known legacy port
> addresses to access the peripherals, the hooking functions corrresponding to
> those target peripherals will be called. Through this way, those upper layer
> drivers which depend on in/out can run on Hip06 without any changes.

As above, this has nothing to do with arm64, and as such, should live in
generic code, exactly as we would do if we had higher-level ISA
accessor ops.

Regardless, given the multi-instance case, I don't think this is
sufficient in general (and I think we need higher-level ISA accessors
to handle the indirection).

[...]

> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
> new file mode 100644
> index 0000000..6ae0787
> --- /dev/null
> +++ b/arch/arm64/include/asm/extio.h

> +#ifndef __LINUX_EXTIO_H
> +#define __LINUX_EXTIO_H

This doesn't match the file naming, __ASM_EXTIO_H would be consistent
with other arm64 headers.

> +
> +struct extio_ops {
> +	unsigned long start;/* inclusive, sys io addr */
> +	unsigned long end;/* inclusive, sys io addr */

Please put whitespace before inline comments.

[...]

> +type in##bw(unsigned long addr)						\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		return read##bw(PCI_IOBASE + addr);			\
> +	return arm64_extio_ops->pfin ?					\
> +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
> +			addr, sizeof(type)) : -1;			\
> +}									\
> +									\
> +void out##bw(type value, unsigned long addr)				\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		write##bw(value, PCI_IOBASE + addr);			\
> +	else								\
> +		if (arm64_extio_ops->pfout)				\
> +			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> +				addr, value, sizeof(type));		\
> +}									\
> +									\
> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		reads##bw(PCI_IOBASE + addr, buffer, count);		\
> +	else								\
> +		if (arm64_extio_ops->pfins)				\
> +			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
> +				addr, buffer, sizeof(type), count);	\
> +}									\
> +									\
> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		writes##bw(PCI_IOBASE + addr, buffer, count);		\
> +	else								\
> +		if (arm64_extio_ops->pfouts)				\
> +			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
> +				addr, buffer, sizeof(type), count);	\
> +}
> +

So all PCI I/O will be slowed down by irrelevant checks when this is
enabled?

[...]

> +static inline void arm64_set_extops(struct extio_ops *ops)
> +{
> +	if (ops)
> +		WRITE_ONCE(arm64_extio_ops, ops);
> +}

Why WRITE_ONCE()?

Is this not protected/propagated by some synchronisation mechanism?

WRITE_ONCE() is not sufficient to ensure that this is consistently
observed by readers, and regardless, I don't see READ_ONCE() anywhere in
this patch.

This looks very suspicious.

Thanks,
Mark.

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-11-08 12:03     ` Mark Rutland
  (?)
  (?)
@ 2016-11-08 16:09       ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-08 16:09 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Mark Rutland, zhichang.yuan, gabriele.paoloni, benh, will.deacon,
	linuxarm, lorenzo.pieralisi, xuwei5, linux-serial,
	catalin.marinas, devicetree, minyard, marc.zyngier, liviu.dudau,
	john.garry, zourongrong, robh+dt, bhelgaas, kantyzc,
	zhichang.yuan02, linux-pci, linux-kernel, olof

On Tuesday, November 8, 2016 12:03:23 PM CET Mark Rutland wrote:
> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> > For arm64, there is no I/O space as other architectural platforms, such as
> > X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> > such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> > known port addresses are used to control the corresponding target devices, for
> > example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> > normal MMIO mode in using.
> 
> This has nothing to do with arm64. Hardware with this kind of indirect
> bus access could be integrated with a variety of CPU architectures. It
> simply hasn't been, yet.

Actually PowerPC has a vaguely similar mechanism.

> > To drive these devices, this patch introduces a method named indirect-IO.
> > In this method the in/out pair in arch/arm64/include/asm/io.h will be
> > redefined. When upper layer drivers call in/out with those known legacy port
> > addresses to access the peripherals, the hooking functions corrresponding to
> > those target peripherals will be called. Through this way, those upper layer
> > drivers which depend on in/out can run on Hip06 without any changes.
> 
> As above, this has nothing to do with arm64, and as such, should live in
> generic code, exactly as we would do if we had higher-level ISA
> accessor ops.
> 
> Regardless, given the multi-instance case, I don't think this is
> sufficient in general (and I think we need higher-level ISA accessors
> to handle the indirection).

I think it is rather unlikely that we have to deal with multiple
instances in the future, it's more likely that future platforms
won't have any I/O ports at all, which is why I was advocating for
simplicity here.

> > +type in##bw(unsigned long addr)						\
> > +{									\
> > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > +			arm64_extio_ops->end < addr)			\
> > +		return read##bw(PCI_IOBASE + addr);			\
> > +	return arm64_extio_ops->pfin ?					\
> > +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
> > +			addr, sizeof(type)) : -1;			\
> > +}									\
> > +									\
> > +void out##bw(type value, unsigned long addr)				\
> > +{									\
> > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > +			arm64_extio_ops->end < addr)			\
> > +		write##bw(value, PCI_IOBASE + addr);			\
> > +	else								\
> > +		if (arm64_extio_ops->pfout)				\
> > +			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > +				addr, value, sizeof(type));		\
> > +}									\
> > +									\
> > +void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
> > +{									\
> > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > +			arm64_extio_ops->end < addr)			\
> > +		reads##bw(PCI_IOBASE + addr, buffer, count);		\
> > +	else								\
> > +		if (arm64_extio_ops->pfins)				\
> > +			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
> > +				addr, buffer, sizeof(type), count);	\
> > +}									\
> > +									\
> > +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
> > +{									\
> > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > +			arm64_extio_ops->end < addr)			\
> > +		writes##bw(PCI_IOBASE + addr, buffer, count);		\
> > +	else								\
> > +		if (arm64_extio_ops->pfouts)				\
> > +			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
> > +				addr, buffer, sizeof(type), count);	\
> > +}
> > +
> 
> So all PCI I/O will be slowed down by irrelevant checks when this is
> enabled?

I don't see a better alternative. I earlier suggested having these
out of line so we don't grow the object code too much when it is
enabled.

Performance of PIO accessors is not an issue here though, any bus
access will by definition be orders of magnitude slower than the
added branches and dereferences here.

> [...]
> 
> > +static inline void arm64_set_extops(struct extio_ops *ops)
> > +{
> > +	if (ops)
> > +		WRITE_ONCE(arm64_extio_ops, ops);
> > +}
> 
> Why WRITE_ONCE()?
> 
> Is this not protected/propagated by some synchronisation mechanism?
> 
> WRITE_ONCE() is not sufficient to ensure that this is consistently
> observed by readers, and regardless, I don't see READ_ONCE() anywhere in
> this patch.
> 
> This looks very suspicious.

Agreed, this looks wrong.

	Arnd

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08 16:09       ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-08 16:09 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Mark Rutland, catalin.marinas, gabriele.paoloni, benh,
	will.deacon, linuxarm, lorenzo.pieralisi, xuwei5, linux-serial,
	linux-pci, devicetree, minyard, marc.zyngier, liviu.dudau,
	john.garry, olof, robh+dt, bhelgaas, kantyzc, zhichang.yuan02,
	linux-kernel, zhichang.yuan, zourongrong

On Tuesday, November 8, 2016 12:03:23 PM CET Mark Rutland wrote:
> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> > For arm64, there is no I/O space as other architectural platforms, such as
> > X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> > such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> > known port addresses are used to control the corresponding target devices, for
> > example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> > normal MMIO mode in using.
> 
> This has nothing to do with arm64. Hardware with this kind of indirect
> bus access could be integrated with a variety of CPU architectures. It
> simply hasn't been, yet.

Actually PowerPC has a vaguely similar mechanism.

> > To drive these devices, this patch introduces a method named indirect-IO.
> > In this method the in/out pair in arch/arm64/include/asm/io.h will be
> > redefined. When upper layer drivers call in/out with those known legacy port
> > addresses to access the peripherals, the hooking functions corrresponding to
> > those target peripherals will be called. Through this way, those upper layer
> > drivers which depend on in/out can run on Hip06 without any changes.
> 
> As above, this has nothing to do with arm64, and as such, should live in
> generic code, exactly as we would do if we had higher-level ISA
> accessor ops.
> 
> Regardless, given the multi-instance case, I don't think this is
> sufficient in general (and I think we need higher-level ISA accessors
> to handle the indirection).

I think it is rather unlikely that we have to deal with multiple
instances in the future, it's more likely that future platforms
won't have any I/O ports at all, which is why I was advocating for
simplicity here.

> > +type in##bw(unsigned long addr)						\
> > +{									\
> > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > +			arm64_extio_ops->end < addr)			\
> > +		return read##bw(PCI_IOBASE + addr);			\
> > +	return arm64_extio_ops->pfin ?					\
> > +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
> > +			addr, sizeof(type)) : -1;			\
> > +}									\
> > +									\
> > +void out##bw(type value, unsigned long addr)				\
> > +{									\
> > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > +			arm64_extio_ops->end < addr)			\
> > +		write##bw(value, PCI_IOBASE + addr);			\
> > +	else								\
> > +		if (arm64_extio_ops->pfout)				\
> > +			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > +				addr, value, sizeof(type));		\
> > +}									\
> > +									\
> > +void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
> > +{									\
> > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > +			arm64_extio_ops->end < addr)			\
> > +		reads##bw(PCI_IOBASE + addr, buffer, count);		\
> > +	else								\
> > +		if (arm64_extio_ops->pfins)				\
> > +			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
> > +				addr, buffer, sizeof(type), count);	\
> > +}									\
> > +									\
> > +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
> > +{									\
> > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > +			arm64_extio_ops->end < addr)			\
> > +		writes##bw(PCI_IOBASE + addr, buffer, count);		\
> > +	else								\
> > +		if (arm64_extio_ops->pfouts)				\
> > +			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
> > +				addr, buffer, sizeof(type), count);	\
> > +}
> > +
> 
> So all PCI I/O will be slowed down by irrelevant checks when this is
> enabled?

I don't see a better alternative. I earlier suggested having these
out of line so we don't grow the object code too much when it is
enabled.

Performance of PIO accessors is not an issue here though, any bus
access will by definition be orders of magnitude slower than the
added branches and dereferences here.

> [...]
> 
> > +static inline void arm64_set_extops(struct extio_ops *ops)
> > +{
> > +	if (ops)
> > +		WRITE_ONCE(arm64_extio_ops, ops);
> > +}
> 
> Why WRITE_ONCE()?
> 
> Is this not protected/propagated by some synchronisation mechanism?
> 
> WRITE_ONCE() is not sufficient to ensure that this is consistently
> observed by readers, and regardless, I don't see READ_ONCE() anywhere in
> this patch.
> 
> This looks very suspicious.

Agreed, this looks wrong.

	Arnd

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08 16:09       ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-08 16:09 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Mark Rutland, catalin.marinas, gabriele.paoloni, benh,
	will.deacon, linuxarm, lorenzo.pieralisi, xuwei5, linux-serial,
	linux-pci, devicetree, minyard, marc.zyngier, liviu.dudau,
	john.garry, olof, robh+dt, bhelgaas, kantyzc, zhichang.yuan02,
	linux-kernel, zhichang.yuan, zourongrong

On Tuesday, November 8, 2016 12:03:23 PM CET Mark Rutland wrote:
> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> > For arm64, there is no I/O space as other architectural platforms, such as
> > X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> > such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> > known port addresses are used to control the corresponding target devices, for
> > example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> > normal MMIO mode in using.
> 
> This has nothing to do with arm64. Hardware with this kind of indirect
> bus access could be integrated with a variety of CPU architectures. It
> simply hasn't been, yet.

Actually PowerPC has a vaguely similar mechanism.

> > To drive these devices, this patch introduces a method named indirect-IO.
> > In this method the in/out pair in arch/arm64/include/asm/io.h will be
> > redefined. When upper layer drivers call in/out with those known legacy port
> > addresses to access the peripherals, the hooking functions corrresponding to
> > those target peripherals will be called. Through this way, those upper layer
> > drivers which depend on in/out can run on Hip06 without any changes.
> 
> As above, this has nothing to do with arm64, and as such, should live in
> generic code, exactly as we would do if we had higher-level ISA
> accessor ops.
> 
> Regardless, given the multi-instance case, I don't think this is
> sufficient in general (and I think we need higher-level ISA accessors
> to handle the indirection).

I think it is rather unlikely that we have to deal with multiple
instances in the future, it's more likely that future platforms
won't have any I/O ports at all, which is why I was advocating for
simplicity here.

> > +type in##bw(unsigned long addr)						\
> > +{									\
> > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > +			arm64_extio_ops->end < addr)			\
> > +		return read##bw(PCI_IOBASE + addr);			\
> > +	return arm64_extio_ops->pfin ?					\
> > +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
> > +			addr, sizeof(type)) : -1;			\
> > +}									\
> > +									\
> > +void out##bw(type value, unsigned long addr)				\
> > +{									\
> > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > +			arm64_extio_ops->end < addr)			\
> > +		write##bw(value, PCI_IOBASE + addr);			\
> > +	else								\
> > +		if (arm64_extio_ops->pfout)				\
> > +			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > +				addr, value, sizeof(type));		\
> > +}									\
> > +									\
> > +void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
> > +{									\
> > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > +			arm64_extio_ops->end < addr)			\
> > +		reads##bw(PCI_IOBASE + addr, buffer, count);		\
> > +	else								\
> > +		if (arm64_extio_ops->pfins)				\
> > +			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
> > +				addr, buffer, sizeof(type), count);	\
> > +}									\
> > +									\
> > +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
> > +{									\
> > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > +			arm64_extio_ops->end < addr)			\
> > +		writes##bw(PCI_IOBASE + addr, buffer, count);		\
> > +	else								\
> > +		if (arm64_extio_ops->pfouts)				\
> > +			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
> > +				addr, buffer, sizeof(type), count);	\
> > +}
> > +
> 
> So all PCI I/O will be slowed down by irrelevant checks when this is
> enabled?

I don't see a better alternative. I earlier suggested having these
out of line so we don't grow the object code too much when it is
enabled.

Performance of PIO accessors is not an issue here though, any bus
access will by definition be orders of magnitude slower than the
added branches and dereferences here.

> [...]
> 
> > +static inline void arm64_set_extops(struct extio_ops *ops)
> > +{
> > +	if (ops)
> > +		WRITE_ONCE(arm64_extio_ops, ops);
> > +}
> 
> Why WRITE_ONCE()?
> 
> Is this not protected/propagated by some synchronisation mechanism?
> 
> WRITE_ONCE() is not sufficient to ensure that this is consistently
> observed by readers, and regardless, I don't see READ_ONCE() anywhere in
> this patch.
> 
> This looks very suspicious.

Agreed, this looks wrong.

	Arnd

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08 16:09       ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-08 16:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday, November 8, 2016 12:03:23 PM CET Mark Rutland wrote:
> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> > For arm64, there is no I/O space as other architectural platforms, such as
> > X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> > such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> > known port addresses are used to control the corresponding target devices, for
> > example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> > normal MMIO mode in using.
> 
> This has nothing to do with arm64. Hardware with this kind of indirect
> bus access could be integrated with a variety of CPU architectures. It
> simply hasn't been, yet.

Actually PowerPC has a vaguely similar mechanism.

> > To drive these devices, this patch introduces a method named indirect-IO.
> > In this method the in/out pair in arch/arm64/include/asm/io.h will be
> > redefined. When upper layer drivers call in/out with those known legacy port
> > addresses to access the peripherals, the hooking functions corrresponding to
> > those target peripherals will be called. Through this way, those upper layer
> > drivers which depend on in/out can run on Hip06 without any changes.
> 
> As above, this has nothing to do with arm64, and as such, should live in
> generic code, exactly as we would do if we had higher-level ISA
> accessor ops.
> 
> Regardless, given the multi-instance case, I don't think this is
> sufficient in general (and I think we need higher-level ISA accessors
> to handle the indirection).

I think it is rather unlikely that we have to deal with multiple
instances in the future, it's more likely that future platforms
won't have any I/O ports at all, which is why I was advocating for
simplicity here.

> > +type in##bw(unsigned long addr)						\
> > +{									\
> > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > +			arm64_extio_ops->end < addr)			\
> > +		return read##bw(PCI_IOBASE + addr);			\
> > +	return arm64_extio_ops->pfin ?					\
> > +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
> > +			addr, sizeof(type)) : -1;			\
> > +}									\
> > +									\
> > +void out##bw(type value, unsigned long addr)				\
> > +{									\
> > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > +			arm64_extio_ops->end < addr)			\
> > +		write##bw(value, PCI_IOBASE + addr);			\
> > +	else								\
> > +		if (arm64_extio_ops->pfout)				\
> > +			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > +				addr, value, sizeof(type));		\
> > +}									\
> > +									\
> > +void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
> > +{									\
> > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > +			arm64_extio_ops->end < addr)			\
> > +		reads##bw(PCI_IOBASE + addr, buffer, count);		\
> > +	else								\
> > +		if (arm64_extio_ops->pfins)				\
> > +			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
> > +				addr, buffer, sizeof(type), count);	\
> > +}									\
> > +									\
> > +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
> > +{									\
> > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > +			arm64_extio_ops->end < addr)			\
> > +		writes##bw(PCI_IOBASE + addr, buffer, count);		\
> > +	else								\
> > +		if (arm64_extio_ops->pfouts)				\
> > +			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
> > +				addr, buffer, sizeof(type), count);	\
> > +}
> > +
> 
> So all PCI I/O will be slowed down by irrelevant checks when this is
> enabled?

I don't see a better alternative. I earlier suggested having these
out of line so we don't grow the object code too much when it is
enabled.

Performance of PIO accessors is not an issue here though, any bus
access will by definition be orders of magnitude slower than the
added branches and dereferences here.

> [...]
> 
> > +static inline void arm64_set_extops(struct extio_ops *ops)
> > +{
> > +	if (ops)
> > +		WRITE_ONCE(arm64_extio_ops, ops);
> > +}
> 
> Why WRITE_ONCE()?
> 
> Is this not protected/propagated by some synchronisation mechanism?
> 
> WRITE_ONCE() is not sufficient to ensure that this is consistently
> observed by readers, and regardless, I don't see READ_ONCE() anywhere in
> this patch.
> 
> This looks very suspicious.

Agreed, this looks wrong.

	Arnd

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-11-08  3:47   ` zhichang.yuan
  (?)
@ 2016-11-08 16:12     ` Will Deacon
  -1 siblings, 0 replies; 286+ messages in thread
From: Will Deacon @ 2016-11-08 16:12 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: catalin.marinas, robh+dt, bhelgaas, mark.rutland, olof, arnd,
	linux-arm-kernel, lorenzo.pieralisi, linux-kernel, linuxarm,
	devicetree, linux-pci, linux-serial, minyard, benh, liviu.dudau,
	zourongrong, john.garry, gabriele.paoloni, zhichang.yuan02,
	kantyzc, xuwei5

On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> For arm64, there is no I/O space as other architectural platforms, such as
> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> known port addresses are used to control the corresponding target devices, for
> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> normal MMIO mode in using.
> 
> To drive these devices, this patch introduces a method named indirect-IO.
> In this method the in/out pair in arch/arm64/include/asm/io.h will be
> redefined. When upper layer drivers call in/out with those known legacy port
> addresses to access the peripherals, the hooking functions corrresponding to
> those target peripherals will be called. Through this way, those upper layer
> drivers which depend on in/out can run on Hip06 without any changes.
> 
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
>  arch/arm64/Kconfig             |  6 +++
>  arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>  arch/arm64/include/asm/io.h    | 29 +++++++++++++
>  arch/arm64/kernel/Makefile     |  1 +
>  arch/arm64/kernel/extio.c      | 27 ++++++++++++
>  5 files changed, 157 insertions(+)
>  create mode 100644 arch/arm64/include/asm/extio.h
>  create mode 100644 arch/arm64/kernel/extio.c
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 969ef88..b44070b 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>         default 16
>  
> +config ARM64_INDIRECT_PIO
> +	bool "access peripherals with legacy I/O port"
> +	help
> +	  Support special accessors for ISA I/O devices. This is needed for
> +	  SoCs that do not support standard read/write for the ISA range.
> +
>  config NO_IOPORT_MAP
>  	def_bool y if !PCI
>  
> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
> new file mode 100644
> index 0000000..6ae0787
> --- /dev/null
> +++ b/arch/arm64/include/asm/extio.h
> @@ -0,0 +1,94 @@
> +/*
> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef __LINUX_EXTIO_H
> +#define __LINUX_EXTIO_H
> +
> +struct extio_ops {
> +	unsigned long start;/* inclusive, sys io addr */
> +	unsigned long end;/* inclusive, sys io addr */
> +
> +	u64 (*pfin)(void *devobj, unsigned long ptaddr,	size_t dlen);
> +	void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
> +					size_t dlen);
> +	u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
> +				size_t dlen, unsigned int count);
> +	void (*pfouts)(void *devobj, unsigned long ptaddr,
> +				const void *outbuf, size_t dlen,
> +				unsigned int count);
> +	void *devpara;
> +};
> +
> +extern struct extio_ops *arm64_extio_ops;
> +
> +#define DECLARE_EXTIO(bw, type)						\
> +extern type in##bw(unsigned long addr);					\
> +extern void out##bw(type value, unsigned long addr);			\
> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
> +
> +#define BUILD_EXTIO(bw, type)						\
> +type in##bw(unsigned long addr)						\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		return read##bw(PCI_IOBASE + addr);			\
> +	return arm64_extio_ops->pfin ?					\
> +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
> +			addr, sizeof(type)) : -1;			\
> +}									\
> +									\
> +void out##bw(type value, unsigned long addr)				\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		write##bw(value, PCI_IOBASE + addr);			\
> +	else								\
> +		if (arm64_extio_ops->pfout)				\
> +			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> +				addr, value, sizeof(type));		\
> +}									\
> +									\
> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		reads##bw(PCI_IOBASE + addr, buffer, count);		\
> +	else								\
> +		if (arm64_extio_ops->pfins)				\
> +			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
> +				addr, buffer, sizeof(type), count);	\
> +}									\
> +									\
> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		writes##bw(PCI_IOBASE + addr, buffer, count);		\
> +	else								\
> +		if (arm64_extio_ops->pfouts)				\
> +			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
> +				addr, buffer, sizeof(type), count);	\
> +}
> +
> +static inline void arm64_set_extops(struct extio_ops *ops)
> +{
> +	if (ops)
> +		WRITE_ONCE(arm64_extio_ops, ops);

Why does this need to be WRITE_ONCE? You don't have READ_ONCE on the reader
side. Also, what if multiple drivers want to set different ops for distinct
address ranges?

> +}
> +
> +#endif /* __LINUX_EXTIO_H*/
> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> index 0bba427..136735d 100644
> --- a/arch/arm64/include/asm/io.h
> +++ b/arch/arm64/include/asm/io.h
> @@ -31,6 +31,7 @@
>  #include <asm/early_ioremap.h>
>  #include <asm/alternative.h>
>  #include <asm/cpufeature.h>
> +#include <asm/extio.h>
>  
>  #include <xen/xen.h>
>  
> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>  #define IO_SPACE_LIMIT		(PCI_IO_SIZE - 1)
>  #define PCI_IOBASE		((void __iomem *)PCI_IO_START)
>  
> +
> +/*
> + * redefine the in(s)b/out(s)b for indirect-IO.
> + */
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +#define inb inb
> +#define outb outb
> +#define insb insb
> +#define outsb outsb
> +/* external declaration */
> +DECLARE_EXTIO(b, u8)
> +
> +#define inw inw
> +#define outw outw
> +#define insw insw
> +#define outsw outsw
> +
> +DECLARE_EXTIO(w, u16)
> +
> +#define inl inl
> +#define outl outl
> +#define insl insl
> +#define outsl outsl
> +
> +DECLARE_EXTIO(l, u32)
> +#endif
> +
> +
>  /*
>   * String version of I/O memory access operations.
>   */
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 7d66bba..60e0482 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
>  					   sys_compat.o entry32.o
>  arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
>  arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO)	+= extio.o
>  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
>  arm64-obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o perf_callchain.o
>  arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> new file mode 100644
> index 0000000..647b3fa
> --- /dev/null
> +++ b/arch/arm64/kernel/extio.c
> @@ -0,0 +1,27 @@
> +/*
> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/io.h>
> +
> +struct extio_ops *arm64_extio_ops;
> +
> +
> +BUILD_EXTIO(b, u8)
> +
> +BUILD_EXTIO(w, u16)
> +
> +BUILD_EXTIO(l, u32)

Is there no way to make this slightly more generic, so that it can be
re-used elsewhere? For example, if struct extio_ops was common, then
you could have the singleton (which maybe should be an interval tree?),
type definition, setter function and the BUILD_EXTIO invocations
somewhere generic, rather than squirelled away in the arch backend.

Will

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08 16:12     ` Will Deacon
  0 siblings, 0 replies; 286+ messages in thread
From: Will Deacon @ 2016-11-08 16:12 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: mark.rutland, gabriele.paoloni, benh, liviu.dudau, linuxarm,
	lorenzo.pieralisi, arnd, xuwei5, linux-serial, catalin.marinas,
	devicetree, minyard, john.garry, zourongrong, robh+dt, bhelgaas,
	kantyzc, zhichang.yuan02, linux-arm-kernel, linux-pci,
	linux-kernel, olof

On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> For arm64, there is no I/O space as other architectural platforms, such as
> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> known port addresses are used to control the corresponding target devices, for
> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> normal MMIO mode in using.
> 
> To drive these devices, this patch introduces a method named indirect-IO.
> In this method the in/out pair in arch/arm64/include/asm/io.h will be
> redefined. When upper layer drivers call in/out with those known legacy port
> addresses to access the peripherals, the hooking functions corrresponding to
> those target peripherals will be called. Through this way, those upper layer
> drivers which depend on in/out can run on Hip06 without any changes.
> 
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
>  arch/arm64/Kconfig             |  6 +++
>  arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>  arch/arm64/include/asm/io.h    | 29 +++++++++++++
>  arch/arm64/kernel/Makefile     |  1 +
>  arch/arm64/kernel/extio.c      | 27 ++++++++++++
>  5 files changed, 157 insertions(+)
>  create mode 100644 arch/arm64/include/asm/extio.h
>  create mode 100644 arch/arm64/kernel/extio.c
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 969ef88..b44070b 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>         default 16
>  
> +config ARM64_INDIRECT_PIO
> +	bool "access peripherals with legacy I/O port"
> +	help
> +	  Support special accessors for ISA I/O devices. This is needed for
> +	  SoCs that do not support standard read/write for the ISA range.
> +
>  config NO_IOPORT_MAP
>  	def_bool y if !PCI
>  
> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
> new file mode 100644
> index 0000000..6ae0787
> --- /dev/null
> +++ b/arch/arm64/include/asm/extio.h
> @@ -0,0 +1,94 @@
> +/*
> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef __LINUX_EXTIO_H
> +#define __LINUX_EXTIO_H
> +
> +struct extio_ops {
> +	unsigned long start;/* inclusive, sys io addr */
> +	unsigned long end;/* inclusive, sys io addr */
> +
> +	u64 (*pfin)(void *devobj, unsigned long ptaddr,	size_t dlen);
> +	void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
> +					size_t dlen);
> +	u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
> +				size_t dlen, unsigned int count);
> +	void (*pfouts)(void *devobj, unsigned long ptaddr,
> +				const void *outbuf, size_t dlen,
> +				unsigned int count);
> +	void *devpara;
> +};
> +
> +extern struct extio_ops *arm64_extio_ops;
> +
> +#define DECLARE_EXTIO(bw, type)						\
> +extern type in##bw(unsigned long addr);					\
> +extern void out##bw(type value, unsigned long addr);			\
> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
> +
> +#define BUILD_EXTIO(bw, type)						\
> +type in##bw(unsigned long addr)						\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		return read##bw(PCI_IOBASE + addr);			\
> +	return arm64_extio_ops->pfin ?					\
> +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
> +			addr, sizeof(type)) : -1;			\
> +}									\
> +									\
> +void out##bw(type value, unsigned long addr)				\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		write##bw(value, PCI_IOBASE + addr);			\
> +	else								\
> +		if (arm64_extio_ops->pfout)				\
> +			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> +				addr, value, sizeof(type));		\
> +}									\
> +									\
> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		reads##bw(PCI_IOBASE + addr, buffer, count);		\
> +	else								\
> +		if (arm64_extio_ops->pfins)				\
> +			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
> +				addr, buffer, sizeof(type), count);	\
> +}									\
> +									\
> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		writes##bw(PCI_IOBASE + addr, buffer, count);		\
> +	else								\
> +		if (arm64_extio_ops->pfouts)				\
> +			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
> +				addr, buffer, sizeof(type), count);	\
> +}
> +
> +static inline void arm64_set_extops(struct extio_ops *ops)
> +{
> +	if (ops)
> +		WRITE_ONCE(arm64_extio_ops, ops);

Why does this need to be WRITE_ONCE? You don't have READ_ONCE on the reader
side. Also, what if multiple drivers want to set different ops for distinct
address ranges?

> +}
> +
> +#endif /* __LINUX_EXTIO_H*/
> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> index 0bba427..136735d 100644
> --- a/arch/arm64/include/asm/io.h
> +++ b/arch/arm64/include/asm/io.h
> @@ -31,6 +31,7 @@
>  #include <asm/early_ioremap.h>
>  #include <asm/alternative.h>
>  #include <asm/cpufeature.h>
> +#include <asm/extio.h>
>  
>  #include <xen/xen.h>
>  
> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>  #define IO_SPACE_LIMIT		(PCI_IO_SIZE - 1)
>  #define PCI_IOBASE		((void __iomem *)PCI_IO_START)
>  
> +
> +/*
> + * redefine the in(s)b/out(s)b for indirect-IO.
> + */
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +#define inb inb
> +#define outb outb
> +#define insb insb
> +#define outsb outsb
> +/* external declaration */
> +DECLARE_EXTIO(b, u8)
> +
> +#define inw inw
> +#define outw outw
> +#define insw insw
> +#define outsw outsw
> +
> +DECLARE_EXTIO(w, u16)
> +
> +#define inl inl
> +#define outl outl
> +#define insl insl
> +#define outsl outsl
> +
> +DECLARE_EXTIO(l, u32)
> +#endif
> +
> +
>  /*
>   * String version of I/O memory access operations.
>   */
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 7d66bba..60e0482 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
>  					   sys_compat.o entry32.o
>  arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
>  arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO)	+= extio.o
>  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
>  arm64-obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o perf_callchain.o
>  arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> new file mode 100644
> index 0000000..647b3fa
> --- /dev/null
> +++ b/arch/arm64/kernel/extio.c
> @@ -0,0 +1,27 @@
> +/*
> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/io.h>
> +
> +struct extio_ops *arm64_extio_ops;
> +
> +
> +BUILD_EXTIO(b, u8)
> +
> +BUILD_EXTIO(w, u16)
> +
> +BUILD_EXTIO(l, u32)

Is there no way to make this slightly more generic, so that it can be
re-used elsewhere? For example, if struct extio_ops was common, then
you could have the singleton (which maybe should be an interval tree?),
type definition, setter function and the BUILD_EXTIO invocations
somewhere generic, rather than squirelled away in the arch backend.

Will

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08 16:12     ` Will Deacon
  0 siblings, 0 replies; 286+ messages in thread
From: Will Deacon @ 2016-11-08 16:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> For arm64, there is no I/O space as other architectural platforms, such as
> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> known port addresses are used to control the corresponding target devices, for
> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> normal MMIO mode in using.
> 
> To drive these devices, this patch introduces a method named indirect-IO.
> In this method the in/out pair in arch/arm64/include/asm/io.h will be
> redefined. When upper layer drivers call in/out with those known legacy port
> addresses to access the peripherals, the hooking functions corrresponding to
> those target peripherals will be called. Through this way, those upper layer
> drivers which depend on in/out can run on Hip06 without any changes.
> 
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
>  arch/arm64/Kconfig             |  6 +++
>  arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>  arch/arm64/include/asm/io.h    | 29 +++++++++++++
>  arch/arm64/kernel/Makefile     |  1 +
>  arch/arm64/kernel/extio.c      | 27 ++++++++++++
>  5 files changed, 157 insertions(+)
>  create mode 100644 arch/arm64/include/asm/extio.h
>  create mode 100644 arch/arm64/kernel/extio.c
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 969ef88..b44070b 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>         default 16
>  
> +config ARM64_INDIRECT_PIO
> +	bool "access peripherals with legacy I/O port"
> +	help
> +	  Support special accessors for ISA I/O devices. This is needed for
> +	  SoCs that do not support standard read/write for the ISA range.
> +
>  config NO_IOPORT_MAP
>  	def_bool y if !PCI
>  
> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
> new file mode 100644
> index 0000000..6ae0787
> --- /dev/null
> +++ b/arch/arm64/include/asm/extio.h
> @@ -0,0 +1,94 @@
> +/*
> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef __LINUX_EXTIO_H
> +#define __LINUX_EXTIO_H
> +
> +struct extio_ops {
> +	unsigned long start;/* inclusive, sys io addr */
> +	unsigned long end;/* inclusive, sys io addr */
> +
> +	u64 (*pfin)(void *devobj, unsigned long ptaddr,	size_t dlen);
> +	void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
> +					size_t dlen);
> +	u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
> +				size_t dlen, unsigned int count);
> +	void (*pfouts)(void *devobj, unsigned long ptaddr,
> +				const void *outbuf, size_t dlen,
> +				unsigned int count);
> +	void *devpara;
> +};
> +
> +extern struct extio_ops *arm64_extio_ops;
> +
> +#define DECLARE_EXTIO(bw, type)						\
> +extern type in##bw(unsigned long addr);					\
> +extern void out##bw(type value, unsigned long addr);			\
> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
> +
> +#define BUILD_EXTIO(bw, type)						\
> +type in##bw(unsigned long addr)						\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		return read##bw(PCI_IOBASE + addr);			\
> +	return arm64_extio_ops->pfin ?					\
> +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
> +			addr, sizeof(type)) : -1;			\
> +}									\
> +									\
> +void out##bw(type value, unsigned long addr)				\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		write##bw(value, PCI_IOBASE + addr);			\
> +	else								\
> +		if (arm64_extio_ops->pfout)				\
> +			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> +				addr, value, sizeof(type));		\
> +}									\
> +									\
> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		reads##bw(PCI_IOBASE + addr, buffer, count);		\
> +	else								\
> +		if (arm64_extio_ops->pfins)				\
> +			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
> +				addr, buffer, sizeof(type), count);	\
> +}									\
> +									\
> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
> +{									\
> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> +			arm64_extio_ops->end < addr)			\
> +		writes##bw(PCI_IOBASE + addr, buffer, count);		\
> +	else								\
> +		if (arm64_extio_ops->pfouts)				\
> +			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
> +				addr, buffer, sizeof(type), count);	\
> +}
> +
> +static inline void arm64_set_extops(struct extio_ops *ops)
> +{
> +	if (ops)
> +		WRITE_ONCE(arm64_extio_ops, ops);

Why does this need to be WRITE_ONCE? You don't have READ_ONCE on the reader
side. Also, what if multiple drivers want to set different ops for distinct
address ranges?

> +}
> +
> +#endif /* __LINUX_EXTIO_H*/
> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> index 0bba427..136735d 100644
> --- a/arch/arm64/include/asm/io.h
> +++ b/arch/arm64/include/asm/io.h
> @@ -31,6 +31,7 @@
>  #include <asm/early_ioremap.h>
>  #include <asm/alternative.h>
>  #include <asm/cpufeature.h>
> +#include <asm/extio.h>
>  
>  #include <xen/xen.h>
>  
> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>  #define IO_SPACE_LIMIT		(PCI_IO_SIZE - 1)
>  #define PCI_IOBASE		((void __iomem *)PCI_IO_START)
>  
> +
> +/*
> + * redefine the in(s)b/out(s)b for indirect-IO.
> + */
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +#define inb inb
> +#define outb outb
> +#define insb insb
> +#define outsb outsb
> +/* external declaration */
> +DECLARE_EXTIO(b, u8)
> +
> +#define inw inw
> +#define outw outw
> +#define insw insw
> +#define outsw outsw
> +
> +DECLARE_EXTIO(w, u16)
> +
> +#define inl inl
> +#define outl outl
> +#define insl insl
> +#define outsl outsl
> +
> +DECLARE_EXTIO(l, u32)
> +#endif
> +
> +
>  /*
>   * String version of I/O memory access operations.
>   */
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 7d66bba..60e0482 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
>  					   sys_compat.o entry32.o
>  arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
>  arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO)	+= extio.o
>  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
>  arm64-obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o perf_callchain.o
>  arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> new file mode 100644
> index 0000000..647b3fa
> --- /dev/null
> +++ b/arch/arm64/kernel/extio.c
> @@ -0,0 +1,27 @@
> +/*
> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/io.h>
> +
> +struct extio_ops *arm64_extio_ops;
> +
> +
> +BUILD_EXTIO(b, u8)
> +
> +BUILD_EXTIO(w, u16)
> +
> +BUILD_EXTIO(l, u32)

Is there no way to make this slightly more generic, so that it can be
re-used elsewhere? For example, if struct extio_ops was common, then
you could have the singleton (which maybe should be an interval tree?),
type definition, setter function and the BUILD_EXTIO invocations
somewhere generic, rather than squirelled away in the arch backend.

Will

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-11-08 16:09       ` Arnd Bergmann
@ 2016-11-08 16:15         ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-08 16:15 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Mark Rutland, catalin.marinas, gabriele.paoloni, benh,
	will.deacon, linuxarm, lorenzo.pieralisi, xuwei5, linux-serial,
	linux-pci, devicetree, minyard, marc.zyngier, liviu.dudau,
	john.garry, olof, robh+dt, bhelgaas, kantyzc, zhichang.yuan02,
	linux-kernel, zhichang.yuan, zourongrong

On Tuesday, November 8, 2016 5:09:59 PM CET Arnd Bergmann wrote:
> 
> I don't see a better alternative. I earlier suggested having these
> out of line so we don't grow the object code too much when it is
> enabled.
> 

On second look, I see that they are all done out of line, I would
just move around the BUILD_EXTIO macro to the file that uses it
and remove and open-code the DECLARE_EXTIO() as that makes it easier
to grep.

	Arnd

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08 16:15         ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-08 16:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday, November 8, 2016 5:09:59 PM CET Arnd Bergmann wrote:
> 
> I don't see a better alternative. I earlier suggested having these
> out of line so we don't grow the object code too much when it is
> enabled.
> 

On second look, I see that they are all done out of line, I would
just move around the BUILD_EXTIO macro to the file that uses it
and remove and open-code the DECLARE_EXTIO() as that makes it easier
to grep.

	Arnd

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
  2016-11-08 11:49     ` Mark Rutland
  (?)
@ 2016-11-08 16:19       ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-08 16:19 UTC (permalink / raw)
  To: Mark Rutland
  Cc: zhichang.yuan, catalin.marinas, will.deacon, robh+dt, bhelgaas,
	olof, linux-arm-kernel, lorenzo.pieralisi, linux-kernel,
	linuxarm, devicetree, linux-pci, linux-serial, minyard, benh,
	liviu.dudau, zourongrong, john.garry, gabriele.paoloni,
	zhichang.yuan02, kantyzc, xuwei5, marc.zyngier

On Tuesday, November 8, 2016 11:49:53 AM CET Mark Rutland wrote:
> On Tue, Nov 08, 2016 at 11:47:08AM +0800, zhichang.yuan wrote:
> > +Hisilicon Hip06 low-pin-count device
> > +  Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
> > +  locate on LPC bus can be accessed direclty. But some SoCs have independent
> > +  LPC controller, and access the legacy ports by triggering LPC I/O cycles.
> > +  Hisilicon Hip06 implements this LPC device.
> 
> s/direclty/directly/
> 
> My understanding of ISA (which may be flawed) is that it's not part of
> the PCI host bridge, but rather on x86 it happens to share the IO space
> with PCI.

On normal systems, ISA or LPC are behind a PCI bridge device, which
passes down both low addresses of I/O space and memory space.

> So, how about this becomes:
> 
>   Hisilicon Hip06 SoCs implement a Low Pin Count (LPC) controller, which
>   provides access to some legacy ISA devices.
> 
> I believe that we could theoretically have multiple independent LPC/ISA
> busses, as is possible with PCI on !x86 systems. If the current ISA code
> assumes a singleton bus, I think that's something that needs to be fixed
> up more generically.
> 
> I don't see why we should need any architecture-specific code here. Why
> can we not fix up the ISA bus code in drivers/of/address.c such that it
> handles multiple ISA bus instances, and translates all sub-device
> addresses relative to the specific bus instance?

I think it is a relatively safe assumption that there is only one
ISA bridge. A lot of old drivers hardcode PIO or memory addresses
when talking to an ISA device, so having multiple instances is
already problematic.

What is odd about ARM64 here is that the PIO space is not shared among
all ISA and PCI buses in some cases.

	Arnd

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-08 16:19       ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-08 16:19 UTC (permalink / raw)
  To: Mark Rutland
  Cc: gabriele.paoloni, benh, will.deacon, linuxarm, lorenzo.pieralisi,
	xuwei5, linux-serial, catalin.marinas, devicetree, minyard,
	marc.zyngier, liviu.dudau, john.garry, zourongrong, robh+dt,
	bhelgaas, kantyzc, zhichang.yuan02, linux-arm-kernel, linux-pci,
	linux-kernel, zhichang.yuan, olof

On Tuesday, November 8, 2016 11:49:53 AM CET Mark Rutland wrote:
> On Tue, Nov 08, 2016 at 11:47:08AM +0800, zhichang.yuan wrote:
> > +Hisilicon Hip06 low-pin-count device
> > +  Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
> > +  locate on LPC bus can be accessed direclty. But some SoCs have independent
> > +  LPC controller, and access the legacy ports by triggering LPC I/O cycles.
> > +  Hisilicon Hip06 implements this LPC device.
> 
> s/direclty/directly/
> 
> My understanding of ISA (which may be flawed) is that it's not part of
> the PCI host bridge, but rather on x86 it happens to share the IO space
> with PCI.

On normal systems, ISA or LPC are behind a PCI bridge device, which
passes down both low addresses of I/O space and memory space.

> So, how about this becomes:
> 
>   Hisilicon Hip06 SoCs implement a Low Pin Count (LPC) controller, which
>   provides access to some legacy ISA devices.
> 
> I believe that we could theoretically have multiple independent LPC/ISA
> busses, as is possible with PCI on !x86 systems. If the current ISA code
> assumes a singleton bus, I think that's something that needs to be fixed
> up more generically.
> 
> I don't see why we should need any architecture-specific code here. Why
> can we not fix up the ISA bus code in drivers/of/address.c such that it
> handles multiple ISA bus instances, and translates all sub-device
> addresses relative to the specific bus instance?

I think it is a relatively safe assumption that there is only one
ISA bridge. A lot of old drivers hardcode PIO or memory addresses
when talking to an ISA device, so having multiple instances is
already problematic.

What is odd about ARM64 here is that the PIO space is not shared among
all ISA and PCI buses in some cases.

	Arnd

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

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-08 16:19       ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-08 16:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday, November 8, 2016 11:49:53 AM CET Mark Rutland wrote:
> On Tue, Nov 08, 2016 at 11:47:08AM +0800, zhichang.yuan wrote:
> > +Hisilicon Hip06 low-pin-count device
> > +  Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
> > +  locate on LPC bus can be accessed direclty. But some SoCs have independent
> > +  LPC controller, and access the legacy ports by triggering LPC I/O cycles.
> > +  Hisilicon Hip06 implements this LPC device.
> 
> s/direclty/directly/
> 
> My understanding of ISA (which may be flawed) is that it's not part of
> the PCI host bridge, but rather on x86 it happens to share the IO space
> with PCI.

On normal systems, ISA or LPC are behind a PCI bridge device, which
passes down both low addresses of I/O space and memory space.

> So, how about this becomes:
> 
>   Hisilicon Hip06 SoCs implement a Low Pin Count (LPC) controller, which
>   provides access to some legacy ISA devices.
> 
> I believe that we could theoretically have multiple independent LPC/ISA
> busses, as is possible with PCI on !x86 systems. If the current ISA code
> assumes a singleton bus, I think that's something that needs to be fixed
> up more generically.
> 
> I don't see why we should need any architecture-specific code here. Why
> can we not fix up the ISA bus code in drivers/of/address.c such that it
> handles multiple ISA bus instances, and translates all sub-device
> addresses relative to the specific bus instance?

I think it is a relatively safe assumption that there is only one
ISA bridge. A lot of old drivers hardcode PIO or memory addresses
when talking to an ISA device, so having multiple instances is
already problematic.

What is odd about ARM64 here is that the PIO space is not shared among
all ISA and PCI buses in some cases.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-08  3:47   ` zhichang.yuan
@ 2016-11-08 16:24     ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-08 16:24 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, mark.rutland,
	olof, linux-arm-kernel, lorenzo.pieralisi, linux-kernel,
	linuxarm, devicetree, linux-pci, linux-serial, minyard, benh,
	liviu.dudau, zourongrong, john.garry, gabriele.paoloni,
	zhichang.yuan02, kantyzc, xuwei5

On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
> +       /*
> +        * The first PCIBIOS_MIN_IO is reserved specifically for indirectIO.
> +        * It will separate indirectIO range from pci host bridge to
> +        * avoid the possible PIO conflict.
> +        * Set the indirectIO range directly here.
> +        */
> +       lpcdev->io_ops.start = 0;
> +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> +       lpcdev->io_ops.devpara = lpcdev;
> +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;

I have to look at patch 2 in more detail again, after missing a few review
rounds. I'm still a bit skeptical about hardcoding a logical I/O port
range here, and would hope that we can just go through the same
assignment of logical port ranges that we have for PCI buses, decoupling
the bus addresses from the linux-internal ones.

	Arnd

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-08 16:24     ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-08 16:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
> +       /*
> +        * The first PCIBIOS_MIN_IO is reserved specifically for indirectIO.
> +        * It will separate indirectIO range from pci host bridge to
> +        * avoid the possible PIO conflict.
> +        * Set the indirectIO range directly here.
> +        */
> +       lpcdev->io_ops.start = 0;
> +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> +       lpcdev->io_ops.devpara = lpcdev;
> +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;

I have to look at patch 2 in more detail again, after missing a few review
rounds. I'm still a bit skeptical about hardcoding a logical I/O port
range here, and would hope that we can just go through the same
assignment of logical port ranges that we have for PCI buses, decoupling
the bus addresses from the linux-internal ones.

	Arnd

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-11-08 16:12     ` Will Deacon
  (?)
  (?)
@ 2016-11-08 16:33       ` John Garry
  -1 siblings, 0 replies; 286+ messages in thread
From: John Garry @ 2016-11-08 16:33 UTC (permalink / raw)
  To: Will Deacon, zhichang.yuan
  Cc: catalin.marinas, robh+dt, bhelgaas, mark.rutland, olof, arnd,
	linux-arm-kernel, lorenzo.pieralisi, linux-kernel, linuxarm,
	devicetree, linux-pci, linux-serial, minyard, benh, liviu.dudau,
	zourongrong, gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5

On 08/11/2016 16:12, Will Deacon wrote:
> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>> For arm64, there is no I/O space as other architectural platforms, such as
>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>> known port addresses are used to control the corresponding target devices, for
>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>> normal MMIO mode in using.
>>
>> To drive these devices, this patch introduces a method named indirect-IO.
>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>> redefined. When upper layer drivers call in/out with those known legacy port
>> addresses to access the peripherals, the hooking functions corrresponding to
>> those target peripherals will be called. Through this way, those upper layer
>> drivers which depend on in/out can run on Hip06 without any changes.
>>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
>> ---
>>  arch/arm64/Kconfig             |  6 +++
>>  arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>>  arch/arm64/include/asm/io.h    | 29 +++++++++++++
>>  arch/arm64/kernel/Makefile     |  1 +
>>  arch/arm64/kernel/extio.c      | 27 ++++++++++++
>>  5 files changed, 157 insertions(+)
>>  create mode 100644 arch/arm64/include/asm/extio.h
>>  create mode 100644 arch/arm64/kernel/extio.c
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 969ef88..b44070b 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>>         default 16
>>
>> +config ARM64_INDIRECT_PIO
>> +	bool "access peripherals with legacy I/O port"
>> +	help
>> +	  Support special accessors for ISA I/O devices. This is needed for
>> +	  SoCs that do not support standard read/write for the ISA range.
>> +
>>  config NO_IOPORT_MAP
>>  	def_bool y if !PCI
>>
>> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
>> new file mode 100644
>> index 0000000..6ae0787
>> --- /dev/null
>> +++ b/arch/arm64/include/asm/extio.h
>> @@ -0,0 +1,94 @@
>> +/*
>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef __LINUX_EXTIO_H
>> +#define __LINUX_EXTIO_H
>> +
>> +struct extio_ops {
>> +	unsigned long start;/* inclusive, sys io addr */
>> +	unsigned long end;/* inclusive, sys io addr */
>> +
>> +	u64 (*pfin)(void *devobj, unsigned long ptaddr,	size_t dlen);
>> +	void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
>> +					size_t dlen);
>> +	u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
>> +				size_t dlen, unsigned int count);
>> +	void (*pfouts)(void *devobj, unsigned long ptaddr,
>> +				const void *outbuf, size_t dlen,
>> +				unsigned int count);
>> +	void *devpara;
>> +};
>> +
>> +extern struct extio_ops *arm64_extio_ops;
>> +
>> +#define DECLARE_EXTIO(bw, type)						\
>> +extern type in##bw(unsigned long addr);					\
>> +extern void out##bw(type value, unsigned long addr);			\
>> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
>> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
>> +
>> +#define BUILD_EXTIO(bw, type)						\
>> +type in##bw(unsigned long addr)						\
>> +{									\
>> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
>> +			arm64_extio_ops->end < addr)			\
>> +		return read##bw(PCI_IOBASE + addr);			\
>> +	return arm64_extio_ops->pfin ?					\
>> +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
>> +			addr, sizeof(type)) : -1;			\
>> +}									\
>> +									\
>> +void out##bw(type value, unsigned long addr)				\
>> +{									\
>> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
>> +			arm64_extio_ops->end < addr)			\
>> +		write##bw(value, PCI_IOBASE + addr);			\
>> +	else								\
>> +		if (arm64_extio_ops->pfout)				\
>> +			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>> +				addr, value, sizeof(type));		\
>> +}									\
>> +									\
>> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
>> +{									\
>> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
>> +			arm64_extio_ops->end < addr)			\
>> +		reads##bw(PCI_IOBASE + addr, buffer, count);		\
>> +	else								\
>> +		if (arm64_extio_ops->pfins)				\
>> +			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
>> +				addr, buffer, sizeof(type), count);	\
>> +}									\
>> +									\
>> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
>> +{									\
>> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
>> +			arm64_extio_ops->end < addr)			\
>> +		writes##bw(PCI_IOBASE + addr, buffer, count);		\
>> +	else								\
>> +		if (arm64_extio_ops->pfouts)				\
>> +			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
>> +				addr, buffer, sizeof(type), count);	\
>> +}
>> +
>> +static inline void arm64_set_extops(struct extio_ops *ops)
>> +{
>> +	if (ops)
>> +		WRITE_ONCE(arm64_extio_ops, ops);
>
> Why does this need to be WRITE_ONCE? You don't have READ_ONCE on the reader
> side. Also, what if multiple drivers want to set different ops for distinct
> address ranges?

I think that the idea here is that we only have possibly one master in 
the system which offers indirectIO backend, so another one could not 
possibly re-set this value.

>
>> +}
>> +
>> +#endif /* __LINUX_EXTIO_H*/
>> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
>> index 0bba427..136735d 100644
>> --- a/arch/arm64/include/asm/io.h
>> +++ b/arch/arm64/include/asm/io.h
>> @@ -31,6 +31,7 @@
>>  #include <asm/early_ioremap.h>
>>  #include <asm/alternative.h>
>>  #include <asm/cpufeature.h>
>> +#include <asm/extio.h>
>>
>>  #include <xen/xen.h>
>>
>> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>  #define IO_SPACE_LIMIT		(PCI_IO_SIZE - 1)
>>  #define PCI_IOBASE		((void __iomem *)PCI_IO_START)
>>
>> +
>> +/*
>> + * redefine the in(s)b/out(s)b for indirect-IO.
>> + */
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +#define inb inb
>> +#define outb outb
>> +#define insb insb
>> +#define outsb outsb
>> +/* external declaration */
>> +DECLARE_EXTIO(b, u8)
>> +
>> +#define inw inw
>> +#define outw outw
>> +#define insw insw
>> +#define outsw outsw
>> +
>> +DECLARE_EXTIO(w, u16)
>> +
>> +#define inl inl
>> +#define outl outl
>> +#define insl insl
>> +#define outsl outsl
>> +
>> +DECLARE_EXTIO(l, u32)
>> +#endif
>> +
>> +
>>  /*
>>   * String version of I/O memory access operations.
>>   */
>> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
>> index 7d66bba..60e0482 100644
>> --- a/arch/arm64/kernel/Makefile
>> +++ b/arch/arm64/kernel/Makefile
>> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
>>  					   sys_compat.o entry32.o
>>  arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
>>  arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
>> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO)	+= extio.o
>>  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
>>  arm64-obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o perf_callchain.o
>>  arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
>> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
>> new file mode 100644
>> index 0000000..647b3fa
>> --- /dev/null
>> +++ b/arch/arm64/kernel/extio.c
>> @@ -0,0 +1,27 @@
>> +/*
>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <linux/io.h>
>> +
>> +struct extio_ops *arm64_extio_ops;
>> +
>> +
>> +BUILD_EXTIO(b, u8)
>> +
>> +BUILD_EXTIO(w, u16)
>> +
>> +BUILD_EXTIO(l, u32)
>
> Is there no way to make this slightly more generic, so that it can be
> re-used elsewhere? For example, if struct extio_ops was common, then
> you could have the singleton (which maybe should be an interval tree?),
> type definition, setter function and the BUILD_EXTIO invocations
> somewhere generic, rather than squirelled away in the arch backend.
>
> Will

The concern would be that some architecture which uses generic 
higher-level ISA accessor ops, but have IO space, could be affected.

John

>
> .
>

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08 16:33       ` John Garry
  0 siblings, 0 replies; 286+ messages in thread
From: John Garry @ 2016-11-08 16:33 UTC (permalink / raw)
  To: Will Deacon, zhichang.yuan
  Cc: mark.rutland, devicetree, lorenzo.pieralisi, benh, minyard, arnd,
	catalin.marinas, gabriele.paoloni, zhichang.yuan02, liviu.dudau,
	linux-kernel, xuwei5, linuxarm, olof, robh+dt, zourongrong,
	linux-serial, linux-pci, bhelgaas, kantyzc, linux-arm-kernel

On 08/11/2016 16:12, Will Deacon wrote:
> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>> For arm64, there is no I/O space as other architectural platforms, such as
>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>> known port addresses are used to control the corresponding target devices, for
>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>> normal MMIO mode in using.
>>
>> To drive these devices, this patch introduces a method named indirect-IO.
>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>> redefined. When upper layer drivers call in/out with those known legacy port
>> addresses to access the peripherals, the hooking functions corrresponding to
>> those target peripherals will be called. Through this way, those upper layer
>> drivers which depend on in/out can run on Hip06 without any changes.
>>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
>> ---
>>  arch/arm64/Kconfig             |  6 +++
>>  arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>>  arch/arm64/include/asm/io.h    | 29 +++++++++++++
>>  arch/arm64/kernel/Makefile     |  1 +
>>  arch/arm64/kernel/extio.c      | 27 ++++++++++++
>>  5 files changed, 157 insertions(+)
>>  create mode 100644 arch/arm64/include/asm/extio.h
>>  create mode 100644 arch/arm64/kernel/extio.c
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 969ef88..b44070b 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>>         default 16
>>
>> +config ARM64_INDIRECT_PIO
>> +	bool "access peripherals with legacy I/O port"
>> +	help
>> +	  Support special accessors for ISA I/O devices. This is needed for
>> +	  SoCs that do not support standard read/write for the ISA range.
>> +
>>  config NO_IOPORT_MAP
>>  	def_bool y if !PCI
>>
>> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
>> new file mode 100644
>> index 0000000..6ae0787
>> --- /dev/null
>> +++ b/arch/arm64/include/asm/extio.h
>> @@ -0,0 +1,94 @@
>> +/*
>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef __LINUX_EXTIO_H
>> +#define __LINUX_EXTIO_H
>> +
>> +struct extio_ops {
>> +	unsigned long start;/* inclusive, sys io addr */
>> +	unsigned long end;/* inclusive, sys io addr */
>> +
>> +	u64 (*pfin)(void *devobj, unsigned long ptaddr,	size_t dlen);
>> +	void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
>> +					size_t dlen);
>> +	u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
>> +				size_t dlen, unsigned int count);
>> +	void (*pfouts)(void *devobj, unsigned long ptaddr,
>> +				const void *outbuf, size_t dlen,
>> +				unsigned int count);
>> +	void *devpara;
>> +};
>> +
>> +extern struct extio_ops *arm64_extio_ops;
>> +
>> +#define DECLARE_EXTIO(bw, type)						\
>> +extern type in##bw(unsigned long addr);					\
>> +extern void out##bw(type value, unsigned long addr);			\
>> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
>> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
>> +
>> +#define BUILD_EXTIO(bw, type)						\
>> +type in##bw(unsigned long addr)						\
>> +{									\
>> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
>> +			arm64_extio_ops->end < addr)			\
>> +		return read##bw(PCI_IOBASE + addr);			\
>> +	return arm64_extio_ops->pfin ?					\
>> +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
>> +			addr, sizeof(type)) : -1;			\
>> +}									\
>> +									\
>> +void out##bw(type value, unsigned long addr)				\
>> +{									\
>> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
>> +			arm64_extio_ops->end < addr)			\
>> +		write##bw(value, PCI_IOBASE + addr);			\
>> +	else								\
>> +		if (arm64_extio_ops->pfout)				\
>> +			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>> +				addr, value, sizeof(type));		\
>> +}									\
>> +									\
>> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
>> +{									\
>> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
>> +			arm64_extio_ops->end < addr)			\
>> +		reads##bw(PCI_IOBASE + addr, buffer, count);		\
>> +	else								\
>> +		if (arm64_extio_ops->pfins)				\
>> +			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
>> +				addr, buffer, sizeof(type), count);	\
>> +}									\
>> +									\
>> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
>> +{									\
>> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
>> +			arm64_extio_ops->end < addr)			\
>> +		writes##bw(PCI_IOBASE + addr, buffer, count);		\
>> +	else								\
>> +		if (arm64_extio_ops->pfouts)				\
>> +			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
>> +				addr, buffer, sizeof(type), count);	\
>> +}
>> +
>> +static inline void arm64_set_extops(struct extio_ops *ops)
>> +{
>> +	if (ops)
>> +		WRITE_ONCE(arm64_extio_ops, ops);
>
> Why does this need to be WRITE_ONCE? You don't have READ_ONCE on the reader
> side. Also, what if multiple drivers want to set different ops for distinct
> address ranges?

I think that the idea here is that we only have possibly one master in 
the system which offers indirectIO backend, so another one could not 
possibly re-set this value.

>
>> +}
>> +
>> +#endif /* __LINUX_EXTIO_H*/
>> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
>> index 0bba427..136735d 100644
>> --- a/arch/arm64/include/asm/io.h
>> +++ b/arch/arm64/include/asm/io.h
>> @@ -31,6 +31,7 @@
>>  #include <asm/early_ioremap.h>
>>  #include <asm/alternative.h>
>>  #include <asm/cpufeature.h>
>> +#include <asm/extio.h>
>>
>>  #include <xen/xen.h>
>>
>> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>  #define IO_SPACE_LIMIT		(PCI_IO_SIZE - 1)
>>  #define PCI_IOBASE		((void __iomem *)PCI_IO_START)
>>
>> +
>> +/*
>> + * redefine the in(s)b/out(s)b for indirect-IO.
>> + */
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +#define inb inb
>> +#define outb outb
>> +#define insb insb
>> +#define outsb outsb
>> +/* external declaration */
>> +DECLARE_EXTIO(b, u8)
>> +
>> +#define inw inw
>> +#define outw outw
>> +#define insw insw
>> +#define outsw outsw
>> +
>> +DECLARE_EXTIO(w, u16)
>> +
>> +#define inl inl
>> +#define outl outl
>> +#define insl insl
>> +#define outsl outsl
>> +
>> +DECLARE_EXTIO(l, u32)
>> +#endif
>> +
>> +
>>  /*
>>   * String version of I/O memory access operations.
>>   */
>> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
>> index 7d66bba..60e0482 100644
>> --- a/arch/arm64/kernel/Makefile
>> +++ b/arch/arm64/kernel/Makefile
>> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
>>  					   sys_compat.o entry32.o
>>  arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
>>  arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
>> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO)	+= extio.o
>>  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
>>  arm64-obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o perf_callchain.o
>>  arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
>> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
>> new file mode 100644
>> index 0000000..647b3fa
>> --- /dev/null
>> +++ b/arch/arm64/kernel/extio.c
>> @@ -0,0 +1,27 @@
>> +/*
>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <linux/io.h>
>> +
>> +struct extio_ops *arm64_extio_ops;
>> +
>> +
>> +BUILD_EXTIO(b, u8)
>> +
>> +BUILD_EXTIO(w, u16)
>> +
>> +BUILD_EXTIO(l, u32)
>
> Is there no way to make this slightly more generic, so that it can be
> re-used elsewhere? For example, if struct extio_ops was common, then
> you could have the singleton (which maybe should be an interval tree?),
> type definition, setter function and the BUILD_EXTIO invocations
> somewhere generic, rather than squirelled away in the arch backend.
>
> Will

The concern would be that some architecture which uses generic 
higher-level ISA accessor ops, but have IO space, could be affected.

John

>
> .
>

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08 16:33       ` John Garry
  0 siblings, 0 replies; 286+ messages in thread
From: John Garry @ 2016-11-08 16:33 UTC (permalink / raw)
  To: Will Deacon, zhichang.yuan
  Cc: mark.rutland, devicetree, lorenzo.pieralisi, benh, minyard, arnd,
	catalin.marinas, gabriele.paoloni, zhichang.yuan02, liviu.dudau,
	linux-kernel, xuwei5, linuxarm, olof, robh+dt, zourongrong,
	linux-serial, linux-pci, bhelgaas, kantyzc, linux-arm-kernel

On 08/11/2016 16:12, Will Deacon wrote:
> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>> For arm64, there is no I/O space as other architectural platforms, such as
>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>> known port addresses are used to control the corresponding target devices, for
>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>> normal MMIO mode in using.
>>
>> To drive these devices, this patch introduces a method named indirect-IO.
>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>> redefined. When upper layer drivers call in/out with those known legacy port
>> addresses to access the peripherals, the hooking functions corrresponding to
>> those target peripherals will be called. Through this way, those upper layer
>> drivers which depend on in/out can run on Hip06 without any changes.
>>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
>> ---
>>  arch/arm64/Kconfig             |  6 +++
>>  arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>>  arch/arm64/include/asm/io.h    | 29 +++++++++++++
>>  arch/arm64/kernel/Makefile     |  1 +
>>  arch/arm64/kernel/extio.c      | 27 ++++++++++++
>>  5 files changed, 157 insertions(+)
>>  create mode 100644 arch/arm64/include/asm/extio.h
>>  create mode 100644 arch/arm64/kernel/extio.c
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 969ef88..b44070b 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>>         default 16
>>
>> +config ARM64_INDIRECT_PIO
>> +	bool "access peripherals with legacy I/O port"
>> +	help
>> +	  Support special accessors for ISA I/O devices. This is needed for
>> +	  SoCs that do not support standard read/write for the ISA range.
>> +
>>  config NO_IOPORT_MAP
>>  	def_bool y if !PCI
>>
>> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
>> new file mode 100644
>> index 0000000..6ae0787
>> --- /dev/null
>> +++ b/arch/arm64/include/asm/extio.h
>> @@ -0,0 +1,94 @@
>> +/*
>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef __LINUX_EXTIO_H
>> +#define __LINUX_EXTIO_H
>> +
>> +struct extio_ops {
>> +	unsigned long start;/* inclusive, sys io addr */
>> +	unsigned long end;/* inclusive, sys io addr */
>> +
>> +	u64 (*pfin)(void *devobj, unsigned long ptaddr,	size_t dlen);
>> +	void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
>> +					size_t dlen);
>> +	u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
>> +				size_t dlen, unsigned int count);
>> +	void (*pfouts)(void *devobj, unsigned long ptaddr,
>> +				const void *outbuf, size_t dlen,
>> +				unsigned int count);
>> +	void *devpara;
>> +};
>> +
>> +extern struct extio_ops *arm64_extio_ops;
>> +
>> +#define DECLARE_EXTIO(bw, type)						\
>> +extern type in##bw(unsigned long addr);					\
>> +extern void out##bw(type value, unsigned long addr);			\
>> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
>> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
>> +
>> +#define BUILD_EXTIO(bw, type)						\
>> +type in##bw(unsigned long addr)						\
>> +{									\
>> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
>> +			arm64_extio_ops->end < addr)			\
>> +		return read##bw(PCI_IOBASE + addr);			\
>> +	return arm64_extio_ops->pfin ?					\
>> +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
>> +			addr, sizeof(type)) : -1;			\
>> +}									\
>> +									\
>> +void out##bw(type value, unsigned long addr)				\
>> +{									\
>> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
>> +			arm64_extio_ops->end < addr)			\
>> +		write##bw(value, PCI_IOBASE + addr);			\
>> +	else								\
>> +		if (arm64_extio_ops->pfout)				\
>> +			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>> +				addr, value, sizeof(type));		\
>> +}									\
>> +									\
>> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
>> +{									\
>> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
>> +			arm64_extio_ops->end < addr)			\
>> +		reads##bw(PCI_IOBASE + addr, buffer, count);		\
>> +	else								\
>> +		if (arm64_extio_ops->pfins)				\
>> +			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
>> +				addr, buffer, sizeof(type), count);	\
>> +}									\
>> +									\
>> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
>> +{									\
>> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
>> +			arm64_extio_ops->end < addr)			\
>> +		writes##bw(PCI_IOBASE + addr, buffer, count);		\
>> +	else								\
>> +		if (arm64_extio_ops->pfouts)				\
>> +			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
>> +				addr, buffer, sizeof(type), count);	\
>> +}
>> +
>> +static inline void arm64_set_extops(struct extio_ops *ops)
>> +{
>> +	if (ops)
>> +		WRITE_ONCE(arm64_extio_ops, ops);
>
> Why does this need to be WRITE_ONCE? You don't have READ_ONCE on the reader
> side. Also, what if multiple drivers want to set different ops for distinct
> address ranges?

I think that the idea here is that we only have possibly one master in 
the system which offers indirectIO backend, so another one could not 
possibly re-set this value.

>
>> +}
>> +
>> +#endif /* __LINUX_EXTIO_H*/
>> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
>> index 0bba427..136735d 100644
>> --- a/arch/arm64/include/asm/io.h
>> +++ b/arch/arm64/include/asm/io.h
>> @@ -31,6 +31,7 @@
>>  #include <asm/early_ioremap.h>
>>  #include <asm/alternative.h>
>>  #include <asm/cpufeature.h>
>> +#include <asm/extio.h>
>>
>>  #include <xen/xen.h>
>>
>> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>  #define IO_SPACE_LIMIT		(PCI_IO_SIZE - 1)
>>  #define PCI_IOBASE		((void __iomem *)PCI_IO_START)
>>
>> +
>> +/*
>> + * redefine the in(s)b/out(s)b for indirect-IO.
>> + */
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +#define inb inb
>> +#define outb outb
>> +#define insb insb
>> +#define outsb outsb
>> +/* external declaration */
>> +DECLARE_EXTIO(b, u8)
>> +
>> +#define inw inw
>> +#define outw outw
>> +#define insw insw
>> +#define outsw outsw
>> +
>> +DECLARE_EXTIO(w, u16)
>> +
>> +#define inl inl
>> +#define outl outl
>> +#define insl insl
>> +#define outsl outsl
>> +
>> +DECLARE_EXTIO(l, u32)
>> +#endif
>> +
>> +
>>  /*
>>   * String version of I/O memory access operations.
>>   */
>> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
>> index 7d66bba..60e0482 100644
>> --- a/arch/arm64/kernel/Makefile
>> +++ b/arch/arm64/kernel/Makefile
>> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
>>  					   sys_compat.o entry32.o
>>  arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
>>  arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
>> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO)	+= extio.o
>>  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
>>  arm64-obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o perf_callchain.o
>>  arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
>> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
>> new file mode 100644
>> index 0000000..647b3fa
>> --- /dev/null
>> +++ b/arch/arm64/kernel/extio.c
>> @@ -0,0 +1,27 @@
>> +/*
>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <linux/io.h>
>> +
>> +struct extio_ops *arm64_extio_ops;
>> +
>> +
>> +BUILD_EXTIO(b, u8)
>> +
>> +BUILD_EXTIO(w, u16)
>> +
>> +BUILD_EXTIO(l, u32)
>
> Is there no way to make this slightly more generic, so that it can be
> re-used elsewhere? For example, if struct extio_ops was common, then
> you could have the singleton (which maybe should be an interval tree?),
> type definition, setter function and the BUILD_EXTIO invocations
> somewhere generic, rather than squirelled away in the arch backend.
>
> Will

The concern would be that some architecture which uses generic 
higher-level ISA accessor ops, but have IO space, could be affected.

John

>
> .
>



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08 16:33       ` John Garry
  0 siblings, 0 replies; 286+ messages in thread
From: John Garry @ 2016-11-08 16:33 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/11/2016 16:12, Will Deacon wrote:
> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>> For arm64, there is no I/O space as other architectural platforms, such as
>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>> known port addresses are used to control the corresponding target devices, for
>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>> normal MMIO mode in using.
>>
>> To drive these devices, this patch introduces a method named indirect-IO.
>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>> redefined. When upper layer drivers call in/out with those known legacy port
>> addresses to access the peripherals, the hooking functions corrresponding to
>> those target peripherals will be called. Through this way, those upper layer
>> drivers which depend on in/out can run on Hip06 without any changes.
>>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
>> ---
>>  arch/arm64/Kconfig             |  6 +++
>>  arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>>  arch/arm64/include/asm/io.h    | 29 +++++++++++++
>>  arch/arm64/kernel/Makefile     |  1 +
>>  arch/arm64/kernel/extio.c      | 27 ++++++++++++
>>  5 files changed, 157 insertions(+)
>>  create mode 100644 arch/arm64/include/asm/extio.h
>>  create mode 100644 arch/arm64/kernel/extio.c
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 969ef88..b44070b 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>>         default 16
>>
>> +config ARM64_INDIRECT_PIO
>> +	bool "access peripherals with legacy I/O port"
>> +	help
>> +	  Support special accessors for ISA I/O devices. This is needed for
>> +	  SoCs that do not support standard read/write for the ISA range.
>> +
>>  config NO_IOPORT_MAP
>>  	def_bool y if !PCI
>>
>> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
>> new file mode 100644
>> index 0000000..6ae0787
>> --- /dev/null
>> +++ b/arch/arm64/include/asm/extio.h
>> @@ -0,0 +1,94 @@
>> +/*
>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef __LINUX_EXTIO_H
>> +#define __LINUX_EXTIO_H
>> +
>> +struct extio_ops {
>> +	unsigned long start;/* inclusive, sys io addr */
>> +	unsigned long end;/* inclusive, sys io addr */
>> +
>> +	u64 (*pfin)(void *devobj, unsigned long ptaddr,	size_t dlen);
>> +	void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
>> +					size_t dlen);
>> +	u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
>> +				size_t dlen, unsigned int count);
>> +	void (*pfouts)(void *devobj, unsigned long ptaddr,
>> +				const void *outbuf, size_t dlen,
>> +				unsigned int count);
>> +	void *devpara;
>> +};
>> +
>> +extern struct extio_ops *arm64_extio_ops;
>> +
>> +#define DECLARE_EXTIO(bw, type)						\
>> +extern type in##bw(unsigned long addr);					\
>> +extern void out##bw(type value, unsigned long addr);			\
>> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
>> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
>> +
>> +#define BUILD_EXTIO(bw, type)						\
>> +type in##bw(unsigned long addr)						\
>> +{									\
>> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
>> +			arm64_extio_ops->end < addr)			\
>> +		return read##bw(PCI_IOBASE + addr);			\
>> +	return arm64_extio_ops->pfin ?					\
>> +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
>> +			addr, sizeof(type)) : -1;			\
>> +}									\
>> +									\
>> +void out##bw(type value, unsigned long addr)				\
>> +{									\
>> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
>> +			arm64_extio_ops->end < addr)			\
>> +		write##bw(value, PCI_IOBASE + addr);			\
>> +	else								\
>> +		if (arm64_extio_ops->pfout)				\
>> +			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>> +				addr, value, sizeof(type));		\
>> +}									\
>> +									\
>> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
>> +{									\
>> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
>> +			arm64_extio_ops->end < addr)			\
>> +		reads##bw(PCI_IOBASE + addr, buffer, count);		\
>> +	else								\
>> +		if (arm64_extio_ops->pfins)				\
>> +			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
>> +				addr, buffer, sizeof(type), count);	\
>> +}									\
>> +									\
>> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
>> +{									\
>> +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
>> +			arm64_extio_ops->end < addr)			\
>> +		writes##bw(PCI_IOBASE + addr, buffer, count);		\
>> +	else								\
>> +		if (arm64_extio_ops->pfouts)				\
>> +			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
>> +				addr, buffer, sizeof(type), count);	\
>> +}
>> +
>> +static inline void arm64_set_extops(struct extio_ops *ops)
>> +{
>> +	if (ops)
>> +		WRITE_ONCE(arm64_extio_ops, ops);
>
> Why does this need to be WRITE_ONCE? You don't have READ_ONCE on the reader
> side. Also, what if multiple drivers want to set different ops for distinct
> address ranges?

I think that the idea here is that we only have possibly one master in 
the system which offers indirectIO backend, so another one could not 
possibly re-set this value.

>
>> +}
>> +
>> +#endif /* __LINUX_EXTIO_H*/
>> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
>> index 0bba427..136735d 100644
>> --- a/arch/arm64/include/asm/io.h
>> +++ b/arch/arm64/include/asm/io.h
>> @@ -31,6 +31,7 @@
>>  #include <asm/early_ioremap.h>
>>  #include <asm/alternative.h>
>>  #include <asm/cpufeature.h>
>> +#include <asm/extio.h>
>>
>>  #include <xen/xen.h>
>>
>> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>  #define IO_SPACE_LIMIT		(PCI_IO_SIZE - 1)
>>  #define PCI_IOBASE		((void __iomem *)PCI_IO_START)
>>
>> +
>> +/*
>> + * redefine the in(s)b/out(s)b for indirect-IO.
>> + */
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +#define inb inb
>> +#define outb outb
>> +#define insb insb
>> +#define outsb outsb
>> +/* external declaration */
>> +DECLARE_EXTIO(b, u8)
>> +
>> +#define inw inw
>> +#define outw outw
>> +#define insw insw
>> +#define outsw outsw
>> +
>> +DECLARE_EXTIO(w, u16)
>> +
>> +#define inl inl
>> +#define outl outl
>> +#define insl insl
>> +#define outsl outsl
>> +
>> +DECLARE_EXTIO(l, u32)
>> +#endif
>> +
>> +
>>  /*
>>   * String version of I/O memory access operations.
>>   */
>> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
>> index 7d66bba..60e0482 100644
>> --- a/arch/arm64/kernel/Makefile
>> +++ b/arch/arm64/kernel/Makefile
>> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
>>  					   sys_compat.o entry32.o
>>  arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
>>  arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
>> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO)	+= extio.o
>>  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
>>  arm64-obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o perf_callchain.o
>>  arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
>> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
>> new file mode 100644
>> index 0000000..647b3fa
>> --- /dev/null
>> +++ b/arch/arm64/kernel/extio.c
>> @@ -0,0 +1,27 @@
>> +/*
>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <linux/io.h>
>> +
>> +struct extio_ops *arm64_extio_ops;
>> +
>> +
>> +BUILD_EXTIO(b, u8)
>> +
>> +BUILD_EXTIO(w, u16)
>> +
>> +BUILD_EXTIO(l, u32)
>
> Is there no way to make this slightly more generic, so that it can be
> re-used elsewhere? For example, if struct extio_ops was common, then
> you could have the singleton (which maybe should be an interval tree?),
> type definition, setter function and the BUILD_EXTIO invocations
> somewhere generic, rather than squirelled away in the arch backend.
>
> Will

The concern would be that some architecture which uses generic 
higher-level ISA accessor ops, but have IO space, could be affected.

John

>
> .
>

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-11-08 16:33       ` John Garry
@ 2016-11-08 16:49         ` Will Deacon
  -1 siblings, 0 replies; 286+ messages in thread
From: Will Deacon @ 2016-11-08 16:49 UTC (permalink / raw)
  To: John Garry
  Cc: zhichang.yuan, mark.rutland, devicetree, lorenzo.pieralisi, benh,
	minyard, arnd, catalin.marinas, gabriele.paoloni,
	zhichang.yuan02, liviu.dudau, linux-kernel, xuwei5, linuxarm,
	olof, robh+dt, zourongrong, linux-serial, linux-pci, bhelgaas,
	kantyzc, linux-arm-kernel

On Tue, Nov 08, 2016 at 04:33:44PM +0000, John Garry wrote:
> On 08/11/2016 16:12, Will Deacon wrote:
> >On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> >>+static inline void arm64_set_extops(struct extio_ops *ops)
> >>+{
> >>+	if (ops)
> >>+		WRITE_ONCE(arm64_extio_ops, ops);
> >
> >Why does this need to be WRITE_ONCE? You don't have READ_ONCE on the reader
> >side. Also, what if multiple drivers want to set different ops for distinct
> >address ranges?
> 
> I think that the idea here is that we only have possibly one master in the
> system which offers indirectIO backend, so another one could not possibly
> re-set this value.

Why is that assumption valid, and why does WRITE_ONCE help there? It's not
ONCE as in WARN_ONCE, more ONCE as in exactly-once-per-invocation.

> >>diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> >>new file mode 100644
> >>index 0000000..647b3fa
> >>--- /dev/null
> >>+++ b/arch/arm64/kernel/extio.c
> >>@@ -0,0 +1,27 @@
> >>+/*
> >>+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> >>+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> >>+ *
> >>+ * This program is free software; you can redistribute it and/or modify
> >>+ * it under the terms of the GNU General Public License version 2 as
> >>+ * published by the Free Software Foundation.
> >>+ *
> >>+ * This program is distributed in the hope that it will be useful,
> >>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >>+ * GNU General Public License for more details.
> >>+ *
> >>+ * You should have received a copy of the GNU General Public License
> >>+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> >>+ */
> >>+
> >>+#include <linux/io.h>
> >>+
> >>+struct extio_ops *arm64_extio_ops;
> >>+
> >>+
> >>+BUILD_EXTIO(b, u8)
> >>+
> >>+BUILD_EXTIO(w, u16)
> >>+
> >>+BUILD_EXTIO(l, u32)
> >
> >Is there no way to make this slightly more generic, so that it can be
> >re-used elsewhere? For example, if struct extio_ops was common, then
> >you could have the singleton (which maybe should be an interval tree?),
> >type definition, setter function and the BUILD_EXTIO invocations
> >somewhere generic, rather than squirelled away in the arch backend.
> >
> The concern would be that some architecture which uses generic higher-level
> ISA accessor ops, but have IO space, could be affected.

You're already adding a Kconfig symbol for this stuff, so you can keep
that if you don't want it on other architectures. I'm just arguing that
plumbing drivers directly into arch code via arm64_set_extops is not
something I'm particularly fond of, especially when it looks like it
could be avoided with a small amount of effort.

Will

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08 16:49         ` Will Deacon
  0 siblings, 0 replies; 286+ messages in thread
From: Will Deacon @ 2016-11-08 16:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Nov 08, 2016 at 04:33:44PM +0000, John Garry wrote:
> On 08/11/2016 16:12, Will Deacon wrote:
> >On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> >>+static inline void arm64_set_extops(struct extio_ops *ops)
> >>+{
> >>+	if (ops)
> >>+		WRITE_ONCE(arm64_extio_ops, ops);
> >
> >Why does this need to be WRITE_ONCE? You don't have READ_ONCE on the reader
> >side. Also, what if multiple drivers want to set different ops for distinct
> >address ranges?
> 
> I think that the idea here is that we only have possibly one master in the
> system which offers indirectIO backend, so another one could not possibly
> re-set this value.

Why is that assumption valid, and why does WRITE_ONCE help there? It's not
ONCE as in WARN_ONCE, more ONCE as in exactly-once-per-invocation.

> >>diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> >>new file mode 100644
> >>index 0000000..647b3fa
> >>--- /dev/null
> >>+++ b/arch/arm64/kernel/extio.c
> >>@@ -0,0 +1,27 @@
> >>+/*
> >>+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> >>+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> >>+ *
> >>+ * This program is free software; you can redistribute it and/or modify
> >>+ * it under the terms of the GNU General Public License version 2 as
> >>+ * published by the Free Software Foundation.
> >>+ *
> >>+ * This program is distributed in the hope that it will be useful,
> >>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >>+ * GNU General Public License for more details.
> >>+ *
> >>+ * You should have received a copy of the GNU General Public License
> >>+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> >>+ */
> >>+
> >>+#include <linux/io.h>
> >>+
> >>+struct extio_ops *arm64_extio_ops;
> >>+
> >>+
> >>+BUILD_EXTIO(b, u8)
> >>+
> >>+BUILD_EXTIO(w, u16)
> >>+
> >>+BUILD_EXTIO(l, u32)
> >
> >Is there no way to make this slightly more generic, so that it can be
> >re-used elsewhere? For example, if struct extio_ops was common, then
> >you could have the singleton (which maybe should be an interval tree?),
> >type definition, setter function and the BUILD_EXTIO invocations
> >somewhere generic, rather than squirelled away in the arch backend.
> >
> The concern would be that some architecture which uses generic higher-level
> ISA accessor ops, but have IO space, could be affected.

You're already adding a Kconfig symbol for this stuff, so you can keep
that if you don't want it on other architectures. I'm just arguing that
plumbing drivers directly into arch code via arm64_set_extops is not
something I'm particularly fond of, especially when it looks like it
could be avoided with a small amount of effort.

Will

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-11-08 16:49         ` Will Deacon
  (?)
@ 2016-11-08 17:05           ` John Garry
  -1 siblings, 0 replies; 286+ messages in thread
From: John Garry @ 2016-11-08 17:05 UTC (permalink / raw)
  To: Will Deacon
  Cc: zhichang.yuan, mark.rutland, devicetree, lorenzo.pieralisi, benh,
	minyard, arnd, catalin.marinas, gabriele.paoloni,
	zhichang.yuan02, liviu.dudau, linux-kernel, xuwei5, linuxarm,
	olof, robh+dt, zourongrong, linux-serial, linux-pci, bhelgaas,
	kantyzc, linux-arm-kernel

On 08/11/2016 16:49, Will Deacon wrote:
> On Tue, Nov 08, 2016 at 04:33:44PM +0000, John Garry wrote:
>> On 08/11/2016 16:12, Will Deacon wrote:
>>> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>>>> +static inline void arm64_set_extops(struct extio_ops *ops)
>>>> +{
>>>> +	if (ops)
>>>> +		WRITE_ONCE(arm64_extio_ops, ops);
>>>
>>> Why does this need to be WRITE_ONCE? You don't have READ_ONCE on the reader
>>> side. Also, what if multiple drivers want to set different ops for distinct
>>> address ranges?
>>
>> I think that the idea here is that we only have possibly one master in the
>> system which offers indirectIO backend, so another one could not possibly
>> re-set this value.
>
> Why is that assumption valid, and why does WRITE_ONCE help there? It's not
> ONCE as in WARN_ONCE, more ONCE as in exactly-once-per-invocation.

It's only valid based on the inherent assumption that all indirectIO is 
redirected to one backend master, i.e. LPC driver.

Anyway, right, I don't think that WRITE_ONCE is correct. Zhichang was 
looking for something which would only allow the pointer to be written 
once ever.

>
>>>> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
>>>> new file mode 100644
>>>> index 0000000..647b3fa
>>>> --- /dev/null
>>>> +++ b/arch/arm64/kernel/extio.c
>>>> @@ -0,0 +1,27 @@
>>>> +/*
>>>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>>>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>>>> + *
>>>> + * This program is free software; you can redistribute it and/or modify
>>>> + * it under the terms of the GNU General Public License version 2 as
>>>> + * published by the Free Software Foundation.
>>>> + *
>>>> + * This program is distributed in the hope that it will be useful,
>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>>> + * GNU General Public License for more details.
>>>> + *
>>>> + * You should have received a copy of the GNU General Public License
>>>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>>> + */
>>>> +
>>>> +#include <linux/io.h>
>>>> +
>>>> +struct extio_ops *arm64_extio_ops;
>>>> +
>>>> +
>>>> +BUILD_EXTIO(b, u8)
>>>> +
>>>> +BUILD_EXTIO(w, u16)
>>>> +
>>>> +BUILD_EXTIO(l, u32)
>>>
>>> Is there no way to make this slightly more generic, so that it can be
>>> re-used elsewhere? For example, if struct extio_ops was common, then
>>> you could have the singleton (which maybe should be an interval tree?),
>>> type definition, setter function and the BUILD_EXTIO invocations
>>> somewhere generic, rather than squirelled away in the arch backend.
>>>
>> The concern would be that some architecture which uses generic higher-level
>> ISA accessor ops, but have IO space, could be affected.
>
> You're already adding a Kconfig symbol for this stuff, so you can keep
> that if you don't want it on other architectures. I'm just arguing that
> plumbing drivers directly into arch code via arm64_set_extops is not
> something I'm particularly fond of, especially when it looks like it
> could be avoided with a small amount of effort.

We'll check this.

Cheers,
John

>
> Will
>
> .
>

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08 17:05           ` John Garry
  0 siblings, 0 replies; 286+ messages in thread
From: John Garry @ 2016-11-08 17:05 UTC (permalink / raw)
  To: Will Deacon
  Cc: zhichang.yuan, mark.rutland, devicetree, lorenzo.pieralisi, benh,
	minyard, arnd, catalin.marinas, gabriele.paoloni,
	zhichang.yuan02, liviu.dudau, linux-kernel, xuwei5, linuxarm,
	olof, robh+dt, zourongrong, linux-serial, linux-pci, bhelgaas,
	kantyzc, linux-arm-kernel

On 08/11/2016 16:49, Will Deacon wrote:
> On Tue, Nov 08, 2016 at 04:33:44PM +0000, John Garry wrote:
>> On 08/11/2016 16:12, Will Deacon wrote:
>>> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>>>> +static inline void arm64_set_extops(struct extio_ops *ops)
>>>> +{
>>>> +	if (ops)
>>>> +		WRITE_ONCE(arm64_extio_ops, ops);
>>>
>>> Why does this need to be WRITE_ONCE? You don't have READ_ONCE on the reader
>>> side. Also, what if multiple drivers want to set different ops for distinct
>>> address ranges?
>>
>> I think that the idea here is that we only have possibly one master in the
>> system which offers indirectIO backend, so another one could not possibly
>> re-set this value.
>
> Why is that assumption valid, and why does WRITE_ONCE help there? It's not
> ONCE as in WARN_ONCE, more ONCE as in exactly-once-per-invocation.

It's only valid based on the inherent assumption that all indirectIO is 
redirected to one backend master, i.e. LPC driver.

Anyway, right, I don't think that WRITE_ONCE is correct. Zhichang was 
looking for something which would only allow the pointer to be written 
once ever.

>
>>>> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
>>>> new file mode 100644
>>>> index 0000000..647b3fa
>>>> --- /dev/null
>>>> +++ b/arch/arm64/kernel/extio.c
>>>> @@ -0,0 +1,27 @@
>>>> +/*
>>>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>>>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>>>> + *
>>>> + * This program is free software; you can redistribute it and/or modify
>>>> + * it under the terms of the GNU General Public License version 2 as
>>>> + * published by the Free Software Foundation.
>>>> + *
>>>> + * This program is distributed in the hope that it will be useful,
>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>>> + * GNU General Public License for more details.
>>>> + *
>>>> + * You should have received a copy of the GNU General Public License
>>>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>>> + */
>>>> +
>>>> +#include <linux/io.h>
>>>> +
>>>> +struct extio_ops *arm64_extio_ops;
>>>> +
>>>> +
>>>> +BUILD_EXTIO(b, u8)
>>>> +
>>>> +BUILD_EXTIO(w, u16)
>>>> +
>>>> +BUILD_EXTIO(l, u32)
>>>
>>> Is there no way to make this slightly more generic, so that it can be
>>> re-used elsewhere? For example, if struct extio_ops was common, then
>>> you could have the singleton (which maybe should be an interval tree?),
>>> type definition, setter function and the BUILD_EXTIO invocations
>>> somewhere generic, rather than squirelled away in the arch backend.
>>>
>> The concern would be that some architecture which uses generic higher-level
>> ISA accessor ops, but have IO space, could be affected.
>
> You're already adding a Kconfig symbol for this stuff, so you can keep
> that if you don't want it on other architectures. I'm just arguing that
> plumbing drivers directly into arch code via arm64_set_extops is not
> something I'm particularly fond of, especially when it looks like it
> could be avoided with a small amount of effort.

We'll check this.

Cheers,
John

>
> Will
>
> .
>

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08 17:05           ` John Garry
  0 siblings, 0 replies; 286+ messages in thread
From: John Garry @ 2016-11-08 17:05 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/11/2016 16:49, Will Deacon wrote:
> On Tue, Nov 08, 2016 at 04:33:44PM +0000, John Garry wrote:
>> On 08/11/2016 16:12, Will Deacon wrote:
>>> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>>>> +static inline void arm64_set_extops(struct extio_ops *ops)
>>>> +{
>>>> +	if (ops)
>>>> +		WRITE_ONCE(arm64_extio_ops, ops);
>>>
>>> Why does this need to be WRITE_ONCE? You don't have READ_ONCE on the reader
>>> side. Also, what if multiple drivers want to set different ops for distinct
>>> address ranges?
>>
>> I think that the idea here is that we only have possibly one master in the
>> system which offers indirectIO backend, so another one could not possibly
>> re-set this value.
>
> Why is that assumption valid, and why does WRITE_ONCE help there? It's not
> ONCE as in WARN_ONCE, more ONCE as in exactly-once-per-invocation.

It's only valid based on the inherent assumption that all indirectIO is 
redirected to one backend master, i.e. LPC driver.

Anyway, right, I don't think that WRITE_ONCE is correct. Zhichang was 
looking for something which would only allow the pointer to be written 
once ever.

>
>>>> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
>>>> new file mode 100644
>>>> index 0000000..647b3fa
>>>> --- /dev/null
>>>> +++ b/arch/arm64/kernel/extio.c
>>>> @@ -0,0 +1,27 @@
>>>> +/*
>>>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>>>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>>>> + *
>>>> + * This program is free software; you can redistribute it and/or modify
>>>> + * it under the terms of the GNU General Public License version 2 as
>>>> + * published by the Free Software Foundation.
>>>> + *
>>>> + * This program is distributed in the hope that it will be useful,
>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>>> + * GNU General Public License for more details.
>>>> + *
>>>> + * You should have received a copy of the GNU General Public License
>>>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>>> + */
>>>> +
>>>> +#include <linux/io.h>
>>>> +
>>>> +struct extio_ops *arm64_extio_ops;
>>>> +
>>>> +
>>>> +BUILD_EXTIO(b, u8)
>>>> +
>>>> +BUILD_EXTIO(w, u16)
>>>> +
>>>> +BUILD_EXTIO(l, u32)
>>>
>>> Is there no way to make this slightly more generic, so that it can be
>>> re-used elsewhere? For example, if struct extio_ops was common, then
>>> you could have the singleton (which maybe should be an interval tree?),
>>> type definition, setter function and the BUILD_EXTIO invocations
>>> somewhere generic, rather than squirelled away in the arch backend.
>>>
>> The concern would be that some architecture which uses generic higher-level
>> ISA accessor ops, but have IO space, could be affected.
>
> You're already adding a Kconfig symbol for this stuff, so you can keep
> that if you don't want it on other architectures. I'm just arguing that
> plumbing drivers directly into arch code via arm64_set_extops is not
> something I'm particularly fond of, especially when it looks like it
> could be avoided with a small amount of effort.

We'll check this.

Cheers,
John

>
> Will
>
> .
>

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
  2016-11-08 16:19       ` Arnd Bergmann
  (?)
@ 2016-11-08 17:10         ` Mark Rutland
  -1 siblings, 0 replies; 286+ messages in thread
From: Mark Rutland @ 2016-11-08 17:10 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: zhichang.yuan, catalin.marinas, will.deacon, robh+dt, bhelgaas,
	olof, linux-arm-kernel, lorenzo.pieralisi, linux-kernel,
	linuxarm, devicetree, linux-pci, linux-serial, minyard, benh,
	liviu.dudau, zourongrong, john.garry, gabriele.paoloni,
	zhichang.yuan02, kantyzc, xuwei5, marc.zyngier

On Tue, Nov 08, 2016 at 05:19:54PM +0100, Arnd Bergmann wrote:
> On Tuesday, November 8, 2016 11:49:53 AM CET Mark Rutland wrote:
> > My understanding of ISA (which may be flawed) is that it's not part of
> > the PCI host bridge, but rather on x86 it happens to share the IO space
> > with PCI.
> 
> On normal systems, ISA or LPC are behind a PCI bridge device, which
> passes down both low addresses of I/O space and memory space.

Ok, so the use of those address spaces is an artifact of the ISA
controller being a device under the PCI host bridge.

Given we can have multiple domains, surely that implies we can have
multiple ISA controllers in general?

> > I believe that we could theoretically have multiple independent LPC/ISA
> > busses, as is possible with PCI on !x86 systems. If the current ISA code
> > assumes a singleton bus, I think that's something that needs to be fixed
> > up more generically.
> > 
> > I don't see why we should need any architecture-specific code here. Why
> > can we not fix up the ISA bus code in drivers/of/address.c such that it
> > handles multiple ISA bus instances, and translates all sub-device
> > addresses relative to the specific bus instance?
> 
> I think it is a relatively safe assumption that there is only one
> ISA bridge. A lot of old drivers hardcode PIO or memory addresses
> when talking to an ISA device, so having multiple instances is
> already problematic.

I'm worried that this might not be a safe assumption. Hardware these
days has a habit of pushing the boundaries of our expectations.

If we're going to assume that, I'd certainly want the kernel to verify
that it's true for all instanciated ISA/LPC devices. Otherwise, I can
imagine people relying on (or working around) that assumption in ACPI
tables and DTs, and that will be a nightmare (at best) to untangle in
future.

Thanks,
Mark.

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-08 17:10         ` Mark Rutland
  0 siblings, 0 replies; 286+ messages in thread
From: Mark Rutland @ 2016-11-08 17:10 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: zhichang.yuan, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, olof-nZhT3qVonbNeoWH0uzbU5w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	lorenzo.pieralisi-5wv7dgnIgG8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linuxarm-hv44wF8Li93QT0dZR+AlfA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, minyard-HInyCGIudOg,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, liviu.dudau-5wv7dgnIgG8,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
	john.garry-hv44wF8Li93QT0dZR+AlfA,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w, kantyzc-9Onoh4P/yGk,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q, marc.zyngier-5wv7dgnIgG8

On Tue, Nov 08, 2016 at 05:19:54PM +0100, Arnd Bergmann wrote:
> On Tuesday, November 8, 2016 11:49:53 AM CET Mark Rutland wrote:
> > My understanding of ISA (which may be flawed) is that it's not part of
> > the PCI host bridge, but rather on x86 it happens to share the IO space
> > with PCI.
> 
> On normal systems, ISA or LPC are behind a PCI bridge device, which
> passes down both low addresses of I/O space and memory space.

Ok, so the use of those address spaces is an artifact of the ISA
controller being a device under the PCI host bridge.

Given we can have multiple domains, surely that implies we can have
multiple ISA controllers in general?

> > I believe that we could theoretically have multiple independent LPC/ISA
> > busses, as is possible with PCI on !x86 systems. If the current ISA code
> > assumes a singleton bus, I think that's something that needs to be fixed
> > up more generically.
> > 
> > I don't see why we should need any architecture-specific code here. Why
> > can we not fix up the ISA bus code in drivers/of/address.c such that it
> > handles multiple ISA bus instances, and translates all sub-device
> > addresses relative to the specific bus instance?
> 
> I think it is a relatively safe assumption that there is only one
> ISA bridge. A lot of old drivers hardcode PIO or memory addresses
> when talking to an ISA device, so having multiple instances is
> already problematic.

I'm worried that this might not be a safe assumption. Hardware these
days has a habit of pushing the boundaries of our expectations.

If we're going to assume that, I'd certainly want the kernel to verify
that it's true for all instanciated ISA/LPC devices. Otherwise, I can
imagine people relying on (or working around) that assumption in ACPI
tables and DTs, and that will be a nightmare (at best) to untangle in
future.

Thanks,
Mark.
--
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] 286+ messages in thread

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-08 17:10         ` Mark Rutland
  0 siblings, 0 replies; 286+ messages in thread
From: Mark Rutland @ 2016-11-08 17:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Nov 08, 2016 at 05:19:54PM +0100, Arnd Bergmann wrote:
> On Tuesday, November 8, 2016 11:49:53 AM CET Mark Rutland wrote:
> > My understanding of ISA (which may be flawed) is that it's not part of
> > the PCI host bridge, but rather on x86 it happens to share the IO space
> > with PCI.
> 
> On normal systems, ISA or LPC are behind a PCI bridge device, which
> passes down both low addresses of I/O space and memory space.

Ok, so the use of those address spaces is an artifact of the ISA
controller being a device under the PCI host bridge.

Given we can have multiple domains, surely that implies we can have
multiple ISA controllers in general?

> > I believe that we could theoretically have multiple independent LPC/ISA
> > busses, as is possible with PCI on !x86 systems. If the current ISA code
> > assumes a singleton bus, I think that's something that needs to be fixed
> > up more generically.
> > 
> > I don't see why we should need any architecture-specific code here. Why
> > can we not fix up the ISA bus code in drivers/of/address.c such that it
> > handles multiple ISA bus instances, and translates all sub-device
> > addresses relative to the specific bus instance?
> 
> I think it is a relatively safe assumption that there is only one
> ISA bridge. A lot of old drivers hardcode PIO or memory addresses
> when talking to an ISA device, so having multiple instances is
> already problematic.

I'm worried that this might not be a safe assumption. Hardware these
days has a habit of pushing the boundaries of our expectations.

If we're going to assume that, I'd certainly want the kernel to verify
that it's true for all instanciated ISA/LPC devices. Otherwise, I can
imagine people relying on (or working around) that assumption in ACPI
tables and DTs, and that will be a nightmare (at best) to untangle in
future.

Thanks,
Mark.

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-11-08 16:49         ` Will Deacon
  (?)
@ 2016-11-08 22:35           ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-08 22:35 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Will Deacon, John Garry, mark.rutland, catalin.marinas,
	gabriele.paoloni, linux-pci, liviu.dudau, linuxarm,
	lorenzo.pieralisi, minyard, xuwei5, linux-serial, benh,
	devicetree, zhichang.yuan02, olof, robh+dt, bhelgaas, kantyzc,
	linux-kernel, zhichang.yuan, zourongrong

On Tuesday, November 8, 2016 4:49:49 PM CET Will Deacon wrote:
> On Tue, Nov 08, 2016 at 04:33:44PM +0000, John Garry wrote:
> > On 08/11/2016 16:12, Will Deacon wrote:
> > >On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:

> > >Is there no way to make this slightly more generic, so that it can be
> > >re-used elsewhere? For example, if struct extio_ops was common, then
> > >you could have the singleton (which maybe should be an interval tree?),
> > >type definition, setter function and the BUILD_EXTIO invocations
> > >somewhere generic, rather than squirelled away in the arch backend.
> > >
> > The concern would be that some architecture which uses generic higher-level
> > ISA accessor ops, but have IO space, could be affected.
> 
> You're already adding a Kconfig symbol for this stuff, so you can keep
> that if you don't want it on other architectures. I'm just arguing that
> plumbing drivers directly into arch code via arm64_set_extops is not
> something I'm particularly fond of, especially when it looks like it
> could be avoided with a small amount of effort.

Agreed, I initially suggested putting this into arch/arm64/, but there isn't
really a reason why it couldn't just live in lib/ with the header file
bits moved to include/asm-generic/io.h which we already use.

	Arnd

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08 22:35           ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-08 22:35 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: mark.rutland, gabriele.paoloni, benh, Will Deacon, linuxarm,
	lorenzo.pieralisi, xuwei5, linux-serial, catalin.marinas,
	devicetree, minyard, liviu.dudau, John Garry, olof, robh+dt,
	bhelgaas, kantyzc, zhichang.yuan02, linux-pci, linux-kernel,
	zhichang.yuan, zourongrong

On Tuesday, November 8, 2016 4:49:49 PM CET Will Deacon wrote:
> On Tue, Nov 08, 2016 at 04:33:44PM +0000, John Garry wrote:
> > On 08/11/2016 16:12, Will Deacon wrote:
> > >On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:

> > >Is there no way to make this slightly more generic, so that it can be
> > >re-used elsewhere? For example, if struct extio_ops was common, then
> > >you could have the singleton (which maybe should be an interval tree?),
> > >type definition, setter function and the BUILD_EXTIO invocations
> > >somewhere generic, rather than squirelled away in the arch backend.
> > >
> > The concern would be that some architecture which uses generic higher-level
> > ISA accessor ops, but have IO space, could be affected.
> 
> You're already adding a Kconfig symbol for this stuff, so you can keep
> that if you don't want it on other architectures. I'm just arguing that
> plumbing drivers directly into arch code via arm64_set_extops is not
> something I'm particularly fond of, especially when it looks like it
> could be avoided with a small amount of effort.

Agreed, I initially suggested putting this into arch/arm64/, but there isn't
really a reason why it couldn't just live in lib/ with the header file
bits moved to include/asm-generic/io.h which we already use.

	Arnd

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08 22:35           ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-08 22:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday, November 8, 2016 4:49:49 PM CET Will Deacon wrote:
> On Tue, Nov 08, 2016 at 04:33:44PM +0000, John Garry wrote:
> > On 08/11/2016 16:12, Will Deacon wrote:
> > >On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:

> > >Is there no way to make this slightly more generic, so that it can be
> > >re-used elsewhere? For example, if struct extio_ops was common, then
> > >you could have the singleton (which maybe should be an interval tree?),
> > >type definition, setter function and the BUILD_EXTIO invocations
> > >somewhere generic, rather than squirelled away in the arch backend.
> > >
> > The concern would be that some architecture which uses generic higher-level
> > ISA accessor ops, but have IO space, could be affected.
> 
> You're already adding a Kconfig symbol for this stuff, so you can keep
> that if you don't want it on other architectures. I'm just arguing that
> plumbing drivers directly into arch code via arm64_set_extops is not
> something I'm particularly fond of, especially when it looks like it
> could be avoided with a small amount of effort.

Agreed, I initially suggested putting this into arch/arm64/, but there isn't
really a reason why it couldn't just live in lib/ with the header file
bits moved to include/asm-generic/io.h which we already use.

	Arnd

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
  2016-11-08 11:49     ` Mark Rutland
  (?)
  (?)
@ 2016-11-08 23:12       ` Benjamin Herrenschmidt
  -1 siblings, 0 replies; 286+ messages in thread
From: Benjamin Herrenschmidt @ 2016-11-08 23:12 UTC (permalink / raw)
  To: Mark Rutland, zhichang.yuan
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, olof, arnd,
	linux-arm-kernel, lorenzo.pieralisi, linux-kernel, linuxarm,
	devicetree, linux-pci, linux-serial, minyard, liviu.dudau,
	zourongrong, john.garry, gabriele.paoloni, zhichang.yuan02,
	kantyzc, xuwei5, marc.zyngier

On Tue, 2016-11-08 at 11:49 +0000, Mark Rutland wrote:
> 
> My understanding of ISA (which may be flawed) is that it's not part of
> the PCI host bridge, but rather on x86 it happens to share the IO space
> with PCI.

Sort-of. On some systems it actually goes through PCI and there's a
PCI->ISA bridge that uses substractive decoding to the legacy devices.

> So, how about this becomes:
> 
>   Hisilicon Hip06 SoCs implement a Low Pin Count (LPC) controller, which
>   provides access to some legacy ISA devices.
> 
> I believe that we could theoretically have multiple independent LPC/ISA
> busses, as is possible with PCI on !x86 systems. If the current ISA code
> assumes a singleton bus, I think that's something that needs to be fixed
> up more generically.
> 
> I don't see why we should need any architecture-specific code here. Why
> can we not fix up the ISA bus code in drivers/of/address.c such that it
> handles multiple ISA bus instances, and translates all sub-device
> addresses relative to the specific bus instance?

What in that code prevents that today ?

Cheers,
Ben.

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-08 23:12       ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 286+ messages in thread
From: Benjamin Herrenschmidt @ 2016-11-08 23:12 UTC (permalink / raw)
  To: Mark Rutland, zhichang.yuan
  Cc: catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, bhelgaas-hpIqsD4AKlfQT0dZR+AlfA,
	olof-nZhT3qVonbNeoWH0uzbU5w, arnd-r2nGTMty4D4,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	lorenzo.pieralisi-5wv7dgnIgG8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linuxarm-hv44wF8Li93QT0dZR+AlfA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, minyard-HInyCGIudOg,
	liviu.dudau-5wv7dgnIgG8, zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
	john.garry-hv44wF8Li93QT0dZR+AlfA,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w, kantyzc-9Onoh4P/yGk,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q, marc.zyngier-5wv7dgnIgG8

On Tue, 2016-11-08 at 11:49 +0000, Mark Rutland wrote:
> 
> My understanding of ISA (which may be flawed) is that it's not part of
> the PCI host bridge, but rather on x86 it happens to share the IO space
> with PCI.

Sort-of. On some systems it actually goes through PCI and there's a
PCI->ISA bridge that uses substractive decoding to the legacy devices.

> So, how about this becomes:
> 
>   Hisilicon Hip06 SoCs implement a Low Pin Count (LPC) controller, which
>   provides access to some legacy ISA devices.
> 
> I believe that we could theoretically have multiple independent LPC/ISA
> busses, as is possible with PCI on !x86 systems. If the current ISA code
> assumes a singleton bus, I think that's something that needs to be fixed
> up more generically.
> 
> I don't see why we should need any architecture-specific code here. Why
> can we not fix up the ISA bus code in drivers/of/address.c such that it
> handles multiple ISA bus instances, and translates all sub-device
> addresses relative to the specific bus instance?

What in that code prevents that today ?

Cheers,
Ben.

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-08 23:12       ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 286+ messages in thread
From: Benjamin Herrenschmidt @ 2016-11-08 23:12 UTC (permalink / raw)
  To: Mark Rutland, zhichang.yuan
  Cc: gabriele.paoloni, catalin.marinas, will.deacon, linuxarm,
	lorenzo.pieralisi, arnd, xuwei5, linux-serial, linux-pci,
	devicetree, minyard, marc.zyngier, liviu.dudau, john.garry,
	zourongrong, robh+dt, bhelgaas, kantyzc, zhichang.yuan02,
	linux-arm-kernel, linux-kernel, olof

T24gVHVlLCAyMDE2LTExLTA4IGF0IDExOjQ5ICswMDAwLCBNYXJrIFJ1dGxhbmQgd3JvdGU6Cj4g
Cj4gTXkgdW5kZXJzdGFuZGluZyBvZiBJU0EgKHdoaWNoIG1heSBiZSBmbGF3ZWQpIGlzIHRoYXQg
aXQncyBub3QgcGFydCBvZgo+IHRoZSBQQ0kgaG9zdCBicmlkZ2UsIGJ1dCByYXRoZXIgb24geDg2
IGl0IGhhcHBlbnMgdG8gc2hhcmUgdGhlIElPIHNwYWNlCj4gd2l0aCBQQ0kuCgpTb3J0LW9mLiBP
biBzb21lIHN5c3RlbXMgaXQgYWN0dWFsbHkgZ29lcyB0aHJvdWdoIFBDSSBhbmQgdGhlcmUncyBh
ClBDSS0+SVNBIGJyaWRnZSB0aGF0IHVzZXMgc3Vic3RyYWN0aXZlIGRlY29kaW5nIHRvIHRoZSBs
ZWdhY3kgZGV2aWNlcy4KCj4gU28sIGhvdyBhYm91dCB0aGlzIGJlY29tZXM6Cj4gCj4gwqAgSGlz
aWxpY29uIEhpcDA2IFNvQ3MgaW1wbGVtZW50IGEgTG93IFBpbiBDb3VudCAoTFBDKSBjb250cm9s
bGVyLCB3aGljaAo+IMKgIHByb3ZpZGVzIGFjY2VzcyB0byBzb21lIGxlZ2FjeSBJU0EgZGV2aWNl
cy4KPiAKPiBJIGJlbGlldmUgdGhhdCB3ZSBjb3VsZCB0aGVvcmV0aWNhbGx5IGhhdmUgbXVsdGlw
bGUgaW5kZXBlbmRlbnQgTFBDL0lTQQo+IGJ1c3NlcywgYXMgaXMgcG9zc2libGUgd2l0aCBQQ0kg
b24gIXg4NiBzeXN0ZW1zLiBJZiB0aGUgY3VycmVudCBJU0EgY29kZQo+IGFzc3VtZXMgYSBzaW5n
bGV0b24gYnVzLCBJIHRoaW5rIHRoYXQncyBzb21ldGhpbmcgdGhhdCBuZWVkcyB0byBiZSBmaXhl
ZAo+IHVwIG1vcmUgZ2VuZXJpY2FsbHkuCj4gCj4gSSBkb24ndCBzZWUgd2h5IHdlIHNob3VsZCBu
ZWVkIGFueSBhcmNoaXRlY3R1cmUtc3BlY2lmaWMgY29kZSBoZXJlLiBXaHkKPiBjYW4gd2Ugbm90
IGZpeCB1cCB0aGUgSVNBIGJ1cyBjb2RlIGluIGRyaXZlcnMvb2YvYWRkcmVzcy5jIHN1Y2ggdGhh
dCBpdAo+IGhhbmRsZXMgbXVsdGlwbGUgSVNBIGJ1cyBpbnN0YW5jZXMsIGFuZCB0cmFuc2xhdGVz
IGFsbCBzdWItZGV2aWNlCj4gYWRkcmVzc2VzIHJlbGF0aXZlIHRvIHRoZSBzcGVjaWZpYyBidXMg
aW5zdGFuY2U/CgpXaGF0IGluIHRoYXQgY29kZSBwcmV2ZW50cyB0aGF0IHRvZGF5ID8KCkNoZWVy
cywKQmVuLgoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
CmxpbnV4LWFybS1rZXJuZWwgbWFpbGluZyBsaXN0CmxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5m
cmFkZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xp
bnV4LWFybS1rZXJuZWwK

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

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-08 23:12       ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 286+ messages in thread
From: Benjamin Herrenschmidt @ 2016-11-08 23:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2016-11-08 at 11:49 +0000, Mark Rutland wrote:
> 
> My understanding of ISA (which may be flawed) is that it's not part of
> the PCI host bridge, but rather on x86 it happens to share the IO space
> with PCI.

Sort-of. On some systems it actually goes through PCI and there's a
PCI->ISA bridge that uses substractive decoding to the legacy devices.

> So, how about this becomes:
> 
> ? Hisilicon Hip06 SoCs implement a Low Pin Count (LPC) controller, which
> ? provides access to some legacy ISA devices.
> 
> I believe that we could theoretically have multiple independent LPC/ISA
> busses, as is possible with PCI on !x86 systems. If the current ISA code
> assumes a singleton bus, I think that's something that needs to be fixed
> up more generically.
> 
> I don't see why we should need any architecture-specific code here. Why
> can we not fix up the ISA bus code in drivers/of/address.c such that it
> handles multiple ISA bus instances, and translates all sub-device
> addresses relative to the specific bus instance?

What in that code prevents that today ?

Cheers,
Ben.

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-11-08 12:03     ` Mark Rutland
  (?)
@ 2016-11-08 23:16       ` Benjamin Herrenschmidt
  -1 siblings, 0 replies; 286+ messages in thread
From: Benjamin Herrenschmidt @ 2016-11-08 23:16 UTC (permalink / raw)
  To: Mark Rutland, zhichang.yuan
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, olof, arnd,
	linux-arm-kernel, lorenzo.pieralisi, linux-kernel, linuxarm,
	devicetree, linux-pci, linux-serial, minyard, liviu.dudau,
	zourongrong, john.garry, gabriele.paoloni, zhichang.yuan02,
	kantyzc, xuwei5, marc.zyngier

On Tue, 2016-11-08 at 12:03 +0000, Mark Rutland wrote:
> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> > 
> > For arm64, there is no I/O space as other architectural platforms, such as
> > X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> > such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> > known port addresses are used to control the corresponding target devices, for
> > example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> > normal MMIO mode in using.
> 
> This has nothing to do with arm64. Hardware with this kind of indirect
> bus access could be integrated with a variety of CPU architectures. It
> simply hasn't been, yet.

On some ppc's we also use similar indirect access methods for IOs. We
have a generic infrastructure for re-routing some memory or IO regions
to hooks.

On POWER8, our PCIe doesn't do IO at all, but we have an LPC bus behind
firmware calls ;-) We use that infrastructure to plumb in the LPC bus.

> > To drive these devices, this patch introduces a method named indirect-IO.
> > In this method the in/out pair in arch/arm64/include/asm/io.h will be
> > redefined. When upper layer drivers call in/out with those known legacy port
> > addresses to access the peripherals, the hooking functions corrresponding to
> > those target peripherals will be called. Through this way, those upper layer
> > drivers which depend on in/out can run on Hip06 without any changes.
> 
> As above, this has nothing to do with arm64, and as such, should live in
> generic code, exactly as we would do if we had higher-level ISA
> accessor ops.
> 
> Regardless, given the multi-instance case, I don't think this is
> sufficient in general (and I think we need higher-level ISA accessors
> to handle the indirection).

Multi-instance with IO is tricky to do generically because archs already
have all sort of hacks to deal with the fact that inb/outb don't require
an explicit ioremap, so an IO resource can take all sort of shape depending
on the arch.

Overall it boils down to applying some kind of per-instance "offset" to
the IO port number though.

> [...]
> 
> > 
> > diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
> > new file mode 100644
> > index 0000000..6ae0787
> > --- /dev/null
> > +++ b/arch/arm64/include/asm/extio.h
> 
> > 
> > +#ifndef __LINUX_EXTIO_H
> > +#define __LINUX_EXTIO_H
> 
> This doesn't match the file naming, __ASM_EXTIO_H would be consistent
> with other arm64 headers.
> 
> > 
> > +
> > +struct extio_ops {
> > > > +	unsigned long start;/* inclusive, sys io addr */
> > > > +	unsigned long end;/* inclusive, sys io addr */
> 
> Please put whitespace before inline comments.
> 
> [...]
> 
> > 
> > > > +type in##bw(unsigned long addr)						\
> > > > +{									\
> > > > > > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > > > > > +			arm64_extio_ops->end < addr)			\
> > > > > > +		return read##bw(PCI_IOBASE + addr);			\
> > > > > > +	return arm64_extio_ops->pfin ?					\
> > > > > > +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
> > > > > > +			addr, sizeof(type)) : -1;			\
> > > > +}									\
> > > > +									\
> > > > +void out##bw(type value, unsigned long addr)				\
> > > > +{									\
> > > > > > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > > > > > +			arm64_extio_ops->end < addr)			\
> > > > > > +		write##bw(value, PCI_IOBASE + addr);			\
> > > > > > +	else								\
> > > > > > +		if (arm64_extio_ops->pfout)				\
> > > > +			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > > > > > +				addr, value, sizeof(type));		\
> > > > +}									\
> > > > +									\
> > > > +void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
> > > > +{									\
> > > > > > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > > > > > +			arm64_extio_ops->end < addr)			\
> > > > > > +		reads##bw(PCI_IOBASE + addr, buffer, count);		\
> > > > > > +	else								\
> > > > > > +		if (arm64_extio_ops->pfins)				\
> > > > +			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
> > > > > > +				addr, buffer, sizeof(type), count);	\
> > > > +}									\
> > > > +									\
> > > > +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
> > > > +{									\
> > > > > > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > > > > > +			arm64_extio_ops->end < addr)			\
> > > > > > +		writes##bw(PCI_IOBASE + addr, buffer, count);		\
> > > > > > +	else								\
> > > > > > +		if (arm64_extio_ops->pfouts)				\
> > > > +			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
> > > > > > +				addr, buffer, sizeof(type), count);	\
> > +}
> > +
> 
> So all PCI I/O will be slowed down by irrelevant checks when this is
> enabled?
> 
> [...]
> 
> > 
> > +static inline void arm64_set_extops(struct extio_ops *ops)
> > +{
> > > > +	if (ops)
> > > > +		WRITE_ONCE(arm64_extio_ops, ops);
> > +}
> 
> Why WRITE_ONCE()?
> 
> Is this not protected/propagated by some synchronisation mechanism?
> 
> WRITE_ONCE() is not sufficient to ensure that this is consistently
> observed by readers, and regardless, I don't see READ_ONCE() anywhere in
> this patch.
> 
> This looks very suspicious.
> 
> Thanks,
> Mark.

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08 23:16       ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 286+ messages in thread
From: Benjamin Herrenschmidt @ 2016-11-08 23:16 UTC (permalink / raw)
  To: Mark Rutland, zhichang.yuan
  Cc: gabriele.paoloni, catalin.marinas, will.deacon, linuxarm,
	lorenzo.pieralisi, arnd, xuwei5, linux-serial, linux-pci,
	devicetree, minyard, marc.zyngier, liviu.dudau, john.garry,
	zourongrong, robh+dt, bhelgaas, kantyzc, zhichang.yuan02,
	linux-arm-kernel, linux-kernel, olof

On Tue, 2016-11-08 at 12:03 +0000, Mark Rutland wrote:
> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> > 
> > For arm64, there is no I/O space as other architectural platforms, such as
> > X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> > such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> > known port addresses are used to control the corresponding target devices, for
> > example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> > normal MMIO mode in using.
> 
> This has nothing to do with arm64. Hardware with this kind of indirect
> bus access could be integrated with a variety of CPU architectures. It
> simply hasn't been, yet.

On some ppc's we also use similar indirect access methods for IOs. We
have a generic infrastructure for re-routing some memory or IO regions
to hooks.

On POWER8, our PCIe doesn't do IO at all, but we have an LPC bus behind
firmware calls ;-) We use that infrastructure to plumb in the LPC bus.

> > To drive these devices, this patch introduces a method named indirect-IO.
> > In this method the in/out pair in arch/arm64/include/asm/io.h will be
> > redefined. When upper layer drivers call in/out with those known legacy port
> > addresses to access the peripherals, the hooking functions corrresponding to
> > those target peripherals will be called. Through this way, those upper layer
> > drivers which depend on in/out can run on Hip06 without any changes.
> 
> As above, this has nothing to do with arm64, and as such, should live in
> generic code, exactly as we would do if we had higher-level ISA
> accessor ops.
> 
> Regardless, given the multi-instance case, I don't think this is
> sufficient in general (and I think we need higher-level ISA accessors
> to handle the indirection).

Multi-instance with IO is tricky to do generically because archs already
have all sort of hacks to deal with the fact that inb/outb don't require
an explicit ioremap, so an IO resource can take all sort of shape depending
on the arch.

Overall it boils down to applying some kind of per-instance "offset" to
the IO port number though.

> [...]
> 
> > 
> > diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
> > new file mode 100644
> > index 0000000..6ae0787
> > --- /dev/null
> > +++ b/arch/arm64/include/asm/extio.h
> 
> > 
> > +#ifndef __LINUX_EXTIO_H
> > +#define __LINUX_EXTIO_H
> 
> This doesn't match the file naming, __ASM_EXTIO_H would be consistent
> with other arm64 headers.
> 
> > 
> > +
> > +struct extio_ops {
> > > > +	unsigned long start;/* inclusive, sys io addr */
> > > > +	unsigned long end;/* inclusive, sys io addr */
> 
> Please put whitespace before inline comments.
> 
> [...]
> 
> > 
> > > > +type in##bw(unsigned long addr)						\
> > > > +{									\
> > > > > > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > > > > > +			arm64_extio_ops->end < addr)			\
> > > > > > +		return read##bw(PCI_IOBASE + addr);			\
> > > > > > +	return arm64_extio_ops->pfin ?					\
> > > > > > +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
> > > > > > +			addr, sizeof(type)) : -1;			\
> > > > +}									\
> > > > +									\
> > > > +void out##bw(type value, unsigned long addr)				\
> > > > +{									\
> > > > > > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > > > > > +			arm64_extio_ops->end < addr)			\
> > > > > > +		write##bw(value, PCI_IOBASE + addr);			\
> > > > > > +	else								\
> > > > > > +		if (arm64_extio_ops->pfout)				\
> > > > +			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > > > > > +				addr, value, sizeof(type));		\
> > > > +}									\
> > > > +									\
> > > > +void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
> > > > +{									\
> > > > > > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > > > > > +			arm64_extio_ops->end < addr)			\
> > > > > > +		reads##bw(PCI_IOBASE + addr, buffer, count);		\
> > > > > > +	else								\
> > > > > > +		if (arm64_extio_ops->pfins)				\
> > > > +			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
> > > > > > +				addr, buffer, sizeof(type), count);	\
> > > > +}									\
> > > > +									\
> > > > +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
> > > > +{									\
> > > > > > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > > > > > +			arm64_extio_ops->end < addr)			\
> > > > > > +		writes##bw(PCI_IOBASE + addr, buffer, count);		\
> > > > > > +	else								\
> > > > > > +		if (arm64_extio_ops->pfouts)				\
> > > > +			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
> > > > > > +				addr, buffer, sizeof(type), count);	\
> > +}
> > +
> 
> So all PCI I/O will be slowed down by irrelevant checks when this is
> enabled?
> 
> [...]
> 
> > 
> > +static inline void arm64_set_extops(struct extio_ops *ops)
> > +{
> > > > +	if (ops)
> > > > +		WRITE_ONCE(arm64_extio_ops, ops);
> > +}
> 
> Why WRITE_ONCE()?
> 
> Is this not protected/propagated by some synchronisation mechanism?
> 
> WRITE_ONCE() is not sufficient to ensure that this is consistently
> observed by readers, and regardless, I don't see READ_ONCE() anywhere in
> this patch.
> 
> This looks very suspicious.
> 
> Thanks,
> Mark.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-08 23:16       ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 286+ messages in thread
From: Benjamin Herrenschmidt @ 2016-11-08 23:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2016-11-08 at 12:03 +0000, Mark Rutland wrote:
> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> > 
> > For arm64, there is no I/O space as other architectural platforms, such as
> > X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> > such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> > known port addresses are used to control the corresponding target devices, for
> > example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> > normal MMIO mode in using.
> 
> This has nothing to do with arm64. Hardware with this kind of indirect
> bus access could be integrated with a variety of CPU architectures. It
> simply hasn't been, yet.

On some ppc's we also use similar indirect access methods for IOs. We
have a generic infrastructure for re-routing some memory or IO regions
to hooks.

On POWER8, our PCIe doesn't do IO at all, but we have an LPC bus behind
firmware calls ;-) We use that infrastructure to plumb in the LPC bus.

> > To drive these devices, this patch introduces a method named indirect-IO.
> > In this method the in/out pair in arch/arm64/include/asm/io.h will be
> > redefined. When upper layer drivers call in/out with those known legacy port
> > addresses to access the peripherals, the hooking functions corrresponding to
> > those target peripherals will be called. Through this way, those upper layer
> > drivers which depend on in/out can run on Hip06 without any changes.
> 
> As above, this has nothing to do with arm64, and as such, should live in
> generic code, exactly as we would do if we had higher-level ISA
> accessor ops.
> 
> Regardless, given the multi-instance case, I don't think this is
> sufficient in general (and I think we need higher-level ISA accessors
> to handle the indirection).

Multi-instance with IO is tricky to do generically because archs already
have all sort of hacks to deal with the fact that inb/outb don't require
an explicit ioremap, so an IO resource can take all sort of shape depending
on the arch.

Overall it boils down to applying some kind of per-instance "offset" to
the IO port number though.

> [...]
> 
> > 
> > diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
> > new file mode 100644
> > index 0000000..6ae0787
> > --- /dev/null
> > +++ b/arch/arm64/include/asm/extio.h
> 
> > 
> > +#ifndef __LINUX_EXTIO_H
> > +#define __LINUX_EXTIO_H
> 
> This doesn't match the file naming, __ASM_EXTIO_H would be consistent
> with other arm64 headers.
> 
> > 
> > +
> > +struct extio_ops {
> > > > +	unsigned long start;/* inclusive, sys io addr */
> > > > +	unsigned long end;/* inclusive, sys io addr */
> 
> Please put whitespace before inline comments.
> 
> [...]
> 
> > 
> > > > +type in##bw(unsigned long addr)						\
> > > > +{									\
> > > > > > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > > > > > +			arm64_extio_ops->end < addr)			\
> > > > > > +		return read##bw(PCI_IOBASE + addr);			\
> > > > > > +	return arm64_extio_ops->pfin ?					\
> > > > > > +		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
> > > > > > +			addr, sizeof(type)) : -1;			\
> > > > +}									\
> > > > +									\
> > > > +void out##bw(type value, unsigned long addr)				\
> > > > +{									\
> > > > > > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > > > > > +			arm64_extio_ops->end < addr)			\
> > > > > > +		write##bw(value, PCI_IOBASE + addr);			\
> > > > > > +	else								\
> > > > > > +		if (arm64_extio_ops->pfout)				\
> > > > +			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > > > > > +				addr, value, sizeof(type));		\
> > > > +}									\
> > > > +									\
> > > > +void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
> > > > +{									\
> > > > > > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > > > > > +			arm64_extio_ops->end < addr)			\
> > > > > > +		reads##bw(PCI_IOBASE + addr, buffer, count);		\
> > > > > > +	else								\
> > > > > > +		if (arm64_extio_ops->pfins)				\
> > > > +			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
> > > > > > +				addr, buffer, sizeof(type), count);	\
> > > > +}									\
> > > > +									\
> > > > +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
> > > > +{									\
> > > > > > +	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
> > > > > > +			arm64_extio_ops->end < addr)			\
> > > > > > +		writes##bw(PCI_IOBASE + addr, buffer, count);		\
> > > > > > +	else								\
> > > > > > +		if (arm64_extio_ops->pfouts)				\
> > > > +			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
> > > > > > +				addr, buffer, sizeof(type), count);	\
> > +}
> > +
> 
> So all PCI I/O will be slowed down by irrelevant checks when this is
> enabled?
> 
> [...]
> 
> > 
> > +static inline void arm64_set_extops(struct extio_ops *ops)
> > +{
> > > > +	if (ops)
> > > > +		WRITE_ONCE(arm64_extio_ops, ops);
> > +}
> 
> Why WRITE_ONCE()?
> 
> Is this not protected/propagated by some synchronisation mechanism?
> 
> WRITE_ONCE() is not sufficient to ensure that this is consistently
> observed by readers, and regardless, I don't see READ_ONCE() anywhere in
> this patch.
> 
> This looks very suspicious.
> 
> Thanks,
> Mark.

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
  2016-11-08 23:12       ` Benjamin Herrenschmidt
@ 2016-11-09 11:20         ` Mark Rutland
  -1 siblings, 0 replies; 286+ messages in thread
From: Mark Rutland @ 2016-11-09 11:20 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: zhichang.yuan, catalin.marinas, will.deacon, robh+dt, bhelgaas,
	olof, arnd, linux-arm-kernel, lorenzo.pieralisi, linux-kernel,
	linuxarm, devicetree, linux-pci, linux-serial, minyard,
	liviu.dudau, zourongrong, john.garry, gabriele.paoloni,
	zhichang.yuan02, kantyzc, xuwei5, marc.zyngier

On Wed, Nov 09, 2016 at 10:12:59AM +1100, Benjamin Herrenschmidt wrote:
> On Tue, 2016-11-08 at 11:49 +0000, Mark Rutland wrote:
> > I believe that we could theoretically have multiple independent LPC/ISA
> > busses, as is possible with PCI on !x86 systems. If the current ISA code
> > assumes a singleton bus, I think that's something that needs to be fixed
> > up more generically.
> > 
> > I don't see why we should need any architecture-specific code here. Why
> > can we not fix up the ISA bus code in drivers/of/address.c such that it
> > handles multiple ISA bus instances, and translates all sub-device
> > addresses relative to the specific bus instance?
> 
> What in that code prevents that today ?

It appears I was mistaken w.r.t. the singleton comment. We can already
translate MMIO->MMIO addresses per-instance (in the presence of a ranges
property).

The big change would be to handle !MMIO translations, for which we'd
need a runtime registry of ISA bus instance to find the relevant
accessor ops and instance-specific data.

Thanks,
Mark.

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

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-09 11:20         ` Mark Rutland
  0 siblings, 0 replies; 286+ messages in thread
From: Mark Rutland @ 2016-11-09 11:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Nov 09, 2016 at 10:12:59AM +1100, Benjamin Herrenschmidt wrote:
> On Tue, 2016-11-08 at 11:49 +0000, Mark Rutland wrote:
> > I believe that we could theoretically have multiple independent LPC/ISA
> > busses, as is possible with PCI on !x86 systems. If the current ISA code
> > assumes a singleton bus, I think that's something that needs to be fixed
> > up more generically.
> > 
> > I don't see why we should need any architecture-specific code here. Why
> > can we not fix up the ISA bus code in drivers/of/address.c such that it
> > handles multiple ISA bus instances, and translates all sub-device
> > addresses relative to the specific bus instance?
> 
> What in that code prevents that today ?

It appears I was mistaken w.r.t. the singleton comment. We can already
translate MMIO->MMIO addresses per-instance (in the presence of a ranges
property).

The big change would be to handle !MMIO translations, for which we'd
need a runtime registry of ISA bus instance to find the relevant
accessor ops and instance-specific data.

Thanks,
Mark.

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-11-08 22:35           ` Arnd Bergmann
  (?)
@ 2016-11-09 11:29             ` John Garry
  -1 siblings, 0 replies; 286+ messages in thread
From: John Garry @ 2016-11-09 11:29 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: Will Deacon, mark.rutland, catalin.marinas, gabriele.paoloni,
	linux-pci, liviu.dudau, linuxarm, lorenzo.pieralisi, minyard,
	xuwei5, linux-serial, benh, devicetree, zhichang.yuan02, olof,
	robh+dt, bhelgaas, kantyzc, linux-kernel, zhichang.yuan,
	zourongrong

On 08/11/2016 22:35, Arnd Bergmann wrote:
> On Tuesday, November 8, 2016 4:49:49 PM CET Will Deacon wrote:
>> On Tue, Nov 08, 2016 at 04:33:44PM +0000, John Garry wrote:
>>> On 08/11/2016 16:12, Will Deacon wrote:
>>>> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>
>>>> Is there no way to make this slightly more generic, so that it can be
>>>> re-used elsewhere? For example, if struct extio_ops was common, then
>>>> you could have the singleton (which maybe should be an interval tree?),
>>>> type definition, setter function and the BUILD_EXTIO invocations
>>>> somewhere generic, rather than squirelled away in the arch backend.
>>>>
>>> The concern would be that some architecture which uses generic higher-level
>>> ISA accessor ops, but have IO space, could be affected.
>>
>> You're already adding a Kconfig symbol for this stuff, so you can keep
>> that if you don't want it on other architectures. I'm just arguing that
>> plumbing drivers directly into arch code via arm64_set_extops is not
>> something I'm particularly fond of, especially when it looks like it
>> could be avoided with a small amount of effort.
>
> Agreed, I initially suggested putting this into arch/arm64/, but there isn't
> really a reason why it couldn't just live in lib/ with the header file
> bits moved to include/asm-generic/io.h which we already use.
>

Right, Zhichang will check the logistics of this. The generic io.h is 
quite clean, so as long as you don't mind new build switches of this 
nature being added, it should be ok; and we'll plan on moving extio.h 
into include/asm-generic as well.

Cheers,
John

> 	Arnd
>
> .
>

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-09 11:29             ` John Garry
  0 siblings, 0 replies; 286+ messages in thread
From: John Garry @ 2016-11-09 11:29 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Will Deacon, mark.rutland-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA, liviu.dudau-5wv7dgnIgG8,
	linuxarm-hv44wF8Li93QT0dZR+AlfA, lorenzo.pieralisi-5wv7dgnIgG8,
	minyard-HInyCGIudOg, xuwei5-C8/M+/jPZTeaMJb+Lgu22Q,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w,
	olof-nZhT3qVonbNeoWH0uzbU5w, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, kantyzc-9Onoh4P/yGk,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, zhichang.yuan,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w

On 08/11/2016 22:35, Arnd Bergmann wrote:
> On Tuesday, November 8, 2016 4:49:49 PM CET Will Deacon wrote:
>> On Tue, Nov 08, 2016 at 04:33:44PM +0000, John Garry wrote:
>>> On 08/11/2016 16:12, Will Deacon wrote:
>>>> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>
>>>> Is there no way to make this slightly more generic, so that it can be
>>>> re-used elsewhere? For example, if struct extio_ops was common, then
>>>> you could have the singleton (which maybe should be an interval tree?),
>>>> type definition, setter function and the BUILD_EXTIO invocations
>>>> somewhere generic, rather than squirelled away in the arch backend.
>>>>
>>> The concern would be that some architecture which uses generic higher-level
>>> ISA accessor ops, but have IO space, could be affected.
>>
>> You're already adding a Kconfig symbol for this stuff, so you can keep
>> that if you don't want it on other architectures. I'm just arguing that
>> plumbing drivers directly into arch code via arm64_set_extops is not
>> something I'm particularly fond of, especially when it looks like it
>> could be avoided with a small amount of effort.
>
> Agreed, I initially suggested putting this into arch/arm64/, but there isn't
> really a reason why it couldn't just live in lib/ with the header file
> bits moved to include/asm-generic/io.h which we already use.
>

Right, Zhichang will check the logistics of this. The generic io.h is 
quite clean, so as long as you don't mind new build switches of this 
nature being added, it should be ok; and we'll plan on moving extio.h 
into include/asm-generic as well.

Cheers,
John

> 	Arnd
>
> .
>


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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-09 11:29             ` John Garry
  0 siblings, 0 replies; 286+ messages in thread
From: John Garry @ 2016-11-09 11:29 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/11/2016 22:35, Arnd Bergmann wrote:
> On Tuesday, November 8, 2016 4:49:49 PM CET Will Deacon wrote:
>> On Tue, Nov 08, 2016 at 04:33:44PM +0000, John Garry wrote:
>>> On 08/11/2016 16:12, Will Deacon wrote:
>>>> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>
>>>> Is there no way to make this slightly more generic, so that it can be
>>>> re-used elsewhere? For example, if struct extio_ops was common, then
>>>> you could have the singleton (which maybe should be an interval tree?),
>>>> type definition, setter function and the BUILD_EXTIO invocations
>>>> somewhere generic, rather than squirelled away in the arch backend.
>>>>
>>> The concern would be that some architecture which uses generic higher-level
>>> ISA accessor ops, but have IO space, could be affected.
>>
>> You're already adding a Kconfig symbol for this stuff, so you can keep
>> that if you don't want it on other architectures. I'm just arguing that
>> plumbing drivers directly into arch code via arm64_set_extops is not
>> something I'm particularly fond of, especially when it looks like it
>> could be avoided with a small amount of effort.
>
> Agreed, I initially suggested putting this into arch/arm64/, but there isn't
> really a reason why it couldn't just live in lib/ with the header file
> bits moved to include/asm-generic/io.h which we already use.
>

Right, Zhichang will check the logistics of this. The generic io.h is 
quite clean, so as long as you don't mind new build switches of this 
nature being added, it should be ok; and we'll plan on moving extio.h 
into include/asm-generic as well.

Cheers,
John

> 	Arnd
>
> .
>

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-09 11:39     ` liviu.dudau-5wv7dgnIgG8
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau @ 2016-11-09 11:39 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, mark.rutland,
	olof, arnd, linux-arm-kernel, lorenzo.pieralisi, linux-kernel,
	linuxarm, devicetree, linux-pci, linux-serial, minyard, benh,
	zourongrong, john.garry, gabriele.paoloni, zhichang.yuan02,
	kantyzc, xuwei5

On Tue, Nov 08, 2016 at 11:47:08AM +0800, zhichang.yuan wrote:
> This patch solves two issues:
> 1) parse and get the right I/O range from DTS node whose parent does not
> define the corresponding ranges property;
> 
> 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 a fixup function, of_get_isa_indirect_io(). During the OF address
> translation, this fixup will be called to check the 'reg' address to be
> translating is for those sepcial ISA/LPC devices and get the I/O range
> directly from the 'reg' property.
> 
> 2) eliminate the I/O range conflict risk with PCI/PCIE leagecy I/O device;
> 
> The current __of_address_to_resource() always translates the I/O range to PIO.
> But this processing is not suitable for our ISA/LPC devices whose I/O range is
> not cpu address(Arnd had stressed this in his comments on V2,V3 patch-set).
> Here, we bypass the mapping between cpu address and PIO for the special
> ISA/LPC devices. But to drive these ISA/LPC devices, a I/O port address below
> PCIBIOS_MIN_IO is needed by in*/out*(). Which means there is conflict risk
> between I/O range of [0, PCIBIOS_MIN_IO) and PCI/PCIE legacy I/O range of [0,
> IO_SPACE_LIMIT).
> To avoid the I/O conflict, this patch reserve the I/O range below
> PCIBIOS_MIN_IO.
> 
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
>  .../arm/hisilicon/hisilicon-low-pin-count.txt      | 31 ++++++++++++
>  arch/arm64/include/asm/io.h                        |  6 +++
>  arch/arm64/kernel/extio.c                          | 25 ++++++++++
>  drivers/of/address.c                               | 56 +++++++++++++++++++++-
>  drivers/pci/pci.c                                  |  6 +--
>  include/linux/of_address.h                         | 17 +++++++
>  include/linux/pci.h                                |  8 ++++
>  7 files changed, 145 insertions(+), 4 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
> new file mode 100644
> index 0000000..13c8ddd
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
> @@ -0,0 +1,31 @@
> +Hisilicon Hip06 low-pin-count device
> +  Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
> +  locate on LPC bus can be accessed direclty. But some SoCs have independent
> +  LPC controller, and access the legacy ports by triggering LPC I/O cycles.
> +  Hisilicon Hip06 implements this LPC device.
> +
> +Required properties:
> +- compatible: should be "hisilicon,low-pin-count"
> +- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
> +- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
> +- reg: base memory range where the register set of this device is mapped.
> +
> +Note:
> +  The node name before '@' must be "isa" to represent the binding stick to the
> +  ISA/EISA binding specification.
> +
> +Example:
> +
> +isa@a01b0000 {
> +	compatible = "hisilicom,low-pin-count";
> +	#address-cells = <2>;
> +	#size-cells = <1>;
> +	reg = <0x0 0xa01b0000 0x0 0x1000>;
> +
> +	ipmi0: bt@e4 {
> +		compatible = "ipmi-bt";
> +		device_type = "ipmi";
> +		reg = <0x01 0xe4 0x04>;
> +		status = "disabled";
> +	};
> +};


This documentation file needs to be part of the next patch. It has nothing to do with
what you are trying to fix here.


> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> index 136735d..c26b7cc 100644
> --- a/arch/arm64/include/asm/io.h
> +++ b/arch/arm64/include/asm/io.h
> @@ -175,6 +175,12 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>  #define outsl outsl
>  
>  DECLARE_EXTIO(l, u32)
> +
> +#define indirect_io_enabled indirect_io_enabled
> +extern bool indirect_io_enabled(void);
> +
> +#define addr_is_indirect_io addr_is_indirect_io
> +extern int addr_is_indirect_io(u64 taddr);
>  #endif
>  
>  
> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> index 647b3fa..3d45fa8 100644
> --- a/arch/arm64/kernel/extio.c
> +++ b/arch/arm64/kernel/extio.c
> @@ -19,6 +19,31 @@
>  
>  struct extio_ops *arm64_extio_ops;
>  
> +/**
> + * indirect_io_enabled - check whether indirectIO is enabled.
> + *	arm64_extio_ops will be set only when indirectIO mechanism had been
> + *	initialized.
> + *
> + * Returns true when indirectIO is enabled.
> + */
> +bool indirect_io_enabled(void)
> +{
> +	return arm64_extio_ops ? true : false;
> +}
> +
> +/**
> + * addr_is_indirect_io - check whether the input taddr is for indirectIO.
> + * @taddr: the io address to be checked.
> + *
> + * Returns 1 when taddr is in the range; otherwise return 0.
> + */
> +int addr_is_indirect_io(u64 taddr)
> +{
> +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end < taddr)

start >= taddr ?

> +		return 0;
> +
> +	return 1;
> +}
>  
>  BUILD_EXTIO(b, u8)
>  
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903..cc2a05d 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct device_node *np)
>  	return false;
>  }
>  
> +
> +/*
> + * of_isa_indirect_io - get the IO address from some isa reg property value.
> + *	For some isa/lpc devices, no ranges property in ancestor node.
> + *	The device addresses are described directly in their regs property.
> + *	This fixup function will be called to get the IO address of isa/lpc
> + *	devices when the normal of_translation failed.
> + *
> + * @parent:	points to the parent dts node;
> + * @bus:		points to the of_bus which can be used to parse address;
> + * @addr:	the address from reg property;
> + * @na:		the address cell counter of @addr;
> + * @presult:	store the address paresed from @addr;
> + *
> + * return 1 when successfully get the I/O address;
> + * 0 will return for some failures.

Bah, you are returning a signed int, why 0 for failure? Return a negative value with
error codes. Otherwise change the return value into a bool.

> + */
> +static int of_get_isa_indirect_io(struct device_node *parent,
> +				struct of_bus *bus, __be32 *addr,
> +				int na, u64 *presult)
> +{
> +	unsigned int flags;
> +	unsigned int rlen;
> +
> +	/* whether support indirectIO */
> +	if (!indirect_io_enabled())
> +		return 0;
> +
> +	if (!of_bus_isa_match(parent))
> +		return 0;
> +
> +	flags = bus->get_flags(addr);
> +	if (!(flags & IORESOURCE_IO))
> +		return 0;
> +
> +	/* there is ranges property, apply the normal translation directly. */

s/there is ranges/if we have a 'ranges'/

> +	if (of_get_property(parent, "ranges", &rlen))
> +		return 0;
> +
> +	*presult = of_read_number(addr + 1, na - 1);
> +	/* this fixup is only valid for specific I/O range. */
> +	return addr_is_indirect_io(*presult);
> +}
> +
>  static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>  			    struct of_bus *pbus, __be32 *addr,
>  			    int na, int ns, int pna, const char *rprop)
> @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct device_node *dev,
>  			result = of_read_number(addr, na);
>  			break;
>  		}
> +		/*
> +		 * For indirectIO device which has no ranges property, get
> +		 * the address from reg directly.
> +		 */
> +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> +			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
> +				of_node_full_name(dev), result);
> +			break;
> +		}
>  
>  		/* Get new parent bus and counts */
>  		pbus = of_match_bus(parent);
> @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct device_node *dev,
>  	if (taddr == OF_BAD_ADDR)
>  		return -EINVAL;
>  	memset(r, 0, sizeof(struct resource));
> -	if (flags & IORESOURCE_IO) {
> +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
>  		unsigned long port;
> +
>  		port = pci_address_to_pio(taddr);
>  		if (port == (unsigned long)-1)
>  			return -EINVAL;
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index ba34907..1a08511 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -3263,7 +3263,7 @@ 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;
> +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
>  
>  	/* check if the range hasn't been previously recorded */
>  	spin_lock(&io_range_lock);
> @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
>  
>  #ifdef PCI_IOBASE
>  	struct io_range *range;
> -	resource_size_t allocated_size = 0;
> +	resource_size_t allocated_size = PCIBIOS_MIN_IO;

Have you checked that pci_pio_to_address still returns valid values after this? I know that
you are trying to take into account PCIBIOS_MIN_IO limit when allocating reserving the IO ranges,
but the values added in the io_range_list are still starting from zero, no from PCIBIOS_MIN_IO,
so the calculation of the address in this function could return negative values casted to pci_addr_t.

Maybe you want to adjust the range->start value in pci_register_io_range() as well to have it
offset by PCIBIOS_MIN_IO as well.

Best regards,
Liviu

>  
>  	if (pio > IO_SPACE_LIMIT)
>  		return address;
> @@ -3335,7 +3335,7 @@ unsigned long __weak pci_address_to_pio(phys_addr_t address)
>  {
>  #ifdef PCI_IOBASE
>  	struct io_range *res;
> -	resource_size_t offset = 0;
> +	resource_size_t offset = PCIBIOS_MIN_IO;
>  	unsigned long addr = -1;
>  
>  	spin_lock(&io_range_lock);
> diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> index 3786473..deec469 100644
> --- a/include/linux/of_address.h
> +++ b/include/linux/of_address.h
> @@ -24,6 +24,23 @@ struct of_pci_range {
>  #define for_each_of_pci_range(parser, range) \
>  	for (; of_pci_range_parser_one(parser, range);)
>  
> +
> +#ifndef indirect_io_enabled
> +#define indirect_io_enabled indirect_io_enabled
> +static inline bool indirect_io_enabled(void)
> +{
> +	return false;
> +}
> +#endif
> +
> +#ifndef addr_is_indirect_io
> +#define addr_is_indirect_io addr_is_indirect_io
> +static inline int addr_is_indirect_io(u64 taddr)
> +{
> +	return 0;
> +}
> +#endif
> +
>  /* Translate a DMA address from device space to CPU space */
>  extern u64 of_translate_dma_address(struct device_node *dev,
>  				    const __be32 *in_addr);
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 0e49f70..7f6bbb6 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct pci_bus *bus)
>  /* provide the legacy pci_dma_* API */
>  #include <linux/pci-dma-compat.h>
>  
> +/*
> + * define this macro here to refrain from compilation error for some
> + * platforms. Please keep this macro at the end of this header file.
> + */
> +#ifndef PCIBIOS_MIN_IO
> +#define PCIBIOS_MIN_IO		0
> +#endif
> +
>  #endif /* LINUX_PCI_H */
> -- 
> 1.9.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-09 11:39     ` liviu.dudau-5wv7dgnIgG8
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau-5wv7dgnIgG8 @ 2016-11-09 11:39 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, bhelgaas-hpIqsD4AKlfQT0dZR+AlfA,
	mark.rutland-5wv7dgnIgG8, olof-nZhT3qVonbNeoWH0uzbU5w,
	arnd-r2nGTMty4D4,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	lorenzo.pieralisi-5wv7dgnIgG8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linuxarm-hv44wF8Li93QT0dZR+AlfA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, minyard-HInyCGIudOg,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
	john.garry-hv44wF8Li93QT0dZR+AlfA,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w, kantyzc-9Onoh4P/yGk,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q

On Tue, Nov 08, 2016 at 11:47:08AM +0800, zhichang.yuan wrote:
> This patch solves two issues:
> 1) parse and get the right I/O range from DTS node whose parent does not
> define the corresponding ranges property;
> 
> 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 a fixup function, of_get_isa_indirect_io(). During the OF address
> translation, this fixup will be called to check the 'reg' address to be
> translating is for those sepcial ISA/LPC devices and get the I/O range
> directly from the 'reg' property.
> 
> 2) eliminate the I/O range conflict risk with PCI/PCIE leagecy I/O device;
> 
> The current __of_address_to_resource() always translates the I/O range to PIO.
> But this processing is not suitable for our ISA/LPC devices whose I/O range is
> not cpu address(Arnd had stressed this in his comments on V2,V3 patch-set).
> Here, we bypass the mapping between cpu address and PIO for the special
> ISA/LPC devices. But to drive these ISA/LPC devices, a I/O port address below
> PCIBIOS_MIN_IO is needed by in*/out*(). Which means there is conflict risk
> between I/O range of [0, PCIBIOS_MIN_IO) and PCI/PCIE legacy I/O range of [0,
> IO_SPACE_LIMIT).
> To avoid the I/O conflict, this patch reserve the I/O range below
> PCIBIOS_MIN_IO.
> 
> Signed-off-by: zhichang.yuan <yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
> ---
>  .../arm/hisilicon/hisilicon-low-pin-count.txt      | 31 ++++++++++++
>  arch/arm64/include/asm/io.h                        |  6 +++
>  arch/arm64/kernel/extio.c                          | 25 ++++++++++
>  drivers/of/address.c                               | 56 +++++++++++++++++++++-
>  drivers/pci/pci.c                                  |  6 +--
>  include/linux/of_address.h                         | 17 +++++++
>  include/linux/pci.h                                |  8 ++++
>  7 files changed, 145 insertions(+), 4 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
> new file mode 100644
> index 0000000..13c8ddd
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
> @@ -0,0 +1,31 @@
> +Hisilicon Hip06 low-pin-count device
> +  Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
> +  locate on LPC bus can be accessed direclty. But some SoCs have independent
> +  LPC controller, and access the legacy ports by triggering LPC I/O cycles.
> +  Hisilicon Hip06 implements this LPC device.
> +
> +Required properties:
> +- compatible: should be "hisilicon,low-pin-count"
> +- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
> +- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
> +- reg: base memory range where the register set of this device is mapped.
> +
> +Note:
> +  The node name before '@' must be "isa" to represent the binding stick to the
> +  ISA/EISA binding specification.
> +
> +Example:
> +
> +isa@a01b0000 {
> +	compatible = "hisilicom,low-pin-count";
> +	#address-cells = <2>;
> +	#size-cells = <1>;
> +	reg = <0x0 0xa01b0000 0x0 0x1000>;
> +
> +	ipmi0: bt@e4 {
> +		compatible = "ipmi-bt";
> +		device_type = "ipmi";
> +		reg = <0x01 0xe4 0x04>;
> +		status = "disabled";
> +	};
> +};


This documentation file needs to be part of the next patch. It has nothing to do with
what you are trying to fix here.


> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> index 136735d..c26b7cc 100644
> --- a/arch/arm64/include/asm/io.h
> +++ b/arch/arm64/include/asm/io.h
> @@ -175,6 +175,12 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>  #define outsl outsl
>  
>  DECLARE_EXTIO(l, u32)
> +
> +#define indirect_io_enabled indirect_io_enabled
> +extern bool indirect_io_enabled(void);
> +
> +#define addr_is_indirect_io addr_is_indirect_io
> +extern int addr_is_indirect_io(u64 taddr);
>  #endif
>  
>  
> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> index 647b3fa..3d45fa8 100644
> --- a/arch/arm64/kernel/extio.c
> +++ b/arch/arm64/kernel/extio.c
> @@ -19,6 +19,31 @@
>  
>  struct extio_ops *arm64_extio_ops;
>  
> +/**
> + * indirect_io_enabled - check whether indirectIO is enabled.
> + *	arm64_extio_ops will be set only when indirectIO mechanism had been
> + *	initialized.
> + *
> + * Returns true when indirectIO is enabled.
> + */
> +bool indirect_io_enabled(void)
> +{
> +	return arm64_extio_ops ? true : false;
> +}
> +
> +/**
> + * addr_is_indirect_io - check whether the input taddr is for indirectIO.
> + * @taddr: the io address to be checked.
> + *
> + * Returns 1 when taddr is in the range; otherwise return 0.
> + */
> +int addr_is_indirect_io(u64 taddr)
> +{
> +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end < taddr)

start >= taddr ?

> +		return 0;
> +
> +	return 1;
> +}
>  
>  BUILD_EXTIO(b, u8)
>  
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903..cc2a05d 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct device_node *np)
>  	return false;
>  }
>  
> +
> +/*
> + * of_isa_indirect_io - get the IO address from some isa reg property value.
> + *	For some isa/lpc devices, no ranges property in ancestor node.
> + *	The device addresses are described directly in their regs property.
> + *	This fixup function will be called to get the IO address of isa/lpc
> + *	devices when the normal of_translation failed.
> + *
> + * @parent:	points to the parent dts node;
> + * @bus:		points to the of_bus which can be used to parse address;
> + * @addr:	the address from reg property;
> + * @na:		the address cell counter of @addr;
> + * @presult:	store the address paresed from @addr;
> + *
> + * return 1 when successfully get the I/O address;
> + * 0 will return for some failures.

Bah, you are returning a signed int, why 0 for failure? Return a negative value with
error codes. Otherwise change the return value into a bool.

> + */
> +static int of_get_isa_indirect_io(struct device_node *parent,
> +				struct of_bus *bus, __be32 *addr,
> +				int na, u64 *presult)
> +{
> +	unsigned int flags;
> +	unsigned int rlen;
> +
> +	/* whether support indirectIO */
> +	if (!indirect_io_enabled())
> +		return 0;
> +
> +	if (!of_bus_isa_match(parent))
> +		return 0;
> +
> +	flags = bus->get_flags(addr);
> +	if (!(flags & IORESOURCE_IO))
> +		return 0;
> +
> +	/* there is ranges property, apply the normal translation directly. */

s/there is ranges/if we have a 'ranges'/

> +	if (of_get_property(parent, "ranges", &rlen))
> +		return 0;
> +
> +	*presult = of_read_number(addr + 1, na - 1);
> +	/* this fixup is only valid for specific I/O range. */
> +	return addr_is_indirect_io(*presult);
> +}
> +
>  static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>  			    struct of_bus *pbus, __be32 *addr,
>  			    int na, int ns, int pna, const char *rprop)
> @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct device_node *dev,
>  			result = of_read_number(addr, na);
>  			break;
>  		}
> +		/*
> +		 * For indirectIO device which has no ranges property, get
> +		 * the address from reg directly.
> +		 */
> +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> +			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
> +				of_node_full_name(dev), result);
> +			break;
> +		}
>  
>  		/* Get new parent bus and counts */
>  		pbus = of_match_bus(parent);
> @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct device_node *dev,
>  	if (taddr == OF_BAD_ADDR)
>  		return -EINVAL;
>  	memset(r, 0, sizeof(struct resource));
> -	if (flags & IORESOURCE_IO) {
> +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
>  		unsigned long port;
> +
>  		port = pci_address_to_pio(taddr);
>  		if (port == (unsigned long)-1)
>  			return -EINVAL;
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index ba34907..1a08511 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -3263,7 +3263,7 @@ 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;
> +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
>  
>  	/* check if the range hasn't been previously recorded */
>  	spin_lock(&io_range_lock);
> @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
>  
>  #ifdef PCI_IOBASE
>  	struct io_range *range;
> -	resource_size_t allocated_size = 0;
> +	resource_size_t allocated_size = PCIBIOS_MIN_IO;

Have you checked that pci_pio_to_address still returns valid values after this? I know that
you are trying to take into account PCIBIOS_MIN_IO limit when allocating reserving the IO ranges,
but the values added in the io_range_list are still starting from zero, no from PCIBIOS_MIN_IO,
so the calculation of the address in this function could return negative values casted to pci_addr_t.

Maybe you want to adjust the range->start value in pci_register_io_range() as well to have it
offset by PCIBIOS_MIN_IO as well.

Best regards,
Liviu

>  
>  	if (pio > IO_SPACE_LIMIT)
>  		return address;
> @@ -3335,7 +3335,7 @@ unsigned long __weak pci_address_to_pio(phys_addr_t address)
>  {
>  #ifdef PCI_IOBASE
>  	struct io_range *res;
> -	resource_size_t offset = 0;
> +	resource_size_t offset = PCIBIOS_MIN_IO;
>  	unsigned long addr = -1;
>  
>  	spin_lock(&io_range_lock);
> diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> index 3786473..deec469 100644
> --- a/include/linux/of_address.h
> +++ b/include/linux/of_address.h
> @@ -24,6 +24,23 @@ struct of_pci_range {
>  #define for_each_of_pci_range(parser, range) \
>  	for (; of_pci_range_parser_one(parser, range);)
>  
> +
> +#ifndef indirect_io_enabled
> +#define indirect_io_enabled indirect_io_enabled
> +static inline bool indirect_io_enabled(void)
> +{
> +	return false;
> +}
> +#endif
> +
> +#ifndef addr_is_indirect_io
> +#define addr_is_indirect_io addr_is_indirect_io
> +static inline int addr_is_indirect_io(u64 taddr)
> +{
> +	return 0;
> +}
> +#endif
> +
>  /* Translate a DMA address from device space to CPU space */
>  extern u64 of_translate_dma_address(struct device_node *dev,
>  				    const __be32 *in_addr);
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 0e49f70..7f6bbb6 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct pci_bus *bus)
>  /* provide the legacy pci_dma_* API */
>  #include <linux/pci-dma-compat.h>
>  
> +/*
> + * define this macro here to refrain from compilation error for some
> + * platforms. Please keep this macro at the end of this header file.
> + */
> +#ifndef PCIBIOS_MIN_IO
> +#define PCIBIOS_MIN_IO		0
> +#endif
> +
>  #endif /* LINUX_PCI_H */
> -- 
> 1.9.1
> 
> --
> 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] 286+ messages in thread

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-09 11:39     ` liviu.dudau-5wv7dgnIgG8
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau at arm.com @ 2016-11-09 11:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Nov 08, 2016 at 11:47:08AM +0800, zhichang.yuan wrote:
> This patch solves two issues:
> 1) parse and get the right I/O range from DTS node whose parent does not
> define the corresponding ranges property;
> 
> 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 a fixup function, of_get_isa_indirect_io(). During the OF address
> translation, this fixup will be called to check the 'reg' address to be
> translating is for those sepcial ISA/LPC devices and get the I/O range
> directly from the 'reg' property.
> 
> 2) eliminate the I/O range conflict risk with PCI/PCIE leagecy I/O device;
> 
> The current __of_address_to_resource() always translates the I/O range to PIO.
> But this processing is not suitable for our ISA/LPC devices whose I/O range is
> not cpu address(Arnd had stressed this in his comments on V2,V3 patch-set).
> Here, we bypass the mapping between cpu address and PIO for the special
> ISA/LPC devices. But to drive these ISA/LPC devices, a I/O port address below
> PCIBIOS_MIN_IO is needed by in*/out*(). Which means there is conflict risk
> between I/O range of [0, PCIBIOS_MIN_IO) and PCI/PCIE legacy I/O range of [0,
> IO_SPACE_LIMIT).
> To avoid the I/O conflict, this patch reserve the I/O range below
> PCIBIOS_MIN_IO.
> 
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
>  .../arm/hisilicon/hisilicon-low-pin-count.txt      | 31 ++++++++++++
>  arch/arm64/include/asm/io.h                        |  6 +++
>  arch/arm64/kernel/extio.c                          | 25 ++++++++++
>  drivers/of/address.c                               | 56 +++++++++++++++++++++-
>  drivers/pci/pci.c                                  |  6 +--
>  include/linux/of_address.h                         | 17 +++++++
>  include/linux/pci.h                                |  8 ++++
>  7 files changed, 145 insertions(+), 4 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
> new file mode 100644
> index 0000000..13c8ddd
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
> @@ -0,0 +1,31 @@
> +Hisilicon Hip06 low-pin-count device
> +  Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
> +  locate on LPC bus can be accessed direclty. But some SoCs have independent
> +  LPC controller, and access the legacy ports by triggering LPC I/O cycles.
> +  Hisilicon Hip06 implements this LPC device.
> +
> +Required properties:
> +- compatible: should be "hisilicon,low-pin-count"
> +- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
> +- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
> +- reg: base memory range where the register set of this device is mapped.
> +
> +Note:
> +  The node name before '@' must be "isa" to represent the binding stick to the
> +  ISA/EISA binding specification.
> +
> +Example:
> +
> +isa at a01b0000 {
> +	compatible = "hisilicom,low-pin-count";
> +	#address-cells = <2>;
> +	#size-cells = <1>;
> +	reg = <0x0 0xa01b0000 0x0 0x1000>;
> +
> +	ipmi0: bt at e4 {
> +		compatible = "ipmi-bt";
> +		device_type = "ipmi";
> +		reg = <0x01 0xe4 0x04>;
> +		status = "disabled";
> +	};
> +};


This documentation file needs to be part of the next patch. It has nothing to do with
what you are trying to fix here.


> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> index 136735d..c26b7cc 100644
> --- a/arch/arm64/include/asm/io.h
> +++ b/arch/arm64/include/asm/io.h
> @@ -175,6 +175,12 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>  #define outsl outsl
>  
>  DECLARE_EXTIO(l, u32)
> +
> +#define indirect_io_enabled indirect_io_enabled
> +extern bool indirect_io_enabled(void);
> +
> +#define addr_is_indirect_io addr_is_indirect_io
> +extern int addr_is_indirect_io(u64 taddr);
>  #endif
>  
>  
> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> index 647b3fa..3d45fa8 100644
> --- a/arch/arm64/kernel/extio.c
> +++ b/arch/arm64/kernel/extio.c
> @@ -19,6 +19,31 @@
>  
>  struct extio_ops *arm64_extio_ops;
>  
> +/**
> + * indirect_io_enabled - check whether indirectIO is enabled.
> + *	arm64_extio_ops will be set only when indirectIO mechanism had been
> + *	initialized.
> + *
> + * Returns true when indirectIO is enabled.
> + */
> +bool indirect_io_enabled(void)
> +{
> +	return arm64_extio_ops ? true : false;
> +}
> +
> +/**
> + * addr_is_indirect_io - check whether the input taddr is for indirectIO.
> + * @taddr: the io address to be checked.
> + *
> + * Returns 1 when taddr is in the range; otherwise return 0.
> + */
> +int addr_is_indirect_io(u64 taddr)
> +{
> +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end < taddr)

start >= taddr ?

> +		return 0;
> +
> +	return 1;
> +}
>  
>  BUILD_EXTIO(b, u8)
>  
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903..cc2a05d 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct device_node *np)
>  	return false;
>  }
>  
> +
> +/*
> + * of_isa_indirect_io - get the IO address from some isa reg property value.
> + *	For some isa/lpc devices, no ranges property in ancestor node.
> + *	The device addresses are described directly in their regs property.
> + *	This fixup function will be called to get the IO address of isa/lpc
> + *	devices when the normal of_translation failed.
> + *
> + * @parent:	points to the parent dts node;
> + * @bus:		points to the of_bus which can be used to parse address;
> + * @addr:	the address from reg property;
> + * @na:		the address cell counter of @addr;
> + * @presult:	store the address paresed from @addr;
> + *
> + * return 1 when successfully get the I/O address;
> + * 0 will return for some failures.

Bah, you are returning a signed int, why 0 for failure? Return a negative value with
error codes. Otherwise change the return value into a bool.

> + */
> +static int of_get_isa_indirect_io(struct device_node *parent,
> +				struct of_bus *bus, __be32 *addr,
> +				int na, u64 *presult)
> +{
> +	unsigned int flags;
> +	unsigned int rlen;
> +
> +	/* whether support indirectIO */
> +	if (!indirect_io_enabled())
> +		return 0;
> +
> +	if (!of_bus_isa_match(parent))
> +		return 0;
> +
> +	flags = bus->get_flags(addr);
> +	if (!(flags & IORESOURCE_IO))
> +		return 0;
> +
> +	/* there is ranges property, apply the normal translation directly. */

s/there is ranges/if we have a 'ranges'/

> +	if (of_get_property(parent, "ranges", &rlen))
> +		return 0;
> +
> +	*presult = of_read_number(addr + 1, na - 1);
> +	/* this fixup is only valid for specific I/O range. */
> +	return addr_is_indirect_io(*presult);
> +}
> +
>  static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>  			    struct of_bus *pbus, __be32 *addr,
>  			    int na, int ns, int pna, const char *rprop)
> @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct device_node *dev,
>  			result = of_read_number(addr, na);
>  			break;
>  		}
> +		/*
> +		 * For indirectIO device which has no ranges property, get
> +		 * the address from reg directly.
> +		 */
> +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> +			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
> +				of_node_full_name(dev), result);
> +			break;
> +		}
>  
>  		/* Get new parent bus and counts */
>  		pbus = of_match_bus(parent);
> @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct device_node *dev,
>  	if (taddr == OF_BAD_ADDR)
>  		return -EINVAL;
>  	memset(r, 0, sizeof(struct resource));
> -	if (flags & IORESOURCE_IO) {
> +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
>  		unsigned long port;
> +
>  		port = pci_address_to_pio(taddr);
>  		if (port == (unsigned long)-1)
>  			return -EINVAL;
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index ba34907..1a08511 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -3263,7 +3263,7 @@ 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;
> +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
>  
>  	/* check if the range hasn't been previously recorded */
>  	spin_lock(&io_range_lock);
> @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
>  
>  #ifdef PCI_IOBASE
>  	struct io_range *range;
> -	resource_size_t allocated_size = 0;
> +	resource_size_t allocated_size = PCIBIOS_MIN_IO;

Have you checked that pci_pio_to_address still returns valid values after this? I know that
you are trying to take into account PCIBIOS_MIN_IO limit when allocating reserving the IO ranges,
but the values added in the io_range_list are still starting from zero, no from PCIBIOS_MIN_IO,
so the calculation of the address in this function could return negative values casted to pci_addr_t.

Maybe you want to adjust the range->start value in pci_register_io_range() as well to have it
offset by PCIBIOS_MIN_IO as well.

Best regards,
Liviu

>  
>  	if (pio > IO_SPACE_LIMIT)
>  		return address;
> @@ -3335,7 +3335,7 @@ unsigned long __weak pci_address_to_pio(phys_addr_t address)
>  {
>  #ifdef PCI_IOBASE
>  	struct io_range *res;
> -	resource_size_t offset = 0;
> +	resource_size_t offset = PCIBIOS_MIN_IO;
>  	unsigned long addr = -1;
>  
>  	spin_lock(&io_range_lock);
> diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> index 3786473..deec469 100644
> --- a/include/linux/of_address.h
> +++ b/include/linux/of_address.h
> @@ -24,6 +24,23 @@ struct of_pci_range {
>  #define for_each_of_pci_range(parser, range) \
>  	for (; of_pci_range_parser_one(parser, range);)
>  
> +
> +#ifndef indirect_io_enabled
> +#define indirect_io_enabled indirect_io_enabled
> +static inline bool indirect_io_enabled(void)
> +{
> +	return false;
> +}
> +#endif
> +
> +#ifndef addr_is_indirect_io
> +#define addr_is_indirect_io addr_is_indirect_io
> +static inline int addr_is_indirect_io(u64 taddr)
> +{
> +	return 0;
> +}
> +#endif
> +
>  /* Translate a DMA address from device space to CPU space */
>  extern u64 of_translate_dma_address(struct device_node *dev,
>  				    const __be32 *in_addr);
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 0e49f70..7f6bbb6 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct pci_bus *bus)
>  /* provide the legacy pci_dma_* API */
>  #include <linux/pci-dma-compat.h>
>  
> +/*
> + * define this macro here to refrain from compilation error for some
> + * platforms. Please keep this macro at the end of this header file.
> + */
> +#ifndef PCIBIOS_MIN_IO
> +#define PCIBIOS_MIN_IO		0
> +#endif
> +
>  #endif /* LINUX_PCI_H */
> -- 
> 1.9.1
> 
> --
> 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] 286+ messages in thread

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-08 16:24     ` Arnd Bergmann
  (?)
  (?)
@ 2016-11-09 12:10       ` Gabriele Paoloni
  -1 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-09 12:10 UTC (permalink / raw)
  To: Arnd Bergmann, Yuanzhichang
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, mark.rutland,
	olof, linux-arm-kernel, lorenzo.pieralisi, linux-kernel,
	Linuxarm, devicetree, linux-pci, linux-serial, minyard, benh,
	liviu.dudau, zourongrong, John Garry, zhichang.yuan02, kantyzc,
	xuwei (O)

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 08 November 2016 16:25
> To: Yuanzhichang
> Cc: catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> bhelgaas@google.com; mark.rutland@arm.com; olof@lixom.net; linux-arm-
> kernel@lists.infradead.org; lorenzo.pieralisi@arm.com; linux-
> kernel@vger.kernel.org; Linuxarm; devicetree@vger.kernel.org; linux-
> pci@vger.kernel.org; linux-serial@vger.kernel.org; minyard@acm.org;
> benh@kernel.crashing.org; liviu.dudau@arm.com; zourongrong@gmail.com;
> John Garry; Gabriele Paoloni; zhichang.yuan02@gmail.com;
> kantyzc@163.com; xuwei (O)
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
> > +       /*
> > +        * The first PCIBIOS_MIN_IO is reserved specifically for
> indirectIO.
> > +        * It will separate indirectIO range from pci host bridge to
> > +        * avoid the possible PIO conflict.
> > +        * Set the indirectIO range directly here.
> > +        */
> > +       lpcdev->io_ops.start = 0;
> > +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> > +       lpcdev->io_ops.devpara = lpcdev;
> > +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> > +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> > +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> > +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
> 
> I have to look at patch 2 in more detail again, after missing a few
> review
> rounds. I'm still a bit skeptical about hardcoding a logical I/O port
> range here, and would hope that we can just go through the same
> assignment of logical port ranges that we have for PCI buses,
> decoupling
> the bus addresses from the linux-internal ones.

The point here is that we want to avoid any conflict/overlap between
the LPC I/O space and the PCI I/O space. With the assignment above
we make sure that LPC never interfere with PCI I/O space.

Thanks

Gab

> 
> 	Arnd

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-09 12:10       ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-09 12:10 UTC (permalink / raw)
  To: Arnd Bergmann, Yuanzhichang
  Cc: catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, bhelgaas-hpIqsD4AKlfQT0dZR+AlfA,
	mark.rutland-5wv7dgnIgG8, olof-nZhT3qVonbNeoWH0uzbU5w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	lorenzo.pieralisi-5wv7dgnIgG8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Linuxarm,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, minyard-HInyCGIudOg,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd-r2nGTMty4D4@public.gmane.org]
> Sent: 08 November 2016 16:25
> To: Yuanzhichang
> Cc: catalin.marinas-5wv7dgnIgG8@public.gmane.org; will.deacon-5wv7dgnIgG8@public.gmane.org; robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org;
> bhelgaas-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org; mark.rutland-5wv7dgnIgG8@public.gmane.org; olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org; linux-arm-
> kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org; lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org; linux-
> kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; Linuxarm; devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux-
> pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; minyard-HInyCGIudOg@public.gmane.org;
> benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org; liviu.dudau-5wv7dgnIgG8@public.gmane.org; zourongrong-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org;
> John Garry; Gabriele Paoloni; zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org;
> kantyzc-9Onoh4P/yGk@public.gmane.org; xuwei (O)
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
> > +       /*
> > +        * The first PCIBIOS_MIN_IO is reserved specifically for
> indirectIO.
> > +        * It will separate indirectIO range from pci host bridge to
> > +        * avoid the possible PIO conflict.
> > +        * Set the indirectIO range directly here.
> > +        */
> > +       lpcdev->io_ops.start = 0;
> > +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> > +       lpcdev->io_ops.devpara = lpcdev;
> > +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> > +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> > +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> > +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
> 
> I have to look at patch 2 in more detail again, after missing a few
> review
> rounds. I'm still a bit skeptical about hardcoding a logical I/O port
> range here, and would hope that we can just go through the same
> assignment of logical port ranges that we have for PCI buses,
> decoupling
> the bus addresses from the linux-internal ones.

The point here is that we want to avoid any conflict/overlap between
the LPC I/O space and the PCI I/O space. With the assignment above
we make sure that LPC never interfere with PCI I/O space.

Thanks

Gab

> 
> 	Arnd
--
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] 286+ messages in thread

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-09 12:10       ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-09 12:10 UTC (permalink / raw)
  To: Arnd Bergmann, Yuanzhichang
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, mark.rutland,
	olof, linux-arm-kernel, lorenzo.pieralisi, linux-kernel,
	Linuxarm, devicetree, linux-pci, linux-serial, minyard, benh,
	liviu.dudau, zourongrong, John Garry, zhichang.yuan02, kantyzc,
	xuwei (O)

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 08 November 2016 16:25
> To: Yuanzhichang
> Cc: catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> bhelgaas@google.com; mark.rutland@arm.com; olof@lixom.net; linux-arm-
> kernel@lists.infradead.org; lorenzo.pieralisi@arm.com; linux-
> kernel@vger.kernel.org; Linuxarm; devicetree@vger.kernel.org; linux-
> pci@vger.kernel.org; linux-serial@vger.kernel.org; minyard@acm.org;
> benh@kernel.crashing.org; liviu.dudau@arm.com; zourongrong@gmail.com;
> John Garry; Gabriele Paoloni; zhichang.yuan02@gmail.com;
> kantyzc@163.com; xuwei (O)
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
> > +       /*
> > +        * The first PCIBIOS_MIN_IO is reserved specifically for
> indirectIO.
> > +        * It will separate indirectIO range from pci host bridge to
> > +        * avoid the possible PIO conflict.
> > +        * Set the indirectIO range directly here.
> > +        */
> > +       lpcdev->io_ops.start = 0;
> > +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> > +       lpcdev->io_ops.devpara = lpcdev;
> > +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> > +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> > +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> > +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
> 
> I have to look at patch 2 in more detail again, after missing a few
> review
> rounds. I'm still a bit skeptical about hardcoding a logical I/O port
> range here, and would hope that we can just go through the same
> assignment of logical port ranges that we have for PCI buses,
> decoupling
> the bus addresses from the linux-internal ones.

The point here is that we want to avoid any conflict/overlap between
the LPC I/O space and the PCI I/O space. With the assignment above
we make sure that LPC never interfere with PCI I/O space.

Thanks

Gab

> 
> 	Arnd

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-09 12:10       ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-09 12:10 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 08 November 2016 16:25
> To: Yuanzhichang
> Cc: catalin.marinas at arm.com; will.deacon at arm.com; robh+dt at kernel.org;
> bhelgaas at google.com; mark.rutland at arm.com; olof at lixom.net; linux-arm-
> kernel at lists.infradead.org; lorenzo.pieralisi at arm.com; linux-
> kernel at vger.kernel.org; Linuxarm; devicetree at vger.kernel.org; linux-
> pci at vger.kernel.org; linux-serial at vger.kernel.org; minyard at acm.org;
> benh at kernel.crashing.org; liviu.dudau at arm.com; zourongrong at gmail.com;
> John Garry; Gabriele Paoloni; zhichang.yuan02 at gmail.com;
> kantyzc at 163.com; xuwei (O)
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
> > +       /*
> > +        * The first PCIBIOS_MIN_IO is reserved specifically for
> indirectIO.
> > +        * It will separate indirectIO range from pci host bridge to
> > +        * avoid the possible PIO conflict.
> > +        * Set the indirectIO range directly here.
> > +        */
> > +       lpcdev->io_ops.start = 0;
> > +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> > +       lpcdev->io_ops.devpara = lpcdev;
> > +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> > +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> > +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> > +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
> 
> I have to look at patch 2 in more detail again, after missing a few
> review
> rounds. I'm still a bit skeptical about hardcoding a logical I/O port
> range here, and would hope that we can just go through the same
> assignment of logical port ranges that we have for PCI buses,
> decoupling
> the bus addresses from the linux-internal ones.

The point here is that we want to avoid any conflict/overlap between
the LPC I/O space and the PCI I/O space. With the assignment above
we make sure that LPC never interfere with PCI I/O space.

Thanks

Gab

> 
> 	Arnd

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
  2016-11-08 16:19       ` Arnd Bergmann
@ 2016-11-09 13:54         ` One Thousand Gnomes
  -1 siblings, 0 replies; 286+ messages in thread
From: One Thousand Gnomes @ 2016-11-09 13:54 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Mark Rutland, zhichang.yuan, catalin.marinas, will.deacon,
	robh+dt, bhelgaas, olof, linux-arm-kernel, lorenzo.pieralisi,
	linux-kernel, linuxarm, devicetree, linux-pci, linux-serial,
	minyard, benh, liviu.dudau, zourongrong, john.garry,
	gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5, marc.zyngier

> I think it is a relatively safe assumption that there is only one
> ISA bridge. A lot of old drivers hardcode PIO or memory addresses

It's not a safe assumption for x86 at least. There are a few systems with
multiple ISA busses particularly older laptops with a docking station.

> when talking to an ISA device, so having multiple instances is
> already problematic.

PCMCIA devices handle it themselves so are ok. I'm not clear how the dual
PIIX4 configuration used in the older IBM laptop docks actually worked so
I assume the transaction went out of both bridges and providing one of
them responded the other kept silent as you simply stuffed the card into
the dock and it worked.

Alan

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

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-09 13:54         ` One Thousand Gnomes
  0 siblings, 0 replies; 286+ messages in thread
From: One Thousand Gnomes @ 2016-11-09 13:54 UTC (permalink / raw)
  To: linux-arm-kernel

> I think it is a relatively safe assumption that there is only one
> ISA bridge. A lot of old drivers hardcode PIO or memory addresses

It's not a safe assumption for x86 at least. There are a few systems with
multiple ISA busses particularly older laptops with a docking station.

> when talking to an ISA device, so having multiple instances is
> already problematic.

PCMCIA devices handle it themselves so are ok. I'm not clear how the dual
PIIX4 configuration used in the older IBM laptop docks actually worked so
I assume the transaction went out of both bridges and providing one of
them responded the other kept silent as you simply stuffed the card into
the dock and it worked.

Alan

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

* RE: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-09 14:51           ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-09 14:51 UTC (permalink / raw)
  To: One Thousand Gnomes, Arnd Bergmann
  Cc: Mark Rutland, Yuanzhichang, catalin.marinas, will.deacon,
	robh+dt, bhelgaas, olof, linux-arm-kernel, lorenzo.pieralisi,
	linux-kernel, Linuxarm, devicetree, linux-pci, linux-serial,
	minyard, benh, liviu.dudau, zourongrong, John Garry,
	zhichang.yuan02, kantyzc, xuwei (O),
	marc.zyngier

> -----Original Message-----
> From: One Thousand Gnomes [mailto:gnomes@lxorguk.ukuu.org.uk]
> Sent: 09 November 2016 13:55
> To: Arnd Bergmann
> Cc: Mark Rutland; Yuanzhichang; catalin.marinas@arm.com;
> will.deacon@arm.com; robh+dt@kernel.org; bhelgaas@google.com;
> olof@lixom.net; linux-arm-kernel@lists.infradead.org;
> lorenzo.pieralisi@arm.com; linux-kernel@vger.kernel.org; Linuxarm;
> devicetree@vger.kernel.org; linux-pci@vger.kernel.org; linux-
> serial@vger.kernel.org; minyard@acm.org; benh@kernel.crashing.org;
> liviu.dudau@arm.com; zourongrong@gmail.com; John Garry; Gabriele
> Paoloni; zhichang.yuan02@gmail.com; kantyzc@163.com; xuwei (O);
> marc.zyngier@arm.com
> Subject: Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for
> special ISA
> 
> > I think it is a relatively safe assumption that there is only one
> > ISA bridge. A lot of old drivers hardcode PIO or memory addresses
> 
> It's not a safe assumption for x86 at least. There are a few systems
> with
> multiple ISA busses particularly older laptops with a docking station.

Mmmm right...now the point is that this kind of special devices appearing
as a special ISA bus will probably never appear on x86 platforms (I guess).

So maybe it is a safe assumption because of this...?

Thanks

Gab

> 
> > when talking to an ISA device, so having multiple instances is
> > already problematic.
> 
> PCMCIA devices handle it themselves so are ok. I'm not clear how the
> dual
> PIIX4 configuration used in the older IBM laptop docks actually worked
> so
> I assume the transaction went out of both bridges and providing one of
> them responded the other kept silent as you simply stuffed the card
> into
> the dock and it worked.
> 
> Alan

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

* RE: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-09 14:51           ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-09 14:51 UTC (permalink / raw)
  To: One Thousand Gnomes, Arnd Bergmann
  Cc: Mark Rutland, Yuanzhichang, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, olof-nZhT3qVonbNeoWH0uzbU5w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	lorenzo.pieralisi-5wv7dgnIgG8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Linuxarm,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, minyard-HInyCGIudOg,
	benh-XVmvHMARGAQRh2imMr4xaA

> -----Original Message-----
> From: One Thousand Gnomes [mailto:gnomes-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org]
> Sent: 09 November 2016 13:55
> To: Arnd Bergmann
> Cc: Mark Rutland; Yuanzhichang; catalin.marinas-5wv7dgnIgG8@public.gmane.org;
> will.deacon-5wv7dgnIgG8@public.gmane.org; robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org; bhelgaas-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org;
> olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org; linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org;
> lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org; linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; Linuxarm;
> devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux-
> serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; minyard-HInyCGIudOg@public.gmane.org; benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org;
> liviu.dudau-5wv7dgnIgG8@public.gmane.org; zourongrong-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org; John Garry; Gabriele
> Paoloni; zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org; kantyzc-9Onoh4P/yGk@public.gmane.org; xuwei (O);
> marc.zyngier-5wv7dgnIgG8@public.gmane.org
> Subject: Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for
> special ISA
> 
> > I think it is a relatively safe assumption that there is only one
> > ISA bridge. A lot of old drivers hardcode PIO or memory addresses
> 
> It's not a safe assumption for x86 at least. There are a few systems
> with
> multiple ISA busses particularly older laptops with a docking station.

Mmmm right...now the point is that this kind of special devices appearing
as a special ISA bus will probably never appear on x86 platforms (I guess).

So maybe it is a safe assumption because of this...?

Thanks

Gab

> 
> > when talking to an ISA device, so having multiple instances is
> > already problematic.
> 
> PCMCIA devices handle it themselves so are ok. I'm not clear how the
> dual
> PIIX4 configuration used in the older IBM laptop docks actually worked
> so
> I assume the transaction went out of both bridges and providing one of
> them responded the other kept silent as you simply stuffed the card
> into
> the dock and it worked.
> 
> Alan
--
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] 286+ messages in thread

* RE: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-09 14:51           ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-09 14:51 UTC (permalink / raw)
  To: One Thousand Gnomes, Arnd Bergmann
  Cc: Mark Rutland, Yuanzhichang, catalin.marinas, will.deacon,
	robh+dt, bhelgaas, olof, linux-arm-kernel, lorenzo.pieralisi,
	linux-kernel, Linuxarm, devicetree, linux-pci, linux-serial,
	minyard, benh, liviu.dudau, zourongrong, John Garry,
	zhichang.yuan02, kantyzc, xuwei (O),
	marc.zyngier

> -----Original Message-----
> From: One Thousand Gnomes [mailto:gnomes@lxorguk.ukuu.org.uk]
> Sent: 09 November 2016 13:55
> To: Arnd Bergmann
> Cc: Mark Rutland; Yuanzhichang; catalin.marinas@arm.com;
> will.deacon@arm.com; robh+dt@kernel.org; bhelgaas@google.com;
> olof@lixom.net; linux-arm-kernel@lists.infradead.org;
> lorenzo.pieralisi@arm.com; linux-kernel@vger.kernel.org; Linuxarm;
> devicetree@vger.kernel.org; linux-pci@vger.kernel.org; linux-
> serial@vger.kernel.org; minyard@acm.org; benh@kernel.crashing.org;
> liviu.dudau@arm.com; zourongrong@gmail.com; John Garry; Gabriele
> Paoloni; zhichang.yuan02@gmail.com; kantyzc@163.com; xuwei (O);
> marc.zyngier@arm.com
> Subject: Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for
> special ISA
> 
> > I think it is a relatively safe assumption that there is only one
> > ISA bridge. A lot of old drivers hardcode PIO or memory addresses
> 
> It's not a safe assumption for x86 at least. There are a few systems
> with
> multiple ISA busses particularly older laptops with a docking station.

Mmmm right...now the point is that this kind of special devices appearing
as a special ISA bus will probably never appear on x86 platforms (I guess).

So maybe it is a safe assumption because of this...?

Thanks

Gab

> 
> > when talking to an ISA device, so having multiple instances is
> > already problematic.
> 
> PCMCIA devices handle it themselves so are ok. I'm not clear how the
> dual
> PIIX4 configuration used in the older IBM laptop docks actually worked
> so
> I assume the transaction went out of both bridges and providing one of
> them responded the other kept silent as you simply stuffed the card
> into
> the dock and it worked.
> 
> Alan

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

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-09 14:51           ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-09 14:51 UTC (permalink / raw)
  To: linux-arm-kernel

> -----Original Message-----
> From: One Thousand Gnomes [mailto:gnomes at lxorguk.ukuu.org.uk]
> Sent: 09 November 2016 13:55
> To: Arnd Bergmann
> Cc: Mark Rutland; Yuanzhichang; catalin.marinas at arm.com;
> will.deacon at arm.com; robh+dt at kernel.org; bhelgaas at google.com;
> olof at lixom.net; linux-arm-kernel at lists.infradead.org;
> lorenzo.pieralisi at arm.com; linux-kernel at vger.kernel.org; Linuxarm;
> devicetree at vger.kernel.org; linux-pci at vger.kernel.org; linux-
> serial at vger.kernel.org; minyard at acm.org; benh at kernel.crashing.org;
> liviu.dudau at arm.com; zourongrong at gmail.com; John Garry; Gabriele
> Paoloni; zhichang.yuan02 at gmail.com; kantyzc at 163.com; xuwei (O);
> marc.zyngier at arm.com
> Subject: Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for
> special ISA
> 
> > I think it is a relatively safe assumption that there is only one
> > ISA bridge. A lot of old drivers hardcode PIO or memory addresses
> 
> It's not a safe assumption for x86 at least. There are a few systems
> with
> multiple ISA busses particularly older laptops with a docking station.

Mmmm right...now the point is that this kind of special devices appearing
as a special ISA bus will probably never appear on x86 platforms (I guess).

So maybe it is a safe assumption because of this...?

Thanks

Gab

> 
> > when talking to an ISA device, so having multiple instances is
> > already problematic.
> 
> PCMCIA devices handle it themselves so are ok. I'm not clear how the
> dual
> PIIX4 configuration used in the older IBM laptop docks actually worked
> so
> I assume the transaction went out of both bridges and providing one of
> them responded the other kept silent as you simply stuffed the card
> into
> the dock and it worked.
> 
> Alan

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

* RE: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
  2016-11-09 11:39     ` liviu.dudau-5wv7dgnIgG8
  (?)
  (?)
@ 2016-11-09 16:16       ` Gabriele Paoloni
  -1 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-09 16:16 UTC (permalink / raw)
  To: liviu.dudau, Yuanzhichang
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, mark.rutland,
	olof, arnd, linux-arm-kernel, lorenzo.pieralisi, linux-kernel,
	Linuxarm, devicetree, linux-pci, linux-serial, minyard, benh,
	zourongrong, John Garry, zhichang.yuan02, kantyzc, xuwei (O)

Hi Liviu

Thanks for reviewing

> -----Original Message-----
> From: liviu.dudau@arm.com [mailto:liviu.dudau@arm.com]
> Sent: 09 November 2016 11:40
> To: Yuanzhichang
> Cc: catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> bhelgaas@google.com; mark.rutland@arm.com; olof@lixom.net;
> arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> lorenzo.pieralisi@arm.com; linux-kernel@vger.kernel.org; Linuxarm;
> devicetree@vger.kernel.org; linux-pci@vger.kernel.org; linux-
> serial@vger.kernel.org; minyard@acm.org; benh@kernel.crashing.org;
> zourongrong@gmail.com; John Garry; Gabriele Paoloni;
> zhichang.yuan02@gmail.com; kantyzc@163.com; xuwei (O)
> Subject: Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for
> special ISA
> 
> On Tue, Nov 08, 2016 at 11:47:08AM +0800, zhichang.yuan wrote:
> > This patch solves two issues:
> > 1) parse and get the right I/O range from DTS node whose parent does
> not
> > define the corresponding ranges property;
> >
> > 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 a fixup function, of_get_isa_indirect_io(). During the OF
> address
> > translation, this fixup will be called to check the 'reg' address to
> be
> > translating is for those sepcial ISA/LPC devices and get the I/O
> range
> > directly from the 'reg' property.
> >
> > 2) eliminate the I/O range conflict risk with PCI/PCIE leagecy I/O
> device;
> >
> > The current __of_address_to_resource() always translates the I/O
> range to PIO.
> > But this processing is not suitable for our ISA/LPC devices whose I/O
> range is
> > not cpu address(Arnd had stressed this in his comments on V2,V3
> patch-set).
> > Here, we bypass the mapping between cpu address and PIO for the
> special
> > ISA/LPC devices. But to drive these ISA/LPC devices, a I/O port
> address below
> > PCIBIOS_MIN_IO is needed by in*/out*(). Which means there is conflict
> risk
> > between I/O range of [0, PCIBIOS_MIN_IO) and PCI/PCIE legacy I/O
> range of [0,
> > IO_SPACE_LIMIT).
> > To avoid the I/O conflict, this patch reserve the I/O range below
> > PCIBIOS_MIN_IO.
> >
> > Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > ---
> >  .../arm/hisilicon/hisilicon-low-pin-count.txt      | 31 ++++++++++++
> >  arch/arm64/include/asm/io.h                        |  6 +++
> >  arch/arm64/kernel/extio.c                          | 25 ++++++++++
> >  drivers/of/address.c                               | 56
> +++++++++++++++++++++-
> >  drivers/pci/pci.c                                  |  6 +--
> >  include/linux/of_address.h                         | 17 +++++++
> >  include/linux/pci.h                                |  8 ++++
> >  7 files changed, 145 insertions(+), 4 deletions(-)
> >  create mode 100644
> Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-
> count.txt
> >
> > diff --git
> a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-
> count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-
> low-pin-count.txt
> > new file mode 100644
> > index 0000000..13c8ddd
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-
> pin-count.txt
> > @@ -0,0 +1,31 @@
> > +Hisilicon Hip06 low-pin-count device
> > +  Usually LPC controller is part of PCI host bridge, so the legacy
> ISA ports
> > +  locate on LPC bus can be accessed direclty. But some SoCs have
> independent
> > +  LPC controller, and access the legacy ports by triggering LPC I/O
> cycles.
> > +  Hisilicon Hip06 implements this LPC device.
> > +
> > +Required properties:
> > +- compatible: should be "hisilicon,low-pin-count"
> > +- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
> > +- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
> > +- reg: base memory range where the register set of this device is
> mapped.
> > +
> > +Note:
> > +  The node name before '@' must be "isa" to represent the binding
> stick to the
> > +  ISA/EISA binding specification.
> > +
> > +Example:
> > +
> > +isa@a01b0000 {
> > +	compatible = "hisilicom,low-pin-count";
> > +	#address-cells = <2>;
> > +	#size-cells = <1>;
> > +	reg = <0x0 0xa01b0000 0x0 0x1000>;
> > +
> > +	ipmi0: bt@e4 {
> > +		compatible = "ipmi-bt";
> > +		device_type = "ipmi";
> > +		reg = <0x01 0xe4 0x04>;
> > +		status = "disabled";
> > +	};
> > +};
> 
> 
> This documentation file needs to be part of the next patch. It has
> nothing to do with
> what you are trying to fix here.

Yes you're right...we'll move it to next one

> 
> 
> > diff --git a/arch/arm64/include/asm/io.h
> b/arch/arm64/include/asm/io.h
> > index 136735d..c26b7cc 100644
> > --- a/arch/arm64/include/asm/io.h
> > +++ b/arch/arm64/include/asm/io.h
> > @@ -175,6 +175,12 @@ static inline u64 __raw_readq(const volatile
> void __iomem *addr)
> >  #define outsl outsl
> >
> >  DECLARE_EXTIO(l, u32)
> > +
> > +#define indirect_io_enabled indirect_io_enabled
> > +extern bool indirect_io_enabled(void);
> > +
> > +#define addr_is_indirect_io addr_is_indirect_io
> > +extern int addr_is_indirect_io(u64 taddr);
> >  #endif
> >
> >
> > diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> > index 647b3fa..3d45fa8 100644
> > --- a/arch/arm64/kernel/extio.c
> > +++ b/arch/arm64/kernel/extio.c
> > @@ -19,6 +19,31 @@
> >
> >  struct extio_ops *arm64_extio_ops;
> >
> > +/**
> > + * indirect_io_enabled - check whether indirectIO is enabled.
> > + *	arm64_extio_ops will be set only when indirectIO mechanism had
> been
> > + *	initialized.
> > + *
> > + * Returns true when indirectIO is enabled.
> > + */
> > +bool indirect_io_enabled(void)
> > +{
> > +	return arm64_extio_ops ? true : false;
> > +}
> > +
> > +/**
> > + * addr_is_indirect_io - check whether the input taddr is for
> indirectIO.
> > + * @taddr: the io address to be checked.
> > + *
> > + * Returns 1 when taddr is in the range; otherwise return 0.
> > + */
> > +int addr_is_indirect_io(u64 taddr)
> > +{
> > +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end <
> taddr)
> 
> start >= taddr ?

Nope... if  (taddr < arm64_extio_ops->start || taddr > arm64_extio_ops->end)
then taddr is outside the range [start; end] and will return 0; otherwise
it will return 1...

> 
> > +		return 0;
> > +
> > +	return 1;
> > +}
> >
> >  BUILD_EXTIO(b, u8)
> >
> > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > index 02b2903..cc2a05d 100644
> > --- a/drivers/of/address.c
> > +++ b/drivers/of/address.c
> > @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
> device_node *np)
> >  	return false;
> >  }
> >
> > +
> > +/*
> > + * of_isa_indirect_io - get the IO address from some isa reg
> property value.
> > + *	For some isa/lpc devices, no ranges property in ancestor node.
> > + *	The device addresses are described directly in their regs
> property.
> > + *	This fixup function will be called to get the IO address of
> isa/lpc
> > + *	devices when the normal of_translation failed.
> > + *
> > + * @parent:	points to the parent dts node;
> > + * @bus:		points to the of_bus which can be used to parse
> address;
> > + * @addr:	the address from reg property;
> > + * @na:		the address cell counter of @addr;
> > + * @presult:	store the address paresed from @addr;
> > + *
> > + * return 1 when successfully get the I/O address;
> > + * 0 will return for some failures.
> 
> Bah, you are returning a signed int, why 0 for failure? Return a
> negative value with
> error codes. Otherwise change the return value into a bool.

Yes we'll move to bool

> 
> > + */
> > +static int of_get_isa_indirect_io(struct device_node *parent,
> > +				struct of_bus *bus, __be32 *addr,
> > +				int na, u64 *presult)
> > +{
> > +	unsigned int flags;
> > +	unsigned int rlen;
> > +
> > +	/* whether support indirectIO */
> > +	if (!indirect_io_enabled())
> > +		return 0;
> > +
> > +	if (!of_bus_isa_match(parent))
> > +		return 0;
> > +
> > +	flags = bus->get_flags(addr);
> > +	if (!(flags & IORESOURCE_IO))
> > +		return 0;
> > +
> > +	/* there is ranges property, apply the normal translation
> directly. */
> 
> s/there is ranges/if we have a 'ranges'/

Thanks for spotting this

> 
> > +	if (of_get_property(parent, "ranges", &rlen))
> > +		return 0;
> > +
> > +	*presult = of_read_number(addr + 1, na - 1);
> > +	/* this fixup is only valid for specific I/O range. */
> > +	return addr_is_indirect_io(*presult);
> > +}
> > +
> >  static int of_translate_one(struct device_node *parent, struct
> of_bus *bus,
> >  			    struct of_bus *pbus, __be32 *addr,
> >  			    int na, int ns, int pna, const char *rprop)
> > @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
> device_node *dev,
> >  			result = of_read_number(addr, na);
> >  			break;
> >  		}
> > +		/*
> > +		 * For indirectIO device which has no ranges property, get
> > +		 * the address from reg directly.
> > +		 */
> > +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> > +			pr_debug("isa indirectIO matched(%s)..addr =
> 0x%llx\n",
> > +				of_node_full_name(dev), result);
> > +			break;
> > +		}
> >
> >  		/* Get new parent bus and counts */
> >  		pbus = of_match_bus(parent);
> > @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
> device_node *dev,
> >  	if (taddr == OF_BAD_ADDR)
> >  		return -EINVAL;
> >  	memset(r, 0, sizeof(struct resource));
> > -	if (flags & IORESOURCE_IO) {
> > +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
> >  		unsigned long port;
> > +
> >  		port = pci_address_to_pio(taddr);
> >  		if (port == (unsigned long)-1)
> >  			return -EINVAL;
> > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > index ba34907..1a08511 100644
> > --- a/drivers/pci/pci.c
> > +++ b/drivers/pci/pci.c
> > @@ -3263,7 +3263,7 @@ 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;
> > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> >
> >  	/* check if the range hasn't been previously recorded */
> >  	spin_lock(&io_range_lock);
> > @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long
> pio)
> >
> >  #ifdef PCI_IOBASE
> >  	struct io_range *range;
> > -	resource_size_t allocated_size = 0;
> > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> 
> Have you checked that pci_pio_to_address still returns valid values
> after this? I know that
> you are trying to take into account PCIBIOS_MIN_IO limit when
> allocating reserving the IO ranges,
> but the values added in the io_range_list are still starting from zero,
> no from PCIBIOS_MIN_IO,

I think you're wrong here as in pci_address_to_pio we have:
+	resource_size_t offset = PCIBIOS_MIN_IO;

This should be enough to guarantee that the PIOs start at
PCIBIOS_MIN_IO...right?


> so the calculation of the address in this function could return
> negative values casted to pci_addr_t.
> 
> Maybe you want to adjust the range->start value in
> pci_register_io_range() as well to have it
> offset by PCIBIOS_MIN_IO as well.
> 
> Best regards,
> Liviu
> 
> >
> >  	if (pio > IO_SPACE_LIMIT)
> >  		return address;
> > @@ -3335,7 +3335,7 @@ unsigned long __weak
> pci_address_to_pio(phys_addr_t address)
> >  {
> >  #ifdef PCI_IOBASE
> >  	struct io_range *res;
> > -	resource_size_t offset = 0;
> > +	resource_size_t offset = PCIBIOS_MIN_IO;
> >  	unsigned long addr = -1;
> >
> >  	spin_lock(&io_range_lock);
> > diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> > index 3786473..deec469 100644
> > --- a/include/linux/of_address.h
> > +++ b/include/linux/of_address.h
> > @@ -24,6 +24,23 @@ struct of_pci_range {
> >  #define for_each_of_pci_range(parser, range) \
> >  	for (; of_pci_range_parser_one(parser, range);)
> >
> > +
> > +#ifndef indirect_io_enabled
> > +#define indirect_io_enabled indirect_io_enabled
> > +static inline bool indirect_io_enabled(void)
> > +{
> > +	return false;
> > +}
> > +#endif
> > +
> > +#ifndef addr_is_indirect_io
> > +#define addr_is_indirect_io addr_is_indirect_io
> > +static inline int addr_is_indirect_io(u64 taddr)
> > +{
> > +	return 0;
> > +}
> > +#endif
> > +
> >  /* Translate a DMA address from device space to CPU space */
> >  extern u64 of_translate_dma_address(struct device_node *dev,
> >  				    const __be32 *in_addr);
> > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > index 0e49f70..7f6bbb6 100644
> > --- a/include/linux/pci.h
> > +++ b/include/linux/pci.h
> > @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
> pci_bus *bus)
> >  /* provide the legacy pci_dma_* API */
> >  #include <linux/pci-dma-compat.h>
> >
> > +/*
> > + * define this macro here to refrain from compilation error for some
> > + * platforms. Please keep this macro at the end of this header file.
> > + */
> > +#ifndef PCIBIOS_MIN_IO
> > +#define PCIBIOS_MIN_IO		0
> > +#endif
> > +
> >  #endif /* LINUX_PCI_H */
> > --
> > 1.9.1
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-pci"
> in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> --
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ¯\_(ツ)_/¯

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

* RE: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-09 16:16       ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-09 16:16 UTC (permalink / raw)
  To: liviu.dudau, Yuanzhichang
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, mark.rutland,
	olof, arnd, linux-arm-kernel, lorenzo.pieralisi, linux-kernel,
	Linuxarm, devicetree, linux-pci, linux-serial, minyard, benh

Hi Liviu

Thanks for reviewing

> -----Original Message-----
> From: liviu.dudau@arm.com [mailto:liviu.dudau@arm.com]
> Sent: 09 November 2016 11:40
> To: Yuanzhichang
> Cc: catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org;
> bhelgaas@google.com; mark.rutland@arm.com; olof@lixom.net;
> arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> lorenzo.pieralisi@arm.com; linux-kernel@vger.kernel.org; Linuxarm;
> devicetree@vger.kernel.org; linux-pci@vger.kernel.org; linux-
> serial@vger.kernel.org; minyard@acm.org; benh@kernel.crashing.org;
> zourongrong@gmail.com; John Garry; Gabriele Paoloni;
> zhichang.yuan02@gmail.com; kantyzc@163.com; xuwei (O)
> Subject: Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for
> special ISA
> 
> On Tue, Nov 08, 2016 at 11:47:08AM +0800, zhichang.yuan wrote:
> > This patch solves two issues:
> > 1) parse and get the right I/O range from DTS node whose parent does
> not
> > define the corresponding ranges property;
> >
> > 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 a fixup function, of_get_isa_indirect_io(). During the OF
> address
> > translation, this fixup will be called to check the 'reg' address to
> be
> > translating is for those sepcial ISA/LPC devices and get the I/O
> range
> > directly from the 'reg' property.
> >
> > 2) eliminate the I/O range conflict risk with PCI/PCIE leagecy I/O
> device;
> >
> > The current __of_address_to_resource() always translates the I/O
> range to PIO.
> > But this processing is not suitable for our ISA/LPC devices whose I/O
> range is
> > not cpu address(Arnd had stressed this in his comments on V2,V3
> patch-set).
> > Here, we bypass the mapping between cpu address and PIO for the
> special
> > ISA/LPC devices. But to drive these ISA/LPC devices, a I/O port
> address below
> > PCIBIOS_MIN_IO is needed by in*/out*(). Which means there is conflict
> risk
> > between I/O range of [0, PCIBIOS_MIN_IO) and PCI/PCIE legacy I/O
> range of [0,
> > IO_SPACE_LIMIT).
> > To avoid the I/O conflict, this patch reserve the I/O range below
> > PCIBIOS_MIN_IO.
> >
> > Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > ---
> >  .../arm/hisilicon/hisilicon-low-pin-count.txt      | 31 ++++++++++++
> >  arch/arm64/include/asm/io.h                        |  6 +++
> >  arch/arm64/kernel/extio.c                          | 25 ++++++++++
> >  drivers/of/address.c                               | 56
> +++++++++++++++++++++-
> >  drivers/pci/pci.c                                  |  6 +--
> >  include/linux/of_address.h                         | 17 +++++++
> >  include/linux/pci.h                                |  8 ++++
> >  7 files changed, 145 insertions(+), 4 deletions(-)
> >  create mode 100644
> Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-
> count.txt
> >
> > diff --git
> a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-
> count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-
> low-pin-count.txt
> > new file mode 100644
> > index 0000000..13c8ddd
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-
> pin-count.txt
> > @@ -0,0 +1,31 @@
> > +Hisilicon Hip06 low-pin-count device
> > +  Usually LPC controller is part of PCI host bridge, so the legacy
> ISA ports
> > +  locate on LPC bus can be accessed direclty. But some SoCs have
> independent
> > +  LPC controller, and access the legacy ports by triggering LPC I/O
> cycles.
> > +  Hisilicon Hip06 implements this LPC device.
> > +
> > +Required properties:
> > +- compatible: should be "hisilicon,low-pin-count"
> > +- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
> > +- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
> > +- reg: base memory range where the register set of this device is
> mapped.
> > +
> > +Note:
> > +  The node name before '@' must be "isa" to represent the binding
> stick to the
> > +  ISA/EISA binding specification.
> > +
> > +Example:
> > +
> > +isa@a01b0000 {
> > +	compatible = "hisilicom,low-pin-count";
> > +	#address-cells = <2>;
> > +	#size-cells = <1>;
> > +	reg = <0x0 0xa01b0000 0x0 0x1000>;
> > +
> > +	ipmi0: bt@e4 {
> > +		compatible = "ipmi-bt";
> > +		device_type = "ipmi";
> > +		reg = <0x01 0xe4 0x04>;
> > +		status = "disabled";
> > +	};
> > +};
> 
> 
> This documentation file needs to be part of the next patch. It has
> nothing to do with
> what you are trying to fix here.

Yes you're right...we'll move it to next one

> 
> 
> > diff --git a/arch/arm64/include/asm/io.h
> b/arch/arm64/include/asm/io.h
> > index 136735d..c26b7cc 100644
> > --- a/arch/arm64/include/asm/io.h
> > +++ b/arch/arm64/include/asm/io.h
> > @@ -175,6 +175,12 @@ static inline u64 __raw_readq(const volatile
> void __iomem *addr)
> >  #define outsl outsl
> >
> >  DECLARE_EXTIO(l, u32)
> > +
> > +#define indirect_io_enabled indirect_io_enabled
> > +extern bool indirect_io_enabled(void);
> > +
> > +#define addr_is_indirect_io addr_is_indirect_io
> > +extern int addr_is_indirect_io(u64 taddr);
> >  #endif
> >
> >
> > diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> > index 647b3fa..3d45fa8 100644
> > --- a/arch/arm64/kernel/extio.c
> > +++ b/arch/arm64/kernel/extio.c
> > @@ -19,6 +19,31 @@
> >
> >  struct extio_ops *arm64_extio_ops;
> >
> > +/**
> > + * indirect_io_enabled - check whether indirectIO is enabled.
> > + *	arm64_extio_ops will be set only when indirectIO mechanism had
> been
> > + *	initialized.
> > + *
> > + * Returns true when indirectIO is enabled.
> > + */
> > +bool indirect_io_enabled(void)
> > +{
> > +	return arm64_extio_ops ? true : false;
> > +}
> > +
> > +/**
> > + * addr_is_indirect_io - check whether the input taddr is for
> indirectIO.
> > + * @taddr: the io address to be checked.
> > + *
> > + * Returns 1 when taddr is in the range; otherwise return 0.
> > + */
> > +int addr_is_indirect_io(u64 taddr)
> > +{
> > +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end <
> taddr)
> 
> start >= taddr ?

Nope... if  (taddr < arm64_extio_ops->start || taddr > arm64_extio_ops->end)
then taddr is outside the range [start; end] and will return 0; otherwise
it will return 1...

> 
> > +		return 0;
> > +
> > +	return 1;
> > +}
> >
> >  BUILD_EXTIO(b, u8)
> >
> > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > index 02b2903..cc2a05d 100644
> > --- a/drivers/of/address.c
> > +++ b/drivers/of/address.c
> > @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
> device_node *np)
> >  	return false;
> >  }
> >
> > +
> > +/*
> > + * of_isa_indirect_io - get the IO address from some isa reg
> property value.
> > + *	For some isa/lpc devices, no ranges property in ancestor node.
> > + *	The device addresses are described directly in their regs
> property.
> > + *	This fixup function will be called to get the IO address of
> isa/lpc
> > + *	devices when the normal of_translation failed.
> > + *
> > + * @parent:	points to the parent dts node;
> > + * @bus:		points to the of_bus which can be used to parse
> address;
> > + * @addr:	the address from reg property;
> > + * @na:		the address cell counter of @addr;
> > + * @presult:	store the address paresed from @addr;
> > + *
> > + * return 1 when successfully get the I/O address;
> > + * 0 will return for some failures.
> 
> Bah, you are returning a signed int, why 0 for failure? Return a
> negative value with
> error codes. Otherwise change the return value into a bool.

Yes we'll move to bool

> 
> > + */
> > +static int of_get_isa_indirect_io(struct device_node *parent,
> > +				struct of_bus *bus, __be32 *addr,
> > +				int na, u64 *presult)
> > +{
> > +	unsigned int flags;
> > +	unsigned int rlen;
> > +
> > +	/* whether support indirectIO */
> > +	if (!indirect_io_enabled())
> > +		return 0;
> > +
> > +	if (!of_bus_isa_match(parent))
> > +		return 0;
> > +
> > +	flags = bus->get_flags(addr);
> > +	if (!(flags & IORESOURCE_IO))
> > +		return 0;
> > +
> > +	/* there is ranges property, apply the normal translation
> directly. */
> 
> s/there is ranges/if we have a 'ranges'/

Thanks for spotting this

> 
> > +	if (of_get_property(parent, "ranges", &rlen))
> > +		return 0;
> > +
> > +	*presult = of_read_number(addr + 1, na - 1);
> > +	/* this fixup is only valid for specific I/O range. */
> > +	return addr_is_indirect_io(*presult);
> > +}
> > +
> >  static int of_translate_one(struct device_node *parent, struct
> of_bus *bus,
> >  			    struct of_bus *pbus, __be32 *addr,
> >  			    int na, int ns, int pna, const char *rprop)
> > @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
> device_node *dev,
> >  			result = of_read_number(addr, na);
> >  			break;
> >  		}
> > +		/*
> > +		 * For indirectIO device which has no ranges property, get
> > +		 * the address from reg directly.
> > +		 */
> > +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> > +			pr_debug("isa indirectIO matched(%s)..addr =
> 0x%llx\n",
> > +				of_node_full_name(dev), result);
> > +			break;
> > +		}
> >
> >  		/* Get new parent bus and counts */
> >  		pbus = of_match_bus(parent);
> > @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
> device_node *dev,
> >  	if (taddr == OF_BAD_ADDR)
> >  		return -EINVAL;
> >  	memset(r, 0, sizeof(struct resource));
> > -	if (flags & IORESOURCE_IO) {
> > +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
> >  		unsigned long port;
> > +
> >  		port = pci_address_to_pio(taddr);
> >  		if (port == (unsigned long)-1)
> >  			return -EINVAL;
> > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > index ba34907..1a08511 100644
> > --- a/drivers/pci/pci.c
> > +++ b/drivers/pci/pci.c
> > @@ -3263,7 +3263,7 @@ 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;
> > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> >
> >  	/* check if the range hasn't been previously recorded */
> >  	spin_lock(&io_range_lock);
> > @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long
> pio)
> >
> >  #ifdef PCI_IOBASE
> >  	struct io_range *range;
> > -	resource_size_t allocated_size = 0;
> > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> 
> Have you checked that pci_pio_to_address still returns valid values
> after this? I know that
> you are trying to take into account PCIBIOS_MIN_IO limit when
> allocating reserving the IO ranges,
> but the values added in the io_range_list are still starting from zero,
> no from PCIBIOS_MIN_IO,

I think you're wrong here as in pci_address_to_pio we have:
+	resource_size_t offset = PCIBIOS_MIN_IO;

This should be enough to guarantee that the PIOs start at
PCIBIOS_MIN_IO...right?


> so the calculation of the address in this function could return
> negative values casted to pci_addr_t.
> 
> Maybe you want to adjust the range->start value in
> pci_register_io_range() as well to have it
> offset by PCIBIOS_MIN_IO as well.
> 
> Best regards,
> Liviu
> 
> >
> >  	if (pio > IO_SPACE_LIMIT)
> >  		return address;
> > @@ -3335,7 +3335,7 @@ unsigned long __weak
> pci_address_to_pio(phys_addr_t address)
> >  {
> >  #ifdef PCI_IOBASE
> >  	struct io_range *res;
> > -	resource_size_t offset = 0;
> > +	resource_size_t offset = PCIBIOS_MIN_IO;
> >  	unsigned long addr = -1;
> >
> >  	spin_lock(&io_range_lock);
> > diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> > index 3786473..deec469 100644
> > --- a/include/linux/of_address.h
> > +++ b/include/linux/of_address.h
> > @@ -24,6 +24,23 @@ struct of_pci_range {
> >  #define for_each_of_pci_range(parser, range) \
> >  	for (; of_pci_range_parser_one(parser, range);)
> >
> > +
> > +#ifndef indirect_io_enabled
> > +#define indirect_io_enabled indirect_io_enabled
> > +static inline bool indirect_io_enabled(void)
> > +{
> > +	return false;
> > +}
> > +#endif
> > +
> > +#ifndef addr_is_indirect_io
> > +#define addr_is_indirect_io addr_is_indirect_io
> > +static inline int addr_is_indirect_io(u64 taddr)
> > +{
> > +	return 0;
> > +}
> > +#endif
> > +
> >  /* Translate a DMA address from device space to CPU space */
> >  extern u64 of_translate_dma_address(struct device_node *dev,
> >  				    const __be32 *in_addr);
> > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > index 0e49f70..7f6bbb6 100644
> > --- a/include/linux/pci.h
> > +++ b/include/linux/pci.h
> > @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
> pci_bus *bus)
> >  /* provide the legacy pci_dma_* API */
> >  #include <linux/pci-dma-compat.h>
> >
> > +/*
> > + * define this macro here to refrain from compilation error for some
> > + * platforms. Please keep this macro at the end of this header file.
> > + */
> > +#ifndef PCIBIOS_MIN_IO
> > +#define PCIBIOS_MIN_IO		0
> > +#endif
> > +
> >  #endif /* LINUX_PCI_H */
> > --
> > 1.9.1
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-pci"
> in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> --
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ¯\_(ツ)_/¯

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

* RE: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-09 16:16       ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-09 16:16 UTC (permalink / raw)
  To: liviu.dudau, Yuanzhichang
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, mark.rutland,
	olof, arnd, linux-arm-kernel, lorenzo.pieralisi, linux-kernel,
	Linuxarm, devicetree, linux-pci, linux-serial, minyard, benh,
	zourongrong, John Garry, zhichang.yuan02, kantyzc, xuwei (O)

SGkgTGl2aXUNCg0KVGhhbmtzIGZvciByZXZpZXdpbmcNCg0KPiAtLS0tLU9yaWdpbmFsIE1lc3Nh
Z2UtLS0tLQ0KPiBGcm9tOiBsaXZpdS5kdWRhdUBhcm0uY29tIFttYWlsdG86bGl2aXUuZHVkYXVA
YXJtLmNvbV0NCj4gU2VudDogMDkgTm92ZW1iZXIgMjAxNiAxMTo0MA0KPiBUbzogWXVhbnpoaWNo
YW5nDQo+IENjOiBjYXRhbGluLm1hcmluYXNAYXJtLmNvbTsgd2lsbC5kZWFjb25AYXJtLmNvbTsg
cm9iaCtkdEBrZXJuZWwub3JnOw0KPiBiaGVsZ2Fhc0Bnb29nbGUuY29tOyBtYXJrLnJ1dGxhbmRA
YXJtLmNvbTsgb2xvZkBsaXhvbS5uZXQ7DQo+IGFybmRAYXJuZGIuZGU7IGxpbnV4LWFybS1rZXJu
ZWxAbGlzdHMuaW5mcmFkZWFkLm9yZzsNCj4gbG9yZW56by5waWVyYWxpc2lAYXJtLmNvbTsgbGlu
dXgta2VybmVsQHZnZXIua2VybmVsLm9yZzsgTGludXhhcm07DQo+IGRldmljZXRyZWVAdmdlci5r
ZXJuZWwub3JnOyBsaW51eC1wY2lAdmdlci5rZXJuZWwub3JnOyBsaW51eC0NCj4gc2VyaWFsQHZn
ZXIua2VybmVsLm9yZzsgbWlueWFyZEBhY20ub3JnOyBiZW5oQGtlcm5lbC5jcmFzaGluZy5vcmc7
DQo+IHpvdXJvbmdyb25nQGdtYWlsLmNvbTsgSm9obiBHYXJyeTsgR2FicmllbGUgUGFvbG9uaTsN
Cj4gemhpY2hhbmcueXVhbjAyQGdtYWlsLmNvbTsga2FudHl6Y0AxNjMuY29tOyB4dXdlaSAoTykN
Cj4gU3ViamVjdDogUmU6IFtQQVRDSCBWNSAyLzNdIEFSTTY0IExQQzogQWRkIG1pc3NpbmcgcmFu
Z2UgZXhjZXB0aW9uIGZvcg0KPiBzcGVjaWFsIElTQQ0KPiANCj4gT24gVHVlLCBOb3YgMDgsIDIw
MTYgYXQgMTE6NDc6MDhBTSArMDgwMCwgemhpY2hhbmcueXVhbiB3cm90ZToNCj4gPiBUaGlzIHBh
dGNoIHNvbHZlcyB0d28gaXNzdWVzOg0KPiA+IDEpIHBhcnNlIGFuZCBnZXQgdGhlIHJpZ2h0IEkv
TyByYW5nZSBmcm9tIERUUyBub2RlIHdob3NlIHBhcmVudCBkb2VzDQo+IG5vdA0KPiA+IGRlZmlu
ZSB0aGUgY29ycmVzcG9uZGluZyByYW5nZXMgcHJvcGVydHk7DQo+ID4NCj4gPiBUaGVyZSBhcmUg
c29tZSBzcGVjaWFsIElTQS9MUEMgZGV2aWNlcyB0aGF0IHdvcmsgb24gYSBzcGVjaWZpYyBJL08N
Cj4gcmFuZ2Ugd2hlcmUNCj4gPiBpdCBpcyBub3QgY29ycmVjdCB0byBzcGVjaWZ5IGEgcmFuZ2Vz
IHByb3BlcnR5IGluIERUUyBwYXJlbnQgbm9kZSBhcw0KPiBjcHUNCj4gPiBhZGRyZXNzZXMgdHJh
bnNsYXRlZCBmcm9tIERUUyBub2RlIGFyZSBvbmx5IGZvciBtZW1vcnkgc3BhY2Ugb24gc29tZQ0K
PiA+IGFyY2hpdGVjdHVyZXMsIHN1Y2ggYXMgQXJtNjQuIFdpdGhvdXQgdGhlIHBhcmVudCAncmFu
Z2VzJyBwcm9wZXJ0eSwNCj4gY3VycmVudA0KPiA+IG9mX3RyYW5zbGF0ZV9hZGRyZXNzKCkgcmV0
dXJuIGFuIGVycm9yLg0KPiA+IEhlcmUgd2UgYWRkIGEgZml4dXAgZnVuY3Rpb24sIG9mX2dldF9p
c2FfaW5kaXJlY3RfaW8oKS4gRHVyaW5nIHRoZSBPRg0KPiBhZGRyZXNzDQo+ID4gdHJhbnNsYXRp
b24sIHRoaXMgZml4dXAgd2lsbCBiZSBjYWxsZWQgdG8gY2hlY2sgdGhlICdyZWcnIGFkZHJlc3Mg
dG8NCj4gYmUNCj4gPiB0cmFuc2xhdGluZyBpcyBmb3IgdGhvc2Ugc2VwY2lhbCBJU0EvTFBDIGRl
dmljZXMgYW5kIGdldCB0aGUgSS9PDQo+IHJhbmdlDQo+ID4gZGlyZWN0bHkgZnJvbSB0aGUgJ3Jl
ZycgcHJvcGVydHkuDQo+ID4NCj4gPiAyKSBlbGltaW5hdGUgdGhlIEkvTyByYW5nZSBjb25mbGlj
dCByaXNrIHdpdGggUENJL1BDSUUgbGVhZ2VjeSBJL08NCj4gZGV2aWNlOw0KPiA+DQo+ID4gVGhl
IGN1cnJlbnQgX19vZl9hZGRyZXNzX3RvX3Jlc291cmNlKCkgYWx3YXlzIHRyYW5zbGF0ZXMgdGhl
IEkvTw0KPiByYW5nZSB0byBQSU8uDQo+ID4gQnV0IHRoaXMgcHJvY2Vzc2luZyBpcyBub3Qgc3Vp
dGFibGUgZm9yIG91ciBJU0EvTFBDIGRldmljZXMgd2hvc2UgSS9PDQo+IHJhbmdlIGlzDQo+ID4g
bm90IGNwdSBhZGRyZXNzKEFybmQgaGFkIHN0cmVzc2VkIHRoaXMgaW4gaGlzIGNvbW1lbnRzIG9u
IFYyLFYzDQo+IHBhdGNoLXNldCkuDQo+ID4gSGVyZSwgd2UgYnlwYXNzIHRoZSBtYXBwaW5nIGJl
dHdlZW4gY3B1IGFkZHJlc3MgYW5kIFBJTyBmb3IgdGhlDQo+IHNwZWNpYWwNCj4gPiBJU0EvTFBD
IGRldmljZXMuIEJ1dCB0byBkcml2ZSB0aGVzZSBJU0EvTFBDIGRldmljZXMsIGEgSS9PIHBvcnQN
Cj4gYWRkcmVzcyBiZWxvdw0KPiA+IFBDSUJJT1NfTUlOX0lPIGlzIG5lZWRlZCBieSBpbiovb3V0
KigpLiBXaGljaCBtZWFucyB0aGVyZSBpcyBjb25mbGljdA0KPiByaXNrDQo+ID4gYmV0d2VlbiBJ
L08gcmFuZ2Ugb2YgWzAsIFBDSUJJT1NfTUlOX0lPKSBhbmQgUENJL1BDSUUgbGVnYWN5IEkvTw0K
PiByYW5nZSBvZiBbMCwNCj4gPiBJT19TUEFDRV9MSU1JVCkuDQo+ID4gVG8gYXZvaWQgdGhlIEkv
TyBjb25mbGljdCwgdGhpcyBwYXRjaCByZXNlcnZlIHRoZSBJL08gcmFuZ2UgYmVsb3cNCj4gPiBQ
Q0lCSU9TX01JTl9JTy4NCj4gPg0KPiA+IFNpZ25lZC1vZmYtYnk6IHpoaWNoYW5nLnl1YW4gPHl1
YW56aGljaGFuZ0BoaXNpbGljb24uY29tPg0KPiA+IFNpZ25lZC1vZmYtYnk6IEdhYnJpZWxlIFBh
b2xvbmkgPGdhYnJpZWxlLnBhb2xvbmlAaHVhd2VpLmNvbT4NCj4gPiAtLS0NCj4gPiAgLi4uL2Fy
bS9oaXNpbGljb24vaGlzaWxpY29uLWxvdy1waW4tY291bnQudHh0ICAgICAgfCAzMSArKysrKysr
KysrKysNCj4gPiAgYXJjaC9hcm02NC9pbmNsdWRlL2FzbS9pby5oICAgICAgICAgICAgICAgICAg
ICAgICAgfCAgNiArKysNCj4gPiAgYXJjaC9hcm02NC9rZXJuZWwvZXh0aW8uYyAgICAgICAgICAg
ICAgICAgICAgICAgICAgfCAyNSArKysrKysrKysrDQo+ID4gIGRyaXZlcnMvb2YvYWRkcmVzcy5j
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNTYNCj4gKysrKysrKysrKysrKysrKysr
KysrLQ0KPiA+ICBkcml2ZXJzL3BjaS9wY2kuYyAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICB8ICA2ICstLQ0KPiA+ICBpbmNsdWRlL2xpbnV4L29mX2FkZHJlc3MuaCAgICAgICAgICAg
ICAgICAgICAgICAgICB8IDE3ICsrKysrKysNCj4gPiAgaW5jbHVkZS9saW51eC9wY2kuaCAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAgOCArKysrDQo+ID4gIDcgZmlsZXMgY2hhbmdl
ZCwgMTQ1IGluc2VydGlvbnMoKyksIDQgZGVsZXRpb25zKC0pDQo+ID4gIGNyZWF0ZSBtb2RlIDEw
MDY0NA0KPiBEb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvYXJtL2hpc2lsaWNvbi9o
aXNpbGljb24tbG93LXBpbi0NCj4gY291bnQudHh0DQo+ID4NCj4gPiBkaWZmIC0tZ2l0DQo+IGEv
RG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL2FybS9oaXNpbGljb24vaGlzaWxpY29u
LWxvdy1waW4tDQo+IGNvdW50LnR4dCBiL0RvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5kaW5n
cy9hcm0vaGlzaWxpY29uL2hpc2lsaWNvbi0NCj4gbG93LXBpbi1jb3VudC50eHQNCj4gPiBuZXcg
ZmlsZSBtb2RlIDEwMDY0NA0KPiA+IGluZGV4IDAwMDAwMDAuLjEzYzhkZGQNCj4gPiAtLS0gL2Rl
di9udWxsDQo+ID4gKysrIGIvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL2FybS9o
aXNpbGljb24vaGlzaWxpY29uLWxvdy0NCj4gcGluLWNvdW50LnR4dA0KPiA+IEBAIC0wLDAgKzEs
MzEgQEANCj4gPiArSGlzaWxpY29uIEhpcDA2IGxvdy1waW4tY291bnQgZGV2aWNlDQo+ID4gKyAg
VXN1YWxseSBMUEMgY29udHJvbGxlciBpcyBwYXJ0IG9mIFBDSSBob3N0IGJyaWRnZSwgc28gdGhl
IGxlZ2FjeQ0KPiBJU0EgcG9ydHMNCj4gPiArICBsb2NhdGUgb24gTFBDIGJ1cyBjYW4gYmUgYWNj
ZXNzZWQgZGlyZWNsdHkuIEJ1dCBzb21lIFNvQ3MgaGF2ZQ0KPiBpbmRlcGVuZGVudA0KPiA+ICsg
IExQQyBjb250cm9sbGVyLCBhbmQgYWNjZXNzIHRoZSBsZWdhY3kgcG9ydHMgYnkgdHJpZ2dlcmlu
ZyBMUEMgSS9PDQo+IGN5Y2xlcy4NCj4gPiArICBIaXNpbGljb24gSGlwMDYgaW1wbGVtZW50cyB0
aGlzIExQQyBkZXZpY2UuDQo+ID4gKw0KPiA+ICtSZXF1aXJlZCBwcm9wZXJ0aWVzOg0KPiA+ICst
IGNvbXBhdGlibGU6IHNob3VsZCBiZSAiaGlzaWxpY29uLGxvdy1waW4tY291bnQiDQo+ID4gKy0g
I2FkZHJlc3MtY2VsbHM6IG11c3QgYmUgMiB3aGljaCBzdGljayB0byB0aGUgSVNBL0VJU0EgYmlu
ZGluZyBkb2MuDQo+ID4gKy0gI3NpemUtY2VsbHM6IG11c3QgYmUgMSB3aGljaCBzdGljayB0byB0
aGUgSVNBL0VJU0EgYmluZGluZyBkb2MuDQo+ID4gKy0gcmVnOiBiYXNlIG1lbW9yeSByYW5nZSB3
aGVyZSB0aGUgcmVnaXN0ZXIgc2V0IG9mIHRoaXMgZGV2aWNlIGlzDQo+IG1hcHBlZC4NCj4gPiAr
DQo+ID4gK05vdGU6DQo+ID4gKyAgVGhlIG5vZGUgbmFtZSBiZWZvcmUgJ0AnIG11c3QgYmUgImlz
YSIgdG8gcmVwcmVzZW50IHRoZSBiaW5kaW5nDQo+IHN0aWNrIHRvIHRoZQ0KPiA+ICsgIElTQS9F
SVNBIGJpbmRpbmcgc3BlY2lmaWNhdGlvbi4NCj4gPiArDQo+ID4gK0V4YW1wbGU6DQo+ID4gKw0K
PiA+ICtpc2FAYTAxYjAwMDAgew0KPiA+ICsJY29tcGF0aWJsZSA9ICJoaXNpbGljb20sbG93LXBp
bi1jb3VudCI7DQo+ID4gKwkjYWRkcmVzcy1jZWxscyA9IDwyPjsNCj4gPiArCSNzaXplLWNlbGxz
ID0gPDE+Ow0KPiA+ICsJcmVnID0gPDB4MCAweGEwMWIwMDAwIDB4MCAweDEwMDA+Ow0KPiA+ICsN
Cj4gPiArCWlwbWkwOiBidEBlNCB7DQo+ID4gKwkJY29tcGF0aWJsZSA9ICJpcG1pLWJ0IjsNCj4g
PiArCQlkZXZpY2VfdHlwZSA9ICJpcG1pIjsNCj4gPiArCQlyZWcgPSA8MHgwMSAweGU0IDB4MDQ+
Ow0KPiA+ICsJCXN0YXR1cyA9ICJkaXNhYmxlZCI7DQo+ID4gKwl9Ow0KPiA+ICt9Ow0KPiANCj4g
DQo+IFRoaXMgZG9jdW1lbnRhdGlvbiBmaWxlIG5lZWRzIHRvIGJlIHBhcnQgb2YgdGhlIG5leHQg
cGF0Y2guIEl0IGhhcw0KPiBub3RoaW5nIHRvIGRvIHdpdGgNCj4gd2hhdCB5b3UgYXJlIHRyeWlu
ZyB0byBmaXggaGVyZS4NCg0KWWVzIHlvdSdyZSByaWdodC4uLndlJ2xsIG1vdmUgaXQgdG8gbmV4
dCBvbmUNCg0KPiANCj4gDQo+ID4gZGlmZiAtLWdpdCBhL2FyY2gvYXJtNjQvaW5jbHVkZS9hc20v
aW8uaA0KPiBiL2FyY2gvYXJtNjQvaW5jbHVkZS9hc20vaW8uaA0KPiA+IGluZGV4IDEzNjczNWQu
LmMyNmI3Y2MgMTAwNjQ0DQo+ID4gLS0tIGEvYXJjaC9hcm02NC9pbmNsdWRlL2FzbS9pby5oDQo+
ID4gKysrIGIvYXJjaC9hcm02NC9pbmNsdWRlL2FzbS9pby5oDQo+ID4gQEAgLTE3NSw2ICsxNzUs
MTIgQEAgc3RhdGljIGlubGluZSB1NjQgX19yYXdfcmVhZHEoY29uc3Qgdm9sYXRpbGUNCj4gdm9p
ZCBfX2lvbWVtICphZGRyKQ0KPiA+ICAjZGVmaW5lIG91dHNsIG91dHNsDQo+ID4NCj4gPiAgREVD
TEFSRV9FWFRJTyhsLCB1MzIpDQo+ID4gKw0KPiA+ICsjZGVmaW5lIGluZGlyZWN0X2lvX2VuYWJs
ZWQgaW5kaXJlY3RfaW9fZW5hYmxlZA0KPiA+ICtleHRlcm4gYm9vbCBpbmRpcmVjdF9pb19lbmFi
bGVkKHZvaWQpOw0KPiA+ICsNCj4gPiArI2RlZmluZSBhZGRyX2lzX2luZGlyZWN0X2lvIGFkZHJf
aXNfaW5kaXJlY3RfaW8NCj4gPiArZXh0ZXJuIGludCBhZGRyX2lzX2luZGlyZWN0X2lvKHU2NCB0
YWRkcik7DQo+ID4gICNlbmRpZg0KPiA+DQo+ID4NCj4gPiBkaWZmIC0tZ2l0IGEvYXJjaC9hcm02
NC9rZXJuZWwvZXh0aW8uYyBiL2FyY2gvYXJtNjQva2VybmVsL2V4dGlvLmMNCj4gPiBpbmRleCA2
NDdiM2ZhLi4zZDQ1ZmE4IDEwMDY0NA0KPiA+IC0tLSBhL2FyY2gvYXJtNjQva2VybmVsL2V4dGlv
LmMNCj4gPiArKysgYi9hcmNoL2FybTY0L2tlcm5lbC9leHRpby5jDQo+ID4gQEAgLTE5LDYgKzE5
LDMxIEBADQo+ID4NCj4gPiAgc3RydWN0IGV4dGlvX29wcyAqYXJtNjRfZXh0aW9fb3BzOw0KPiA+
DQo+ID4gKy8qKg0KPiA+ICsgKiBpbmRpcmVjdF9pb19lbmFibGVkIC0gY2hlY2sgd2hldGhlciBp
bmRpcmVjdElPIGlzIGVuYWJsZWQuDQo+ID4gKyAqCWFybTY0X2V4dGlvX29wcyB3aWxsIGJlIHNl
dCBvbmx5IHdoZW4gaW5kaXJlY3RJTyBtZWNoYW5pc20gaGFkDQo+IGJlZW4NCj4gPiArICoJaW5p
dGlhbGl6ZWQuDQo+ID4gKyAqDQo+ID4gKyAqIFJldHVybnMgdHJ1ZSB3aGVuIGluZGlyZWN0SU8g
aXMgZW5hYmxlZC4NCj4gPiArICovDQo+ID4gK2Jvb2wgaW5kaXJlY3RfaW9fZW5hYmxlZCh2b2lk
KQ0KPiA+ICt7DQo+ID4gKwlyZXR1cm4gYXJtNjRfZXh0aW9fb3BzID8gdHJ1ZSA6IGZhbHNlOw0K
PiA+ICt9DQo+ID4gKw0KPiA+ICsvKioNCj4gPiArICogYWRkcl9pc19pbmRpcmVjdF9pbyAtIGNo
ZWNrIHdoZXRoZXIgdGhlIGlucHV0IHRhZGRyIGlzIGZvcg0KPiBpbmRpcmVjdElPLg0KPiA+ICsg
KiBAdGFkZHI6IHRoZSBpbyBhZGRyZXNzIHRvIGJlIGNoZWNrZWQuDQo+ID4gKyAqDQo+ID4gKyAq
IFJldHVybnMgMSB3aGVuIHRhZGRyIGlzIGluIHRoZSByYW5nZTsgb3RoZXJ3aXNlIHJldHVybiAw
Lg0KPiA+ICsgKi8NCj4gPiAraW50IGFkZHJfaXNfaW5kaXJlY3RfaW8odTY0IHRhZGRyKQ0KPiA+
ICt7DQo+ID4gKwlpZiAoYXJtNjRfZXh0aW9fb3BzLT5zdGFydCA+IHRhZGRyIHx8IGFybTY0X2V4
dGlvX29wcy0+ZW5kIDwNCj4gdGFkZHIpDQo+IA0KPiBzdGFydCA+PSB0YWRkciA/DQoNCk5vcGUu
Li4gaWYgICh0YWRkciA8IGFybTY0X2V4dGlvX29wcy0+c3RhcnQgfHwgdGFkZHIgPiBhcm02NF9l
eHRpb19vcHMtPmVuZCkNCnRoZW4gdGFkZHIgaXMgb3V0c2lkZSB0aGUgcmFuZ2UgW3N0YXJ0OyBl
bmRdIGFuZCB3aWxsIHJldHVybiAwOyBvdGhlcndpc2UNCml0IHdpbGwgcmV0dXJuIDEuLi4NCg0K
PiANCj4gPiArCQlyZXR1cm4gMDsNCj4gPiArDQo+ID4gKwlyZXR1cm4gMTsNCj4gPiArfQ0KPiA+
DQo+ID4gIEJVSUxEX0VYVElPKGIsIHU4KQ0KPiA+DQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMv
b2YvYWRkcmVzcy5jIGIvZHJpdmVycy9vZi9hZGRyZXNzLmMNCj4gPiBpbmRleCAwMmIyOTAzLi5j
YzJhMDVkIDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvb2YvYWRkcmVzcy5jDQo+ID4gKysrIGIv
ZHJpdmVycy9vZi9hZGRyZXNzLmMNCj4gPiBAQCAtNDc5LDYgKzQ3OSw1MCBAQCBzdGF0aWMgaW50
IG9mX2VtcHR5X3Jhbmdlc19xdWlyayhzdHJ1Y3QNCj4gZGV2aWNlX25vZGUgKm5wKQ0KPiA+ICAJ
cmV0dXJuIGZhbHNlOw0KPiA+ICB9DQo+ID4NCj4gPiArDQo+ID4gKy8qDQo+ID4gKyAqIG9mX2lz
YV9pbmRpcmVjdF9pbyAtIGdldCB0aGUgSU8gYWRkcmVzcyBmcm9tIHNvbWUgaXNhIHJlZw0KPiBw
cm9wZXJ0eSB2YWx1ZS4NCj4gPiArICoJRm9yIHNvbWUgaXNhL2xwYyBkZXZpY2VzLCBubyByYW5n
ZXMgcHJvcGVydHkgaW4gYW5jZXN0b3Igbm9kZS4NCj4gPiArICoJVGhlIGRldmljZSBhZGRyZXNz
ZXMgYXJlIGRlc2NyaWJlZCBkaXJlY3RseSBpbiB0aGVpciByZWdzDQo+IHByb3BlcnR5Lg0KPiA+
ICsgKglUaGlzIGZpeHVwIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIHRvIGdldCB0aGUgSU8gYWRk
cmVzcyBvZg0KPiBpc2EvbHBjDQo+ID4gKyAqCWRldmljZXMgd2hlbiB0aGUgbm9ybWFsIG9mX3Ry
YW5zbGF0aW9uIGZhaWxlZC4NCj4gPiArICoNCj4gPiArICogQHBhcmVudDoJcG9pbnRzIHRvIHRo
ZSBwYXJlbnQgZHRzIG5vZGU7DQo+ID4gKyAqIEBidXM6CQlwb2ludHMgdG8gdGhlIG9mX2J1cyB3
aGljaCBjYW4gYmUgdXNlZCB0byBwYXJzZQ0KPiBhZGRyZXNzOw0KPiA+ICsgKiBAYWRkcjoJdGhl
IGFkZHJlc3MgZnJvbSByZWcgcHJvcGVydHk7DQo+ID4gKyAqIEBuYToJCXRoZSBhZGRyZXNzIGNl
bGwgY291bnRlciBvZiBAYWRkcjsNCj4gPiArICogQHByZXN1bHQ6CXN0b3JlIHRoZSBhZGRyZXNz
IHBhcmVzZWQgZnJvbSBAYWRkcjsNCj4gPiArICoNCj4gPiArICogcmV0dXJuIDEgd2hlbiBzdWNj
ZXNzZnVsbHkgZ2V0IHRoZSBJL08gYWRkcmVzczsNCj4gPiArICogMCB3aWxsIHJldHVybiBmb3Ig
c29tZSBmYWlsdXJlcy4NCj4gDQo+IEJhaCwgeW91IGFyZSByZXR1cm5pbmcgYSBzaWduZWQgaW50
LCB3aHkgMCBmb3IgZmFpbHVyZT8gUmV0dXJuIGENCj4gbmVnYXRpdmUgdmFsdWUgd2l0aA0KPiBl
cnJvciBjb2Rlcy4gT3RoZXJ3aXNlIGNoYW5nZSB0aGUgcmV0dXJuIHZhbHVlIGludG8gYSBib29s
Lg0KDQpZZXMgd2UnbGwgbW92ZSB0byBib29sDQoNCj4gDQo+ID4gKyAqLw0KPiA+ICtzdGF0aWMg
aW50IG9mX2dldF9pc2FfaW5kaXJlY3RfaW8oc3RydWN0IGRldmljZV9ub2RlICpwYXJlbnQsDQo+
ID4gKwkJCQlzdHJ1Y3Qgb2ZfYnVzICpidXMsIF9fYmUzMiAqYWRkciwNCj4gPiArCQkJCWludCBu
YSwgdTY0ICpwcmVzdWx0KQ0KPiA+ICt7DQo+ID4gKwl1bnNpZ25lZCBpbnQgZmxhZ3M7DQo+ID4g
Kwl1bnNpZ25lZCBpbnQgcmxlbjsNCj4gPiArDQo+ID4gKwkvKiB3aGV0aGVyIHN1cHBvcnQgaW5k
aXJlY3RJTyAqLw0KPiA+ICsJaWYgKCFpbmRpcmVjdF9pb19lbmFibGVkKCkpDQo+ID4gKwkJcmV0
dXJuIDA7DQo+ID4gKw0KPiA+ICsJaWYgKCFvZl9idXNfaXNhX21hdGNoKHBhcmVudCkpDQo+ID4g
KwkJcmV0dXJuIDA7DQo+ID4gKw0KPiA+ICsJZmxhZ3MgPSBidXMtPmdldF9mbGFncyhhZGRyKTsN
Cj4gPiArCWlmICghKGZsYWdzICYgSU9SRVNPVVJDRV9JTykpDQo+ID4gKwkJcmV0dXJuIDA7DQo+
ID4gKw0KPiA+ICsJLyogdGhlcmUgaXMgcmFuZ2VzIHByb3BlcnR5LCBhcHBseSB0aGUgbm9ybWFs
IHRyYW5zbGF0aW9uDQo+IGRpcmVjdGx5LiAqLw0KPiANCj4gcy90aGVyZSBpcyByYW5nZXMvaWYg
d2UgaGF2ZSBhICdyYW5nZXMnLw0KDQpUaGFua3MgZm9yIHNwb3R0aW5nIHRoaXMNCg0KPiANCj4g
PiArCWlmIChvZl9nZXRfcHJvcGVydHkocGFyZW50LCAicmFuZ2VzIiwgJnJsZW4pKQ0KPiA+ICsJ
CXJldHVybiAwOw0KPiA+ICsNCj4gPiArCSpwcmVzdWx0ID0gb2ZfcmVhZF9udW1iZXIoYWRkciAr
IDEsIG5hIC0gMSk7DQo+ID4gKwkvKiB0aGlzIGZpeHVwIGlzIG9ubHkgdmFsaWQgZm9yIHNwZWNp
ZmljIEkvTyByYW5nZS4gKi8NCj4gPiArCXJldHVybiBhZGRyX2lzX2luZGlyZWN0X2lvKCpwcmVz
dWx0KTsNCj4gPiArfQ0KPiA+ICsNCj4gPiAgc3RhdGljIGludCBvZl90cmFuc2xhdGVfb25lKHN0
cnVjdCBkZXZpY2Vfbm9kZSAqcGFyZW50LCBzdHJ1Y3QNCj4gb2ZfYnVzICpidXMsDQo+ID4gIAkJ
CSAgICBzdHJ1Y3Qgb2ZfYnVzICpwYnVzLCBfX2JlMzIgKmFkZHIsDQo+ID4gIAkJCSAgICBpbnQg
bmEsIGludCBucywgaW50IHBuYSwgY29uc3QgY2hhciAqcnByb3ApDQo+ID4gQEAgLTU5NSw2ICs2
MzksMTUgQEAgc3RhdGljIHU2NCBfX29mX3RyYW5zbGF0ZV9hZGRyZXNzKHN0cnVjdA0KPiBkZXZp
Y2Vfbm9kZSAqZGV2LA0KPiA+ICAJCQlyZXN1bHQgPSBvZl9yZWFkX251bWJlcihhZGRyLCBuYSk7
DQo+ID4gIAkJCWJyZWFrOw0KPiA+ICAJCX0NCj4gPiArCQkvKg0KPiA+ICsJCSAqIEZvciBpbmRp
cmVjdElPIGRldmljZSB3aGljaCBoYXMgbm8gcmFuZ2VzIHByb3BlcnR5LCBnZXQNCj4gPiArCQkg
KiB0aGUgYWRkcmVzcyBmcm9tIHJlZyBkaXJlY3RseS4NCj4gPiArCQkgKi8NCj4gPiArCQlpZiAo
b2ZfZ2V0X2lzYV9pbmRpcmVjdF9pbyhkZXYsIGJ1cywgYWRkciwgbmEsICZyZXN1bHQpKSB7DQo+
ID4gKwkJCXByX2RlYnVnKCJpc2EgaW5kaXJlY3RJTyBtYXRjaGVkKCVzKS4uYWRkciA9DQo+IDB4
JWxseFxuIiwNCj4gPiArCQkJCW9mX25vZGVfZnVsbF9uYW1lKGRldiksIHJlc3VsdCk7DQo+ID4g
KwkJCWJyZWFrOw0KPiA+ICsJCX0NCj4gPg0KPiA+ICAJCS8qIEdldCBuZXcgcGFyZW50IGJ1cyBh
bmQgY291bnRzICovDQo+ID4gIAkJcGJ1cyA9IG9mX21hdGNoX2J1cyhwYXJlbnQpOw0KPiA+IEBA
IC02ODgsOCArNzQxLDkgQEAgc3RhdGljIGludCBfX29mX2FkZHJlc3NfdG9fcmVzb3VyY2Uoc3Ry
dWN0DQo+IGRldmljZV9ub2RlICpkZXYsDQo+ID4gIAlpZiAodGFkZHIgPT0gT0ZfQkFEX0FERFIp
DQo+ID4gIAkJcmV0dXJuIC1FSU5WQUw7DQo+ID4gIAltZW1zZXQociwgMCwgc2l6ZW9mKHN0cnVj
dCByZXNvdXJjZSkpOw0KPiA+IC0JaWYgKGZsYWdzICYgSU9SRVNPVVJDRV9JTykgew0KPiA+ICsJ
aWYgKGZsYWdzICYgSU9SRVNPVVJDRV9JTyAmJiB0YWRkciA+PSBQQ0lCSU9TX01JTl9JTykgew0K
PiA+ICAJCXVuc2lnbmVkIGxvbmcgcG9ydDsNCj4gPiArDQo+ID4gIAkJcG9ydCA9IHBjaV9hZGRy
ZXNzX3RvX3Bpbyh0YWRkcik7DQo+ID4gIAkJaWYgKHBvcnQgPT0gKHVuc2lnbmVkIGxvbmcpLTEp
DQo+ID4gIAkJCXJldHVybiAtRUlOVkFMOw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3BjaS9w
Y2kuYyBiL2RyaXZlcnMvcGNpL3BjaS5jDQo+ID4gaW5kZXggYmEzNDkwNy4uMWEwODUxMSAxMDA2
NDQNCj4gPiAtLS0gYS9kcml2ZXJzL3BjaS9wY2kuYw0KPiA+ICsrKyBiL2RyaXZlcnMvcGNpL3Bj
aS5jDQo+ID4gQEAgLTMyNjMsNyArMzI2Myw3IEBAIGludCBfX3dlYWsgcGNpX3JlZ2lzdGVyX2lv
X3JhbmdlKHBoeXNfYWRkcl90DQo+IGFkZHIsIHJlc291cmNlX3NpemVfdCBzaXplKQ0KPiA+DQo+
ID4gICNpZmRlZiBQQ0lfSU9CQVNFDQo+ID4gIAlzdHJ1Y3QgaW9fcmFuZ2UgKnJhbmdlOw0KPiA+
IC0JcmVzb3VyY2Vfc2l6ZV90IGFsbG9jYXRlZF9zaXplID0gMDsNCj4gPiArCXJlc291cmNlX3Np
emVfdCBhbGxvY2F0ZWRfc2l6ZSA9IFBDSUJJT1NfTUlOX0lPOw0KPiA+DQo+ID4gIAkvKiBjaGVj
ayBpZiB0aGUgcmFuZ2UgaGFzbid0IGJlZW4gcHJldmlvdXNseSByZWNvcmRlZCAqLw0KPiA+ICAJ
c3Bpbl9sb2NrKCZpb19yYW5nZV9sb2NrKTsNCj4gPiBAQCAtMzMxMiw3ICszMzEyLDcgQEAgcGh5
c19hZGRyX3QgcGNpX3Bpb190b19hZGRyZXNzKHVuc2lnbmVkIGxvbmcNCj4gcGlvKQ0KPiA+DQo+
ID4gICNpZmRlZiBQQ0lfSU9CQVNFDQo+ID4gIAlzdHJ1Y3QgaW9fcmFuZ2UgKnJhbmdlOw0KPiA+
IC0JcmVzb3VyY2Vfc2l6ZV90IGFsbG9jYXRlZF9zaXplID0gMDsNCj4gPiArCXJlc291cmNlX3Np
emVfdCBhbGxvY2F0ZWRfc2l6ZSA9IFBDSUJJT1NfTUlOX0lPOw0KPiANCj4gSGF2ZSB5b3UgY2hl
Y2tlZCB0aGF0IHBjaV9waW9fdG9fYWRkcmVzcyBzdGlsbCByZXR1cm5zIHZhbGlkIHZhbHVlcw0K
PiBhZnRlciB0aGlzPyBJIGtub3cgdGhhdA0KPiB5b3UgYXJlIHRyeWluZyB0byB0YWtlIGludG8g
YWNjb3VudCBQQ0lCSU9TX01JTl9JTyBsaW1pdCB3aGVuDQo+IGFsbG9jYXRpbmcgcmVzZXJ2aW5n
IHRoZSBJTyByYW5nZXMsDQo+IGJ1dCB0aGUgdmFsdWVzIGFkZGVkIGluIHRoZSBpb19yYW5nZV9s
aXN0IGFyZSBzdGlsbCBzdGFydGluZyBmcm9tIHplcm8sDQo+IG5vIGZyb20gUENJQklPU19NSU5f
SU8sDQoNCkkgdGhpbmsgeW91J3JlIHdyb25nIGhlcmUgYXMgaW4gcGNpX2FkZHJlc3NfdG9fcGlv
IHdlIGhhdmU6DQorCXJlc291cmNlX3NpemVfdCBvZmZzZXQgPSBQQ0lCSU9TX01JTl9JTzsNCg0K
VGhpcyBzaG91bGQgYmUgZW5vdWdoIHRvIGd1YXJhbnRlZSB0aGF0IHRoZSBQSU9zIHN0YXJ0IGF0
DQpQQ0lCSU9TX01JTl9JTy4uLnJpZ2h0Pw0KDQoNCj4gc28gdGhlIGNhbGN1bGF0aW9uIG9mIHRo
ZSBhZGRyZXNzIGluIHRoaXMgZnVuY3Rpb24gY291bGQgcmV0dXJuDQo+IG5lZ2F0aXZlIHZhbHVl
cyBjYXN0ZWQgdG8gcGNpX2FkZHJfdC4NCj4gDQo+IE1heWJlIHlvdSB3YW50IHRvIGFkanVzdCB0
aGUgcmFuZ2UtPnN0YXJ0IHZhbHVlIGluDQo+IHBjaV9yZWdpc3Rlcl9pb19yYW5nZSgpIGFzIHdl
bGwgdG8gaGF2ZSBpdA0KPiBvZmZzZXQgYnkgUENJQklPU19NSU5fSU8gYXMgd2VsbC4NCj4gDQo+
IEJlc3QgcmVnYXJkcywNCj4gTGl2aXUNCj4gDQo+ID4NCj4gPiAgCWlmIChwaW8gPiBJT19TUEFD
RV9MSU1JVCkNCj4gPiAgCQlyZXR1cm4gYWRkcmVzczsNCj4gPiBAQCAtMzMzNSw3ICszMzM1LDcg
QEAgdW5zaWduZWQgbG9uZyBfX3dlYWsNCj4gcGNpX2FkZHJlc3NfdG9fcGlvKHBoeXNfYWRkcl90
IGFkZHJlc3MpDQo+ID4gIHsNCj4gPiAgI2lmZGVmIFBDSV9JT0JBU0UNCj4gPiAgCXN0cnVjdCBp
b19yYW5nZSAqcmVzOw0KPiA+IC0JcmVzb3VyY2Vfc2l6ZV90IG9mZnNldCA9IDA7DQo+ID4gKwly
ZXNvdXJjZV9zaXplX3Qgb2Zmc2V0ID0gUENJQklPU19NSU5fSU87DQo+ID4gIAl1bnNpZ25lZCBs
b25nIGFkZHIgPSAtMTsNCj4gPg0KPiA+ICAJc3Bpbl9sb2NrKCZpb19yYW5nZV9sb2NrKTsNCj4g
PiBkaWZmIC0tZ2l0IGEvaW5jbHVkZS9saW51eC9vZl9hZGRyZXNzLmggYi9pbmNsdWRlL2xpbnV4
L29mX2FkZHJlc3MuaA0KPiA+IGluZGV4IDM3ODY0NzMuLmRlZWM0NjkgMTAwNjQ0DQo+ID4gLS0t
IGEvaW5jbHVkZS9saW51eC9vZl9hZGRyZXNzLmgNCj4gPiArKysgYi9pbmNsdWRlL2xpbnV4L29m
X2FkZHJlc3MuaA0KPiA+IEBAIC0yNCw2ICsyNCwyMyBAQCBzdHJ1Y3Qgb2ZfcGNpX3JhbmdlIHsN
Cj4gPiAgI2RlZmluZSBmb3JfZWFjaF9vZl9wY2lfcmFuZ2UocGFyc2VyLCByYW5nZSkgXA0KPiA+
ICAJZm9yICg7IG9mX3BjaV9yYW5nZV9wYXJzZXJfb25lKHBhcnNlciwgcmFuZ2UpOykNCj4gPg0K
PiA+ICsNCj4gPiArI2lmbmRlZiBpbmRpcmVjdF9pb19lbmFibGVkDQo+ID4gKyNkZWZpbmUgaW5k
aXJlY3RfaW9fZW5hYmxlZCBpbmRpcmVjdF9pb19lbmFibGVkDQo+ID4gK3N0YXRpYyBpbmxpbmUg
Ym9vbCBpbmRpcmVjdF9pb19lbmFibGVkKHZvaWQpDQo+ID4gK3sNCj4gPiArCXJldHVybiBmYWxz
ZTsNCj4gPiArfQ0KPiA+ICsjZW5kaWYNCj4gPiArDQo+ID4gKyNpZm5kZWYgYWRkcl9pc19pbmRp
cmVjdF9pbw0KPiA+ICsjZGVmaW5lIGFkZHJfaXNfaW5kaXJlY3RfaW8gYWRkcl9pc19pbmRpcmVj
dF9pbw0KPiA+ICtzdGF0aWMgaW5saW5lIGludCBhZGRyX2lzX2luZGlyZWN0X2lvKHU2NCB0YWRk
cikNCj4gPiArew0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArI2VuZGlmDQo+ID4gKw0K
PiA+ICAvKiBUcmFuc2xhdGUgYSBETUEgYWRkcmVzcyBmcm9tIGRldmljZSBzcGFjZSB0byBDUFUg
c3BhY2UgKi8NCj4gPiAgZXh0ZXJuIHU2NCBvZl90cmFuc2xhdGVfZG1hX2FkZHJlc3Moc3RydWN0
IGRldmljZV9ub2RlICpkZXYsDQo+ID4gIAkJCQkgICAgY29uc3QgX19iZTMyICppbl9hZGRyKTsN
Cj4gPiBkaWZmIC0tZ2l0IGEvaW5jbHVkZS9saW51eC9wY2kuaCBiL2luY2x1ZGUvbGludXgvcGNp
LmgNCj4gPiBpbmRleCAwZTQ5ZjcwLi43ZjZiYmI2IDEwMDY0NA0KPiA+IC0tLSBhL2luY2x1ZGUv
bGludXgvcGNpLmgNCj4gPiArKysgYi9pbmNsdWRlL2xpbnV4L3BjaS5oDQo+ID4gQEAgLTIxMzAs
NCArMjEzMCwxMiBAQCBzdGF0aWMgaW5saW5lIGJvb2wgcGNpX2FyaV9lbmFibGVkKHN0cnVjdA0K
PiBwY2lfYnVzICpidXMpDQo+ID4gIC8qIHByb3ZpZGUgdGhlIGxlZ2FjeSBwY2lfZG1hXyogQVBJ
ICovDQo+ID4gICNpbmNsdWRlIDxsaW51eC9wY2ktZG1hLWNvbXBhdC5oPg0KPiA+DQo+ID4gKy8q
DQo+ID4gKyAqIGRlZmluZSB0aGlzIG1hY3JvIGhlcmUgdG8gcmVmcmFpbiBmcm9tIGNvbXBpbGF0
aW9uIGVycm9yIGZvciBzb21lDQo+ID4gKyAqIHBsYXRmb3Jtcy4gUGxlYXNlIGtlZXAgdGhpcyBt
YWNybyBhdCB0aGUgZW5kIG9mIHRoaXMgaGVhZGVyIGZpbGUuDQo+ID4gKyAqLw0KPiA+ICsjaWZu
ZGVmIFBDSUJJT1NfTUlOX0lPDQo+ID4gKyNkZWZpbmUgUENJQklPU19NSU5fSU8JCTANCj4gPiAr
I2VuZGlmDQo+ID4gKw0KPiA+ICAjZW5kaWYgLyogTElOVVhfUENJX0ggKi8NCj4gPiAtLQ0KPiA+
IDEuOS4xDQo+ID4NCj4gPiAtLQ0KPiA+IFRvIHVuc3Vic2NyaWJlIGZyb20gdGhpcyBsaXN0OiBz
ZW5kIHRoZSBsaW5lICJ1bnN1YnNjcmliZSBsaW51eC1wY2kiDQo+IGluDQo+ID4gdGhlIGJvZHkg
b2YgYSBtZXNzYWdlIHRvIG1ham9yZG9tb0B2Z2VyLmtlcm5lbC5vcmcNCj4gPiBNb3JlIG1ham9y
ZG9tbyBpbmZvIGF0ICBodHRwOi8vdmdlci5rZXJuZWwub3JnL21ham9yZG9tby1pbmZvLmh0bWwN
Cj4gDQo+IC0tDQo+ID09PT09PT09PT09PT09PT09PT09DQo+IHwgSSB3b3VsZCBsaWtlIHRvIHwN
Cj4gfCBmaXggdGhlIHdvcmxkLCAgfA0KPiB8IGJ1dCB0aGV5J3JlIG5vdCB8DQo+IHwgZ2l2aW5n
IG1lIHRoZSAgIHwNCj4gIFwgc291cmNlIGNvZGUhICAvDQo+ICAgLS0tLS0tLS0tLS0tLS0tDQo+
ICAgICDCr1xfKOODhClfL8KvDQo=

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

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-09 16:16       ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-09 16:16 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Liviu

Thanks for reviewing

> -----Original Message-----
> From: liviu.dudau at arm.com [mailto:liviu.dudau at arm.com]
> Sent: 09 November 2016 11:40
> To: Yuanzhichang
> Cc: catalin.marinas at arm.com; will.deacon at arm.com; robh+dt at kernel.org;
> bhelgaas at google.com; mark.rutland at arm.com; olof at lixom.net;
> arnd at arndb.de; linux-arm-kernel at lists.infradead.org;
> lorenzo.pieralisi at arm.com; linux-kernel at vger.kernel.org; Linuxarm;
> devicetree at vger.kernel.org; linux-pci at vger.kernel.org; linux-
> serial at vger.kernel.org; minyard at acm.org; benh at kernel.crashing.org;
> zourongrong at gmail.com; John Garry; Gabriele Paoloni;
> zhichang.yuan02 at gmail.com; kantyzc at 163.com; xuwei (O)
> Subject: Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for
> special ISA
> 
> On Tue, Nov 08, 2016 at 11:47:08AM +0800, zhichang.yuan wrote:
> > This patch solves two issues:
> > 1) parse and get the right I/O range from DTS node whose parent does
> not
> > define the corresponding ranges property;
> >
> > 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 a fixup function, of_get_isa_indirect_io(). During the OF
> address
> > translation, this fixup will be called to check the 'reg' address to
> be
> > translating is for those sepcial ISA/LPC devices and get the I/O
> range
> > directly from the 'reg' property.
> >
> > 2) eliminate the I/O range conflict risk with PCI/PCIE leagecy I/O
> device;
> >
> > The current __of_address_to_resource() always translates the I/O
> range to PIO.
> > But this processing is not suitable for our ISA/LPC devices whose I/O
> range is
> > not cpu address(Arnd had stressed this in his comments on V2,V3
> patch-set).
> > Here, we bypass the mapping between cpu address and PIO for the
> special
> > ISA/LPC devices. But to drive these ISA/LPC devices, a I/O port
> address below
> > PCIBIOS_MIN_IO is needed by in*/out*(). Which means there is conflict
> risk
> > between I/O range of [0, PCIBIOS_MIN_IO) and PCI/PCIE legacy I/O
> range of [0,
> > IO_SPACE_LIMIT).
> > To avoid the I/O conflict, this patch reserve the I/O range below
> > PCIBIOS_MIN_IO.
> >
> > Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> > ---
> >  .../arm/hisilicon/hisilicon-low-pin-count.txt      | 31 ++++++++++++
> >  arch/arm64/include/asm/io.h                        |  6 +++
> >  arch/arm64/kernel/extio.c                          | 25 ++++++++++
> >  drivers/of/address.c                               | 56
> +++++++++++++++++++++-
> >  drivers/pci/pci.c                                  |  6 +--
> >  include/linux/of_address.h                         | 17 +++++++
> >  include/linux/pci.h                                |  8 ++++
> >  7 files changed, 145 insertions(+), 4 deletions(-)
> >  create mode 100644
> Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-
> count.txt
> >
> > diff --git
> a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-
> count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-
> low-pin-count.txt
> > new file mode 100644
> > index 0000000..13c8ddd
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-
> pin-count.txt
> > @@ -0,0 +1,31 @@
> > +Hisilicon Hip06 low-pin-count device
> > +  Usually LPC controller is part of PCI host bridge, so the legacy
> ISA ports
> > +  locate on LPC bus can be accessed direclty. But some SoCs have
> independent
> > +  LPC controller, and access the legacy ports by triggering LPC I/O
> cycles.
> > +  Hisilicon Hip06 implements this LPC device.
> > +
> > +Required properties:
> > +- compatible: should be "hisilicon,low-pin-count"
> > +- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
> > +- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
> > +- reg: base memory range where the register set of this device is
> mapped.
> > +
> > +Note:
> > +  The node name before '@' must be "isa" to represent the binding
> stick to the
> > +  ISA/EISA binding specification.
> > +
> > +Example:
> > +
> > +isa at a01b0000 {
> > +	compatible = "hisilicom,low-pin-count";
> > +	#address-cells = <2>;
> > +	#size-cells = <1>;
> > +	reg = <0x0 0xa01b0000 0x0 0x1000>;
> > +
> > +	ipmi0: bt at e4 {
> > +		compatible = "ipmi-bt";
> > +		device_type = "ipmi";
> > +		reg = <0x01 0xe4 0x04>;
> > +		status = "disabled";
> > +	};
> > +};
> 
> 
> This documentation file needs to be part of the next patch. It has
> nothing to do with
> what you are trying to fix here.

Yes you're right...we'll move it to next one

> 
> 
> > diff --git a/arch/arm64/include/asm/io.h
> b/arch/arm64/include/asm/io.h
> > index 136735d..c26b7cc 100644
> > --- a/arch/arm64/include/asm/io.h
> > +++ b/arch/arm64/include/asm/io.h
> > @@ -175,6 +175,12 @@ static inline u64 __raw_readq(const volatile
> void __iomem *addr)
> >  #define outsl outsl
> >
> >  DECLARE_EXTIO(l, u32)
> > +
> > +#define indirect_io_enabled indirect_io_enabled
> > +extern bool indirect_io_enabled(void);
> > +
> > +#define addr_is_indirect_io addr_is_indirect_io
> > +extern int addr_is_indirect_io(u64 taddr);
> >  #endif
> >
> >
> > diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> > index 647b3fa..3d45fa8 100644
> > --- a/arch/arm64/kernel/extio.c
> > +++ b/arch/arm64/kernel/extio.c
> > @@ -19,6 +19,31 @@
> >
> >  struct extio_ops *arm64_extio_ops;
> >
> > +/**
> > + * indirect_io_enabled - check whether indirectIO is enabled.
> > + *	arm64_extio_ops will be set only when indirectIO mechanism had
> been
> > + *	initialized.
> > + *
> > + * Returns true when indirectIO is enabled.
> > + */
> > +bool indirect_io_enabled(void)
> > +{
> > +	return arm64_extio_ops ? true : false;
> > +}
> > +
> > +/**
> > + * addr_is_indirect_io - check whether the input taddr is for
> indirectIO.
> > + * @taddr: the io address to be checked.
> > + *
> > + * Returns 1 when taddr is in the range; otherwise return 0.
> > + */
> > +int addr_is_indirect_io(u64 taddr)
> > +{
> > +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end <
> taddr)
> 
> start >= taddr ?

Nope... if  (taddr < arm64_extio_ops->start || taddr > arm64_extio_ops->end)
then taddr is outside the range [start; end] and will return 0; otherwise
it will return 1...

> 
> > +		return 0;
> > +
> > +	return 1;
> > +}
> >
> >  BUILD_EXTIO(b, u8)
> >
> > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > index 02b2903..cc2a05d 100644
> > --- a/drivers/of/address.c
> > +++ b/drivers/of/address.c
> > @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
> device_node *np)
> >  	return false;
> >  }
> >
> > +
> > +/*
> > + * of_isa_indirect_io - get the IO address from some isa reg
> property value.
> > + *	For some isa/lpc devices, no ranges property in ancestor node.
> > + *	The device addresses are described directly in their regs
> property.
> > + *	This fixup function will be called to get the IO address of
> isa/lpc
> > + *	devices when the normal of_translation failed.
> > + *
> > + * @parent:	points to the parent dts node;
> > + * @bus:		points to the of_bus which can be used to parse
> address;
> > + * @addr:	the address from reg property;
> > + * @na:		the address cell counter of @addr;
> > + * @presult:	store the address paresed from @addr;
> > + *
> > + * return 1 when successfully get the I/O address;
> > + * 0 will return for some failures.
> 
> Bah, you are returning a signed int, why 0 for failure? Return a
> negative value with
> error codes. Otherwise change the return value into a bool.

Yes we'll move to bool

> 
> > + */
> > +static int of_get_isa_indirect_io(struct device_node *parent,
> > +				struct of_bus *bus, __be32 *addr,
> > +				int na, u64 *presult)
> > +{
> > +	unsigned int flags;
> > +	unsigned int rlen;
> > +
> > +	/* whether support indirectIO */
> > +	if (!indirect_io_enabled())
> > +		return 0;
> > +
> > +	if (!of_bus_isa_match(parent))
> > +		return 0;
> > +
> > +	flags = bus->get_flags(addr);
> > +	if (!(flags & IORESOURCE_IO))
> > +		return 0;
> > +
> > +	/* there is ranges property, apply the normal translation
> directly. */
> 
> s/there is ranges/if we have a 'ranges'/

Thanks for spotting this

> 
> > +	if (of_get_property(parent, "ranges", &rlen))
> > +		return 0;
> > +
> > +	*presult = of_read_number(addr + 1, na - 1);
> > +	/* this fixup is only valid for specific I/O range. */
> > +	return addr_is_indirect_io(*presult);
> > +}
> > +
> >  static int of_translate_one(struct device_node *parent, struct
> of_bus *bus,
> >  			    struct of_bus *pbus, __be32 *addr,
> >  			    int na, int ns, int pna, const char *rprop)
> > @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
> device_node *dev,
> >  			result = of_read_number(addr, na);
> >  			break;
> >  		}
> > +		/*
> > +		 * For indirectIO device which has no ranges property, get
> > +		 * the address from reg directly.
> > +		 */
> > +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> > +			pr_debug("isa indirectIO matched(%s)..addr =
> 0x%llx\n",
> > +				of_node_full_name(dev), result);
> > +			break;
> > +		}
> >
> >  		/* Get new parent bus and counts */
> >  		pbus = of_match_bus(parent);
> > @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
> device_node *dev,
> >  	if (taddr == OF_BAD_ADDR)
> >  		return -EINVAL;
> >  	memset(r, 0, sizeof(struct resource));
> > -	if (flags & IORESOURCE_IO) {
> > +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
> >  		unsigned long port;
> > +
> >  		port = pci_address_to_pio(taddr);
> >  		if (port == (unsigned long)-1)
> >  			return -EINVAL;
> > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > index ba34907..1a08511 100644
> > --- a/drivers/pci/pci.c
> > +++ b/drivers/pci/pci.c
> > @@ -3263,7 +3263,7 @@ 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;
> > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> >
> >  	/* check if the range hasn't been previously recorded */
> >  	spin_lock(&io_range_lock);
> > @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long
> pio)
> >
> >  #ifdef PCI_IOBASE
> >  	struct io_range *range;
> > -	resource_size_t allocated_size = 0;
> > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> 
> Have you checked that pci_pio_to_address still returns valid values
> after this? I know that
> you are trying to take into account PCIBIOS_MIN_IO limit when
> allocating reserving the IO ranges,
> but the values added in the io_range_list are still starting from zero,
> no from PCIBIOS_MIN_IO,

I think you're wrong here as in pci_address_to_pio we have:
+	resource_size_t offset = PCIBIOS_MIN_IO;

This should be enough to guarantee that the PIOs start at
PCIBIOS_MIN_IO...right?


> so the calculation of the address in this function could return
> negative values casted to pci_addr_t.
> 
> Maybe you want to adjust the range->start value in
> pci_register_io_range() as well to have it
> offset by PCIBIOS_MIN_IO as well.
> 
> Best regards,
> Liviu
> 
> >
> >  	if (pio > IO_SPACE_LIMIT)
> >  		return address;
> > @@ -3335,7 +3335,7 @@ unsigned long __weak
> pci_address_to_pio(phys_addr_t address)
> >  {
> >  #ifdef PCI_IOBASE
> >  	struct io_range *res;
> > -	resource_size_t offset = 0;
> > +	resource_size_t offset = PCIBIOS_MIN_IO;
> >  	unsigned long addr = -1;
> >
> >  	spin_lock(&io_range_lock);
> > diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> > index 3786473..deec469 100644
> > --- a/include/linux/of_address.h
> > +++ b/include/linux/of_address.h
> > @@ -24,6 +24,23 @@ struct of_pci_range {
> >  #define for_each_of_pci_range(parser, range) \
> >  	for (; of_pci_range_parser_one(parser, range);)
> >
> > +
> > +#ifndef indirect_io_enabled
> > +#define indirect_io_enabled indirect_io_enabled
> > +static inline bool indirect_io_enabled(void)
> > +{
> > +	return false;
> > +}
> > +#endif
> > +
> > +#ifndef addr_is_indirect_io
> > +#define addr_is_indirect_io addr_is_indirect_io
> > +static inline int addr_is_indirect_io(u64 taddr)
> > +{
> > +	return 0;
> > +}
> > +#endif
> > +
> >  /* Translate a DMA address from device space to CPU space */
> >  extern u64 of_translate_dma_address(struct device_node *dev,
> >  				    const __be32 *in_addr);
> > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > index 0e49f70..7f6bbb6 100644
> > --- a/include/linux/pci.h
> > +++ b/include/linux/pci.h
> > @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
> pci_bus *bus)
> >  /* provide the legacy pci_dma_* API */
> >  #include <linux/pci-dma-compat.h>
> >
> > +/*
> > + * define this macro here to refrain from compilation error for some
> > + * platforms. Please keep this macro at the end of this header file.
> > + */
> > +#ifndef PCIBIOS_MIN_IO
> > +#define PCIBIOS_MIN_IO		0
> > +#endif
> > +
> >  #endif /* LINUX_PCI_H */
> > --
> > 1.9.1
> >
> > --
> > 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] 286+ messages in thread

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
  2016-11-09 16:16       ` Gabriele Paoloni
  (?)
  (?)
@ 2016-11-09 16:50         ` liviu.dudau-5wv7dgnIgG8
  -1 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau @ 2016-11-09 16:50 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Yuanzhichang, catalin.marinas, will.deacon, robh+dt, bhelgaas,
	mark.rutland, olof, arnd, linux-arm-kernel, lorenzo.pieralisi,
	linux-kernel, Linuxarm, devicetree, linux-pci, linux-serial,
	minyard, benh, zourongrong, John Garry, zhichang.yuan02, kantyzc,
	xuwei (O)

On Wed, Nov 09, 2016 at 04:16:17PM +0000, Gabriele Paoloni wrote:
> Hi Liviu
> 
> Thanks for reviewing
> 

[removed some irrelevant part of discussion, avoid crazy formatting]

> > > +/**
> > > + * addr_is_indirect_io - check whether the input taddr is for
> > indirectIO.
> > > + * @taddr: the io address to be checked.
> > > + *
> > > + * Returns 1 when taddr is in the range; otherwise return 0.
> > > + */
> > > +int addr_is_indirect_io(u64 taddr)
> > > +{
> > > +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end <
> > taddr)
> > 
> > start >= taddr ?
> 
> Nope... if  (taddr < arm64_extio_ops->start || taddr > arm64_extio_ops->end)
> then taddr is outside the range [start; end] and will return 0; otherwise
> it will return 1...

Oops, sorry, did not pay attention to the returned value. The check is
correct as it is, no need to change then.

> 
> > 
> > > +		return 0;
> > > +
> > > +	return 1;
> > > +}
> > >
> > >  BUILD_EXTIO(b, u8)
> > >
> > > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > > index 02b2903..cc2a05d 100644
> > > --- a/drivers/of/address.c
> > > +++ b/drivers/of/address.c
> > > @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
> > device_node *np)
> > >  	return false;
> > >  }
> > >
> > > +
> > > +/*
> > > + * of_isa_indirect_io - get the IO address from some isa reg
> > property value.
> > > + *	For some isa/lpc devices, no ranges property in ancestor node.
> > > + *	The device addresses are described directly in their regs
> > property.
> > > + *	This fixup function will be called to get the IO address of
> > isa/lpc
> > > + *	devices when the normal of_translation failed.
> > > + *
> > > + * @parent:	points to the parent dts node;
> > > + * @bus:		points to the of_bus which can be used to parse
> > address;
> > > + * @addr:	the address from reg property;
> > > + * @na:		the address cell counter of @addr;
> > > + * @presult:	store the address paresed from @addr;
> > > + *
> > > + * return 1 when successfully get the I/O address;
> > > + * 0 will return for some failures.
> > 
> > Bah, you are returning a signed int, why 0 for failure? Return a
> > negative value with
> > error codes. Otherwise change the return value into a bool.
> 
> Yes we'll move to bool
> 
> > 
> > > + */
> > > +static int of_get_isa_indirect_io(struct device_node *parent,
> > > +				struct of_bus *bus, __be32 *addr,
> > > +				int na, u64 *presult)
> > > +{
> > > +	unsigned int flags;
> > > +	unsigned int rlen;
> > > +
> > > +	/* whether support indirectIO */
> > > +	if (!indirect_io_enabled())
> > > +		return 0;
> > > +
> > > +	if (!of_bus_isa_match(parent))
> > > +		return 0;
> > > +
> > > +	flags = bus->get_flags(addr);
> > > +	if (!(flags & IORESOURCE_IO))
> > > +		return 0;
> > > +
> > > +	/* there is ranges property, apply the normal translation
> > directly. */
> > 
> > s/there is ranges/if we have a 'ranges'/
> 
> Thanks for spotting this
> 
> > 
> > > +	if (of_get_property(parent, "ranges", &rlen))
> > > +		return 0;
> > > +
> > > +	*presult = of_read_number(addr + 1, na - 1);
> > > +	/* this fixup is only valid for specific I/O range. */
> > > +	return addr_is_indirect_io(*presult);
> > > +}
> > > +
> > >  static int of_translate_one(struct device_node *parent, struct
> > of_bus *bus,
> > >  			    struct of_bus *pbus, __be32 *addr,
> > >  			    int na, int ns, int pna, const char *rprop)
> > > @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
> > device_node *dev,
> > >  			result = of_read_number(addr, na);
> > >  			break;
> > >  		}
> > > +		/*
> > > +		 * For indirectIO device which has no ranges property, get
> > > +		 * the address from reg directly.
> > > +		 */
> > > +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> > > +			pr_debug("isa indirectIO matched(%s)..addr =
> > 0x%llx\n",
> > > +				of_node_full_name(dev), result);
> > > +			break;
> > > +		}
> > >
> > >  		/* Get new parent bus and counts */
> > >  		pbus = of_match_bus(parent);
> > > @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
> > device_node *dev,
> > >  	if (taddr == OF_BAD_ADDR)
> > >  		return -EINVAL;
> > >  	memset(r, 0, sizeof(struct resource));
> > > -	if (flags & IORESOURCE_IO) {
> > > +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
> > >  		unsigned long port;
> > > +
> > >  		port = pci_address_to_pio(taddr);
> > >  		if (port == (unsigned long)-1)
> > >  			return -EINVAL;
> > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > > index ba34907..1a08511 100644
> > > --- a/drivers/pci/pci.c
> > > +++ b/drivers/pci/pci.c
> > > @@ -3263,7 +3263,7 @@ 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;
> > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > >
> > >  	/* check if the range hasn't been previously recorded */
> > >  	spin_lock(&io_range_lock);
> > > @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long
> > pio)
> > >
> > >  #ifdef PCI_IOBASE
> > >  	struct io_range *range;
> > > -	resource_size_t allocated_size = 0;
> > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > 
> > Have you checked that pci_pio_to_address still returns valid values
> > after this? I know that
> > you are trying to take into account PCIBIOS_MIN_IO limit when
> > allocating reserving the IO ranges,
> > but the values added in the io_range_list are still starting from zero,
> > no from PCIBIOS_MIN_IO,
> 
> I think you're wrong here as in pci_address_to_pio we have:
> +	resource_size_t offset = PCIBIOS_MIN_IO;
> 
> This should be enough to guarantee that the PIOs start at
> PCIBIOS_MIN_IO...right?

I don't think you can guarantee that the pio value that gets passed into
pci_pio_to_address() always comes from a previously returned value by
pci_address_to_pio(). Maybe you can add a check in pci_pio_to_address()

	if (pio < PCIBIOS_MIN_IO)
		return address;

to avoid adding more checks in the list_for_each_entry() loop.

Best regards,
Liviu

> 
> 
> > so the calculation of the address in this function could return
> > negative values casted to pci_addr_t.
> > 
> > Maybe you want to adjust the range->start value in
> > pci_register_io_range() as well to have it
> > offset by PCIBIOS_MIN_IO as well.
> > 
> > Best regards,
> > Liviu
> > 
> > >
> > >  	if (pio > IO_SPACE_LIMIT)
> > >  		return address;
> > > @@ -3335,7 +3335,7 @@ unsigned long __weak
> > pci_address_to_pio(phys_addr_t address)
> > >  {
> > >  #ifdef PCI_IOBASE
> > >  	struct io_range *res;
> > > -	resource_size_t offset = 0;
> > > +	resource_size_t offset = PCIBIOS_MIN_IO;
> > >  	unsigned long addr = -1;
> > >
> > >  	spin_lock(&io_range_lock);
> > > diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> > > index 3786473..deec469 100644
> > > --- a/include/linux/of_address.h
> > > +++ b/include/linux/of_address.h
> > > @@ -24,6 +24,23 @@ struct of_pci_range {
> > >  #define for_each_of_pci_range(parser, range) \
> > >  	for (; of_pci_range_parser_one(parser, range);)
> > >
> > > +
> > > +#ifndef indirect_io_enabled
> > > +#define indirect_io_enabled indirect_io_enabled
> > > +static inline bool indirect_io_enabled(void)
> > > +{
> > > +	return false;
> > > +}
> > > +#endif
> > > +
> > > +#ifndef addr_is_indirect_io
> > > +#define addr_is_indirect_io addr_is_indirect_io
> > > +static inline int addr_is_indirect_io(u64 taddr)
> > > +{
> > > +	return 0;
> > > +}
> > > +#endif
> > > +
> > >  /* Translate a DMA address from device space to CPU space */
> > >  extern u64 of_translate_dma_address(struct device_node *dev,
> > >  				    const __be32 *in_addr);
> > > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > > index 0e49f70..7f6bbb6 100644
> > > --- a/include/linux/pci.h
> > > +++ b/include/linux/pci.h
> > > @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
> > pci_bus *bus)
> > >  /* provide the legacy pci_dma_* API */
> > >  #include <linux/pci-dma-compat.h>
> > >
> > > +/*
> > > + * define this macro here to refrain from compilation error for some
> > > + * platforms. Please keep this macro at the end of this header file.
> > > + */
> > > +#ifndef PCIBIOS_MIN_IO
> > > +#define PCIBIOS_MIN_IO		0
> > > +#endif
> > > +
> > >  #endif /* LINUX_PCI_H */
> > > --
> > > 1.9.1
> > >
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-pci"
> > in
> > > the body of a message to majordomo@vger.kernel.org
> > > More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-09 16:50         ` liviu.dudau-5wv7dgnIgG8
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau-5wv7dgnIgG8 @ 2016-11-09 16:50 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Yuanzhichang, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, mark.rutland-5wv7dgnIgG8,
	olof-nZhT3qVonbNeoWH0uzbU5w, arnd-r2nGTMty4D4,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	lorenzo.pieralisi-5wv7dgnIgG8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Linuxarm,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	minyard-HInyCGIudOg@public.gmane.org

On Wed, Nov 09, 2016 at 04:16:17PM +0000, Gabriele Paoloni wrote:
> Hi Liviu
> 
> Thanks for reviewing
> 

[removed some irrelevant part of discussion, avoid crazy formatting]

> > > +/**
> > > + * addr_is_indirect_io - check whether the input taddr is for
> > indirectIO.
> > > + * @taddr: the io address to be checked.
> > > + *
> > > + * Returns 1 when taddr is in the range; otherwise return 0.
> > > + */
> > > +int addr_is_indirect_io(u64 taddr)
> > > +{
> > > +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end <
> > taddr)
> > 
> > start >= taddr ?
> 
> Nope... if  (taddr < arm64_extio_ops->start || taddr > arm64_extio_ops->end)
> then taddr is outside the range [start; end] and will return 0; otherwise
> it will return 1...

Oops, sorry, did not pay attention to the returned value. The check is
correct as it is, no need to change then.

> 
> > 
> > > +		return 0;
> > > +
> > > +	return 1;
> > > +}
> > >
> > >  BUILD_EXTIO(b, u8)
> > >
> > > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > > index 02b2903..cc2a05d 100644
> > > --- a/drivers/of/address.c
> > > +++ b/drivers/of/address.c
> > > @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
> > device_node *np)
> > >  	return false;
> > >  }
> > >
> > > +
> > > +/*
> > > + * of_isa_indirect_io - get the IO address from some isa reg
> > property value.
> > > + *	For some isa/lpc devices, no ranges property in ancestor node.
> > > + *	The device addresses are described directly in their regs
> > property.
> > > + *	This fixup function will be called to get the IO address of
> > isa/lpc
> > > + *	devices when the normal of_translation failed.
> > > + *
> > > + * @parent:	points to the parent dts node;
> > > + * @bus:		points to the of_bus which can be used to parse
> > address;
> > > + * @addr:	the address from reg property;
> > > + * @na:		the address cell counter of @addr;
> > > + * @presult:	store the address paresed from @addr;
> > > + *
> > > + * return 1 when successfully get the I/O address;
> > > + * 0 will return for some failures.
> > 
> > Bah, you are returning a signed int, why 0 for failure? Return a
> > negative value with
> > error codes. Otherwise change the return value into a bool.
> 
> Yes we'll move to bool
> 
> > 
> > > + */
> > > +static int of_get_isa_indirect_io(struct device_node *parent,
> > > +				struct of_bus *bus, __be32 *addr,
> > > +				int na, u64 *presult)
> > > +{
> > > +	unsigned int flags;
> > > +	unsigned int rlen;
> > > +
> > > +	/* whether support indirectIO */
> > > +	if (!indirect_io_enabled())
> > > +		return 0;
> > > +
> > > +	if (!of_bus_isa_match(parent))
> > > +		return 0;
> > > +
> > > +	flags = bus->get_flags(addr);
> > > +	if (!(flags & IORESOURCE_IO))
> > > +		return 0;
> > > +
> > > +	/* there is ranges property, apply the normal translation
> > directly. */
> > 
> > s/there is ranges/if we have a 'ranges'/
> 
> Thanks for spotting this
> 
> > 
> > > +	if (of_get_property(parent, "ranges", &rlen))
> > > +		return 0;
> > > +
> > > +	*presult = of_read_number(addr + 1, na - 1);
> > > +	/* this fixup is only valid for specific I/O range. */
> > > +	return addr_is_indirect_io(*presult);
> > > +}
> > > +
> > >  static int of_translate_one(struct device_node *parent, struct
> > of_bus *bus,
> > >  			    struct of_bus *pbus, __be32 *addr,
> > >  			    int na, int ns, int pna, const char *rprop)
> > > @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
> > device_node *dev,
> > >  			result = of_read_number(addr, na);
> > >  			break;
> > >  		}
> > > +		/*
> > > +		 * For indirectIO device which has no ranges property, get
> > > +		 * the address from reg directly.
> > > +		 */
> > > +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> > > +			pr_debug("isa indirectIO matched(%s)..addr =
> > 0x%llx\n",
> > > +				of_node_full_name(dev), result);
> > > +			break;
> > > +		}
> > >
> > >  		/* Get new parent bus and counts */
> > >  		pbus = of_match_bus(parent);
> > > @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
> > device_node *dev,
> > >  	if (taddr == OF_BAD_ADDR)
> > >  		return -EINVAL;
> > >  	memset(r, 0, sizeof(struct resource));
> > > -	if (flags & IORESOURCE_IO) {
> > > +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
> > >  		unsigned long port;
> > > +
> > >  		port = pci_address_to_pio(taddr);
> > >  		if (port == (unsigned long)-1)
> > >  			return -EINVAL;
> > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > > index ba34907..1a08511 100644
> > > --- a/drivers/pci/pci.c
> > > +++ b/drivers/pci/pci.c
> > > @@ -3263,7 +3263,7 @@ 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;
> > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > >
> > >  	/* check if the range hasn't been previously recorded */
> > >  	spin_lock(&io_range_lock);
> > > @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long
> > pio)
> > >
> > >  #ifdef PCI_IOBASE
> > >  	struct io_range *range;
> > > -	resource_size_t allocated_size = 0;
> > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > 
> > Have you checked that pci_pio_to_address still returns valid values
> > after this? I know that
> > you are trying to take into account PCIBIOS_MIN_IO limit when
> > allocating reserving the IO ranges,
> > but the values added in the io_range_list are still starting from zero,
> > no from PCIBIOS_MIN_IO,
> 
> I think you're wrong here as in pci_address_to_pio we have:
> +	resource_size_t offset = PCIBIOS_MIN_IO;
> 
> This should be enough to guarantee that the PIOs start at
> PCIBIOS_MIN_IO...right?

I don't think you can guarantee that the pio value that gets passed into
pci_pio_to_address() always comes from a previously returned value by
pci_address_to_pio(). Maybe you can add a check in pci_pio_to_address()

	if (pio < PCIBIOS_MIN_IO)
		return address;

to avoid adding more checks in the list_for_each_entry() loop.

Best regards,
Liviu

> 
> 
> > so the calculation of the address in this function could return
> > negative values casted to pci_addr_t.
> > 
> > Maybe you want to adjust the range->start value in
> > pci_register_io_range() as well to have it
> > offset by PCIBIOS_MIN_IO as well.
> > 
> > Best regards,
> > Liviu
> > 
> > >
> > >  	if (pio > IO_SPACE_LIMIT)
> > >  		return address;
> > > @@ -3335,7 +3335,7 @@ unsigned long __weak
> > pci_address_to_pio(phys_addr_t address)
> > >  {
> > >  #ifdef PCI_IOBASE
> > >  	struct io_range *res;
> > > -	resource_size_t offset = 0;
> > > +	resource_size_t offset = PCIBIOS_MIN_IO;
> > >  	unsigned long addr = -1;
> > >
> > >  	spin_lock(&io_range_lock);
> > > diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> > > index 3786473..deec469 100644
> > > --- a/include/linux/of_address.h
> > > +++ b/include/linux/of_address.h
> > > @@ -24,6 +24,23 @@ struct of_pci_range {
> > >  #define for_each_of_pci_range(parser, range) \
> > >  	for (; of_pci_range_parser_one(parser, range);)
> > >
> > > +
> > > +#ifndef indirect_io_enabled
> > > +#define indirect_io_enabled indirect_io_enabled
> > > +static inline bool indirect_io_enabled(void)
> > > +{
> > > +	return false;
> > > +}
> > > +#endif
> > > +
> > > +#ifndef addr_is_indirect_io
> > > +#define addr_is_indirect_io addr_is_indirect_io
> > > +static inline int addr_is_indirect_io(u64 taddr)
> > > +{
> > > +	return 0;
> > > +}
> > > +#endif
> > > +
> > >  /* Translate a DMA address from device space to CPU space */
> > >  extern u64 of_translate_dma_address(struct device_node *dev,
> > >  				    const __be32 *in_addr);
> > > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > > index 0e49f70..7f6bbb6 100644
> > > --- a/include/linux/pci.h
> > > +++ b/include/linux/pci.h
> > > @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
> > pci_bus *bus)
> > >  /* provide the legacy pci_dma_* API */
> > >  #include <linux/pci-dma-compat.h>
> > >
> > > +/*
> > > + * define this macro here to refrain from compilation error for some
> > > + * platforms. Please keep this macro at the end of this header file.
> > > + */
> > > +#ifndef PCIBIOS_MIN_IO
> > > +#define PCIBIOS_MIN_IO		0
> > > +#endif
> > > +
> > >  #endif /* LINUX_PCI_H */
> > > --
> > > 1.9.1
> > >
> > > --
> > > 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] 286+ messages in thread

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-09 16:50         ` liviu.dudau-5wv7dgnIgG8
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau @ 2016-11-09 16:50 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Yuanzhichang, catalin.marinas, will.deacon, robh+dt, bhelgaas,
	mark.rutland, olof, arnd, linux-arm-kernel, lorenzo.pieralisi,
	linux-kernel, Linuxarm, devicetree, linux-pci, linux-serial,
	minyard, benh, zourongrong, John Garry, zhichang.yuan02, kantyzc,
	xuwei (O)

On Wed, Nov 09, 2016 at 04:16:17PM +0000, Gabriele Paoloni wrote:
> Hi Liviu
> 
> Thanks for reviewing
> 

[removed some irrelevant part of discussion, avoid crazy formatting]

> > > +/**
> > > + * addr_is_indirect_io - check whether the input taddr is for
> > indirectIO.
> > > + * @taddr: the io address to be checked.
> > > + *
> > > + * Returns 1 when taddr is in the range; otherwise return 0.
> > > + */
> > > +int addr_is_indirect_io(u64 taddr)
> > > +{
> > > +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end <
> > taddr)
> > 
> > start >= taddr ?
> 
> Nope... if  (taddr < arm64_extio_ops->start || taddr > arm64_extio_ops->end)
> then taddr is outside the range [start; end] and will return 0; otherwise
> it will return 1...

Oops, sorry, did not pay attention to the returned value. The check is
correct as it is, no need to change then.

> 
> > 
> > > +		return 0;
> > > +
> > > +	return 1;
> > > +}
> > >
> > >  BUILD_EXTIO(b, u8)
> > >
> > > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > > index 02b2903..cc2a05d 100644
> > > --- a/drivers/of/address.c
> > > +++ b/drivers/of/address.c
> > > @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
> > device_node *np)
> > >  	return false;
> > >  }
> > >
> > > +
> > > +/*
> > > + * of_isa_indirect_io - get the IO address from some isa reg
> > property value.
> > > + *	For some isa/lpc devices, no ranges property in ancestor node.
> > > + *	The device addresses are described directly in their regs
> > property.
> > > + *	This fixup function will be called to get the IO address of
> > isa/lpc
> > > + *	devices when the normal of_translation failed.
> > > + *
> > > + * @parent:	points to the parent dts node;
> > > + * @bus:		points to the of_bus which can be used to parse
> > address;
> > > + * @addr:	the address from reg property;
> > > + * @na:		the address cell counter of @addr;
> > > + * @presult:	store the address paresed from @addr;
> > > + *
> > > + * return 1 when successfully get the I/O address;
> > > + * 0 will return for some failures.
> > 
> > Bah, you are returning a signed int, why 0 for failure? Return a
> > negative value with
> > error codes. Otherwise change the return value into a bool.
> 
> Yes we'll move to bool
> 
> > 
> > > + */
> > > +static int of_get_isa_indirect_io(struct device_node *parent,
> > > +				struct of_bus *bus, __be32 *addr,
> > > +				int na, u64 *presult)
> > > +{
> > > +	unsigned int flags;
> > > +	unsigned int rlen;
> > > +
> > > +	/* whether support indirectIO */
> > > +	if (!indirect_io_enabled())
> > > +		return 0;
> > > +
> > > +	if (!of_bus_isa_match(parent))
> > > +		return 0;
> > > +
> > > +	flags = bus->get_flags(addr);
> > > +	if (!(flags & IORESOURCE_IO))
> > > +		return 0;
> > > +
> > > +	/* there is ranges property, apply the normal translation
> > directly. */
> > 
> > s/there is ranges/if we have a 'ranges'/
> 
> Thanks for spotting this
> 
> > 
> > > +	if (of_get_property(parent, "ranges", &rlen))
> > > +		return 0;
> > > +
> > > +	*presult = of_read_number(addr + 1, na - 1);
> > > +	/* this fixup is only valid for specific I/O range. */
> > > +	return addr_is_indirect_io(*presult);
> > > +}
> > > +
> > >  static int of_translate_one(struct device_node *parent, struct
> > of_bus *bus,
> > >  			    struct of_bus *pbus, __be32 *addr,
> > >  			    int na, int ns, int pna, const char *rprop)
> > > @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
> > device_node *dev,
> > >  			result = of_read_number(addr, na);
> > >  			break;
> > >  		}
> > > +		/*
> > > +		 * For indirectIO device which has no ranges property, get
> > > +		 * the address from reg directly.
> > > +		 */
> > > +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> > > +			pr_debug("isa indirectIO matched(%s)..addr =
> > 0x%llx\n",
> > > +				of_node_full_name(dev), result);
> > > +			break;
> > > +		}
> > >
> > >  		/* Get new parent bus and counts */
> > >  		pbus = of_match_bus(parent);
> > > @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
> > device_node *dev,
> > >  	if (taddr == OF_BAD_ADDR)
> > >  		return -EINVAL;
> > >  	memset(r, 0, sizeof(struct resource));
> > > -	if (flags & IORESOURCE_IO) {
> > > +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
> > >  		unsigned long port;
> > > +
> > >  		port = pci_address_to_pio(taddr);
> > >  		if (port == (unsigned long)-1)
> > >  			return -EINVAL;
> > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > > index ba34907..1a08511 100644
> > > --- a/drivers/pci/pci.c
> > > +++ b/drivers/pci/pci.c
> > > @@ -3263,7 +3263,7 @@ 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;
> > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > >
> > >  	/* check if the range hasn't been previously recorded */
> > >  	spin_lock(&io_range_lock);
> > > @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long
> > pio)
> > >
> > >  #ifdef PCI_IOBASE
> > >  	struct io_range *range;
> > > -	resource_size_t allocated_size = 0;
> > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > 
> > Have you checked that pci_pio_to_address still returns valid values
> > after this? I know that
> > you are trying to take into account PCIBIOS_MIN_IO limit when
> > allocating reserving the IO ranges,
> > but the values added in the io_range_list are still starting from zero,
> > no from PCIBIOS_MIN_IO,
> 
> I think you're wrong here as in pci_address_to_pio we have:
> +	resource_size_t offset = PCIBIOS_MIN_IO;
> 
> This should be enough to guarantee that the PIOs start at
> PCIBIOS_MIN_IO...right?

I don't think you can guarantee that the pio value that gets passed into
pci_pio_to_address() always comes from a previously returned value by
pci_address_to_pio(). Maybe you can add a check in pci_pio_to_address()

	if (pio < PCIBIOS_MIN_IO)
		return address;

to avoid adding more checks in the list_for_each_entry() loop.

Best regards,
Liviu

> 
> 
> > so the calculation of the address in this function could return
> > negative values casted to pci_addr_t.
> > 
> > Maybe you want to adjust the range->start value in
> > pci_register_io_range() as well to have it
> > offset by PCIBIOS_MIN_IO as well.
> > 
> > Best regards,
> > Liviu
> > 
> > >
> > >  	if (pio > IO_SPACE_LIMIT)
> > >  		return address;
> > > @@ -3335,7 +3335,7 @@ unsigned long __weak
> > pci_address_to_pio(phys_addr_t address)
> > >  {
> > >  #ifdef PCI_IOBASE
> > >  	struct io_range *res;
> > > -	resource_size_t offset = 0;
> > > +	resource_size_t offset = PCIBIOS_MIN_IO;
> > >  	unsigned long addr = -1;
> > >
> > >  	spin_lock(&io_range_lock);
> > > diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> > > index 3786473..deec469 100644
> > > --- a/include/linux/of_address.h
> > > +++ b/include/linux/of_address.h
> > > @@ -24,6 +24,23 @@ struct of_pci_range {
> > >  #define for_each_of_pci_range(parser, range) \
> > >  	for (; of_pci_range_parser_one(parser, range);)
> > >
> > > +
> > > +#ifndef indirect_io_enabled
> > > +#define indirect_io_enabled indirect_io_enabled
> > > +static inline bool indirect_io_enabled(void)
> > > +{
> > > +	return false;
> > > +}
> > > +#endif
> > > +
> > > +#ifndef addr_is_indirect_io
> > > +#define addr_is_indirect_io addr_is_indirect_io
> > > +static inline int addr_is_indirect_io(u64 taddr)
> > > +{
> > > +	return 0;
> > > +}
> > > +#endif
> > > +
> > >  /* Translate a DMA address from device space to CPU space */
> > >  extern u64 of_translate_dma_address(struct device_node *dev,
> > >  				    const __be32 *in_addr);
> > > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > > index 0e49f70..7f6bbb6 100644
> > > --- a/include/linux/pci.h
> > > +++ b/include/linux/pci.h
> > > @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
> > pci_bus *bus)
> > >  /* provide the legacy pci_dma_* API */
> > >  #include <linux/pci-dma-compat.h>
> > >
> > > +/*
> > > + * define this macro here to refrain from compilation error for some
> > > + * platforms. Please keep this macro at the end of this header file.
> > > + */
> > > +#ifndef PCIBIOS_MIN_IO
> > > +#define PCIBIOS_MIN_IO		0
> > > +#endif
> > > +
> > >  #endif /* LINUX_PCI_H */
> > > --
> > > 1.9.1
> > >
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-pci"
> > in
> > > the body of a message to majordomo@vger.kernel.org
> > > More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

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

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-09 16:50         ` liviu.dudau-5wv7dgnIgG8
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau at arm.com @ 2016-11-09 16:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Nov 09, 2016 at 04:16:17PM +0000, Gabriele Paoloni wrote:
> Hi Liviu
> 
> Thanks for reviewing
> 

[removed some irrelevant part of discussion, avoid crazy formatting]

> > > +/**
> > > + * addr_is_indirect_io - check whether the input taddr is for
> > indirectIO.
> > > + * @taddr: the io address to be checked.
> > > + *
> > > + * Returns 1 when taddr is in the range; otherwise return 0.
> > > + */
> > > +int addr_is_indirect_io(u64 taddr)
> > > +{
> > > +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end <
> > taddr)
> > 
> > start >= taddr ?
> 
> Nope... if  (taddr < arm64_extio_ops->start || taddr > arm64_extio_ops->end)
> then taddr is outside the range [start; end] and will return 0; otherwise
> it will return 1...

Oops, sorry, did not pay attention to the returned value. The check is
correct as it is, no need to change then.

> 
> > 
> > > +		return 0;
> > > +
> > > +	return 1;
> > > +}
> > >
> > >  BUILD_EXTIO(b, u8)
> > >
> > > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > > index 02b2903..cc2a05d 100644
> > > --- a/drivers/of/address.c
> > > +++ b/drivers/of/address.c
> > > @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
> > device_node *np)
> > >  	return false;
> > >  }
> > >
> > > +
> > > +/*
> > > + * of_isa_indirect_io - get the IO address from some isa reg
> > property value.
> > > + *	For some isa/lpc devices, no ranges property in ancestor node.
> > > + *	The device addresses are described directly in their regs
> > property.
> > > + *	This fixup function will be called to get the IO address of
> > isa/lpc
> > > + *	devices when the normal of_translation failed.
> > > + *
> > > + * @parent:	points to the parent dts node;
> > > + * @bus:		points to the of_bus which can be used to parse
> > address;
> > > + * @addr:	the address from reg property;
> > > + * @na:		the address cell counter of @addr;
> > > + * @presult:	store the address paresed from @addr;
> > > + *
> > > + * return 1 when successfully get the I/O address;
> > > + * 0 will return for some failures.
> > 
> > Bah, you are returning a signed int, why 0 for failure? Return a
> > negative value with
> > error codes. Otherwise change the return value into a bool.
> 
> Yes we'll move to bool
> 
> > 
> > > + */
> > > +static int of_get_isa_indirect_io(struct device_node *parent,
> > > +				struct of_bus *bus, __be32 *addr,
> > > +				int na, u64 *presult)
> > > +{
> > > +	unsigned int flags;
> > > +	unsigned int rlen;
> > > +
> > > +	/* whether support indirectIO */
> > > +	if (!indirect_io_enabled())
> > > +		return 0;
> > > +
> > > +	if (!of_bus_isa_match(parent))
> > > +		return 0;
> > > +
> > > +	flags = bus->get_flags(addr);
> > > +	if (!(flags & IORESOURCE_IO))
> > > +		return 0;
> > > +
> > > +	/* there is ranges property, apply the normal translation
> > directly. */
> > 
> > s/there is ranges/if we have a 'ranges'/
> 
> Thanks for spotting this
> 
> > 
> > > +	if (of_get_property(parent, "ranges", &rlen))
> > > +		return 0;
> > > +
> > > +	*presult = of_read_number(addr + 1, na - 1);
> > > +	/* this fixup is only valid for specific I/O range. */
> > > +	return addr_is_indirect_io(*presult);
> > > +}
> > > +
> > >  static int of_translate_one(struct device_node *parent, struct
> > of_bus *bus,
> > >  			    struct of_bus *pbus, __be32 *addr,
> > >  			    int na, int ns, int pna, const char *rprop)
> > > @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
> > device_node *dev,
> > >  			result = of_read_number(addr, na);
> > >  			break;
> > >  		}
> > > +		/*
> > > +		 * For indirectIO device which has no ranges property, get
> > > +		 * the address from reg directly.
> > > +		 */
> > > +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> > > +			pr_debug("isa indirectIO matched(%s)..addr =
> > 0x%llx\n",
> > > +				of_node_full_name(dev), result);
> > > +			break;
> > > +		}
> > >
> > >  		/* Get new parent bus and counts */
> > >  		pbus = of_match_bus(parent);
> > > @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
> > device_node *dev,
> > >  	if (taddr == OF_BAD_ADDR)
> > >  		return -EINVAL;
> > >  	memset(r, 0, sizeof(struct resource));
> > > -	if (flags & IORESOURCE_IO) {
> > > +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
> > >  		unsigned long port;
> > > +
> > >  		port = pci_address_to_pio(taddr);
> > >  		if (port == (unsigned long)-1)
> > >  			return -EINVAL;
> > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > > index ba34907..1a08511 100644
> > > --- a/drivers/pci/pci.c
> > > +++ b/drivers/pci/pci.c
> > > @@ -3263,7 +3263,7 @@ 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;
> > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > >
> > >  	/* check if the range hasn't been previously recorded */
> > >  	spin_lock(&io_range_lock);
> > > @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long
> > pio)
> > >
> > >  #ifdef PCI_IOBASE
> > >  	struct io_range *range;
> > > -	resource_size_t allocated_size = 0;
> > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > 
> > Have you checked that pci_pio_to_address still returns valid values
> > after this? I know that
> > you are trying to take into account PCIBIOS_MIN_IO limit when
> > allocating reserving the IO ranges,
> > but the values added in the io_range_list are still starting from zero,
> > no from PCIBIOS_MIN_IO,
> 
> I think you're wrong here as in pci_address_to_pio we have:
> +	resource_size_t offset = PCIBIOS_MIN_IO;
> 
> This should be enough to guarantee that the PIOs start at
> PCIBIOS_MIN_IO...right?

I don't think you can guarantee that the pio value that gets passed into
pci_pio_to_address() always comes from a previously returned value by
pci_address_to_pio(). Maybe you can add a check in pci_pio_to_address()

	if (pio < PCIBIOS_MIN_IO)
		return address;

to avoid adding more checks in the list_for_each_entry() loop.

Best regards,
Liviu

> 
> 
> > so the calculation of the address in this function could return
> > negative values casted to pci_addr_t.
> > 
> > Maybe you want to adjust the range->start value in
> > pci_register_io_range() as well to have it
> > offset by PCIBIOS_MIN_IO as well.
> > 
> > Best regards,
> > Liviu
> > 
> > >
> > >  	if (pio > IO_SPACE_LIMIT)
> > >  		return address;
> > > @@ -3335,7 +3335,7 @@ unsigned long __weak
> > pci_address_to_pio(phys_addr_t address)
> > >  {
> > >  #ifdef PCI_IOBASE
> > >  	struct io_range *res;
> > > -	resource_size_t offset = 0;
> > > +	resource_size_t offset = PCIBIOS_MIN_IO;
> > >  	unsigned long addr = -1;
> > >
> > >  	spin_lock(&io_range_lock);
> > > diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> > > index 3786473..deec469 100644
> > > --- a/include/linux/of_address.h
> > > +++ b/include/linux/of_address.h
> > > @@ -24,6 +24,23 @@ struct of_pci_range {
> > >  #define for_each_of_pci_range(parser, range) \
> > >  	for (; of_pci_range_parser_one(parser, range);)
> > >
> > > +
> > > +#ifndef indirect_io_enabled
> > > +#define indirect_io_enabled indirect_io_enabled
> > > +static inline bool indirect_io_enabled(void)
> > > +{
> > > +	return false;
> > > +}
> > > +#endif
> > > +
> > > +#ifndef addr_is_indirect_io
> > > +#define addr_is_indirect_io addr_is_indirect_io
> > > +static inline int addr_is_indirect_io(u64 taddr)
> > > +{
> > > +	return 0;
> > > +}
> > > +#endif
> > > +
> > >  /* Translate a DMA address from device space to CPU space */
> > >  extern u64 of_translate_dma_address(struct device_node *dev,
> > >  				    const __be32 *in_addr);
> > > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > > index 0e49f70..7f6bbb6 100644
> > > --- a/include/linux/pci.h
> > > +++ b/include/linux/pci.h
> > > @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
> > pci_bus *bus)
> > >  /* provide the legacy pci_dma_* API */
> > >  #include <linux/pci-dma-compat.h>
> > >
> > > +/*
> > > + * define this macro here to refrain from compilation error for some
> > > + * platforms. Please keep this macro at the end of this header file.
> > > + */
> > > +#ifndef PCIBIOS_MIN_IO
> > > +#define PCIBIOS_MIN_IO		0
> > > +#endif
> > > +
> > >  #endif /* LINUX_PCI_H */
> > > --
> > > 1.9.1
> > >
> > > --
> > > 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] 286+ messages in thread

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-11-09 11:29             ` John Garry
  (?)
@ 2016-11-09 21:33               ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-09 21:33 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: John Garry, mark.rutland, devicetree, lorenzo.pieralisi, benh,
	minyard, gabriele.paoloni, catalin.marinas, zhichang.yuan02,
	liviu.dudau, linuxarm, Will Deacon, linux-kernel, zourongrong,
	bhelgaas, robh+dt, xuwei5, linux-serial, linux-pci, olof,
	kantyzc, zhichang.yuan

On Wednesday, November 9, 2016 11:29:46 AM CET John Garry wrote:
> On 08/11/2016 22:35, Arnd Bergmann wrote:
> > On Tuesday, November 8, 2016 4:49:49 PM CET Will Deacon wrote:
> >> On Tue, Nov 08, 2016 at 04:33:44PM +0000, John Garry wrote:
> >>> On 08/11/2016 16:12, Will Deacon wrote:
> >>>> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> >
> >>>> Is there no way to make this slightly more generic, so that it can be
> >>>> re-used elsewhere? For example, if struct extio_ops was common, then
> >>>> you could have the singleton (which maybe should be an interval tree?),
> >>>> type definition, setter function and the BUILD_EXTIO invocations
> >>>> somewhere generic, rather than squirelled away in the arch backend.
> >>>>
> >>> The concern would be that some architecture which uses generic higher-level
> >>> ISA accessor ops, but have IO space, could be affected.
> >>
> >> You're already adding a Kconfig symbol for this stuff, so you can keep
> >> that if you don't want it on other architectures. I'm just arguing that
> >> plumbing drivers directly into arch code via arm64_set_extops is not
> >> something I'm particularly fond of, especially when it looks like it
> >> could be avoided with a small amount of effort.
> >
> > Agreed, I initially suggested putting this into arch/arm64/, but there isn't
> > really a reason why it couldn't just live in lib/ with the header file
> > bits moved to include/asm-generic/io.h which we already use.
> >
> 
> Right, Zhichang will check the logistics of this. The generic io.h is 
> quite clean, so as long as you don't mind new build switches of this 
> nature being added, it should be ok; and we'll plan on moving extio.h 
> into include/asm-generic as well.

I think all we need is an #ifdef CONFIG_something around the existing
defintion, with the alternative being "extern" declarations, after that
all the interesting logic can sit in a file in lib/.

	Arnd

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-09 21:33               ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-09 21:33 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: mark.rutland, catalin.marinas, gabriele.paoloni, linux-pci,
	liviu.dudau, linuxarm, lorenzo.pieralisi, xuwei5, linux-serial,
	benh, devicetree, minyard, Will Deacon, John Garry, olof,
	robh+dt, bhelgaas, kantyzc, zhichang.yuan02, linux-kernel,
	zhichang.yuan, zourongrong

On Wednesday, November 9, 2016 11:29:46 AM CET John Garry wrote:
> On 08/11/2016 22:35, Arnd Bergmann wrote:
> > On Tuesday, November 8, 2016 4:49:49 PM CET Will Deacon wrote:
> >> On Tue, Nov 08, 2016 at 04:33:44PM +0000, John Garry wrote:
> >>> On 08/11/2016 16:12, Will Deacon wrote:
> >>>> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> >
> >>>> Is there no way to make this slightly more generic, so that it can be
> >>>> re-used elsewhere? For example, if struct extio_ops was common, then
> >>>> you could have the singleton (which maybe should be an interval tree?),
> >>>> type definition, setter function and the BUILD_EXTIO invocations
> >>>> somewhere generic, rather than squirelled away in the arch backend.
> >>>>
> >>> The concern would be that some architecture which uses generic higher-level
> >>> ISA accessor ops, but have IO space, could be affected.
> >>
> >> You're already adding a Kconfig symbol for this stuff, so you can keep
> >> that if you don't want it on other architectures. I'm just arguing that
> >> plumbing drivers directly into arch code via arm64_set_extops is not
> >> something I'm particularly fond of, especially when it looks like it
> >> could be avoided with a small amount of effort.
> >
> > Agreed, I initially suggested putting this into arch/arm64/, but there isn't
> > really a reason why it couldn't just live in lib/ with the header file
> > bits moved to include/asm-generic/io.h which we already use.
> >
> 
> Right, Zhichang will check the logistics of this. The generic io.h is 
> quite clean, so as long as you don't mind new build switches of this 
> nature being added, it should be ok; and we'll plan on moving extio.h 
> into include/asm-generic as well.

I think all we need is an #ifdef CONFIG_something around the existing
defintion, with the alternative being "extern" declarations, after that
all the interesting logic can sit in a file in lib/.

	Arnd


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-09 21:33               ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-09 21:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday, November 9, 2016 11:29:46 AM CET John Garry wrote:
> On 08/11/2016 22:35, Arnd Bergmann wrote:
> > On Tuesday, November 8, 2016 4:49:49 PM CET Will Deacon wrote:
> >> On Tue, Nov 08, 2016 at 04:33:44PM +0000, John Garry wrote:
> >>> On 08/11/2016 16:12, Will Deacon wrote:
> >>>> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> >
> >>>> Is there no way to make this slightly more generic, so that it can be
> >>>> re-used elsewhere? For example, if struct extio_ops was common, then
> >>>> you could have the singleton (which maybe should be an interval tree?),
> >>>> type definition, setter function and the BUILD_EXTIO invocations
> >>>> somewhere generic, rather than squirelled away in the arch backend.
> >>>>
> >>> The concern would be that some architecture which uses generic higher-level
> >>> ISA accessor ops, but have IO space, could be affected.
> >>
> >> You're already adding a Kconfig symbol for this stuff, so you can keep
> >> that if you don't want it on other architectures. I'm just arguing that
> >> plumbing drivers directly into arch code via arm64_set_extops is not
> >> something I'm particularly fond of, especially when it looks like it
> >> could be avoided with a small amount of effort.
> >
> > Agreed, I initially suggested putting this into arch/arm64/, but there isn't
> > really a reason why it couldn't just live in lib/ with the header file
> > bits moved to include/asm-generic/io.h which we already use.
> >
> 
> Right, Zhichang will check the logistics of this. The generic io.h is 
> quite clean, so as long as you don't mind new build switches of this 
> nature being added, it should be ok; and we'll plan on moving extio.h 
> into include/asm-generic as well.

I think all we need is an #ifdef CONFIG_something around the existing
defintion, with the alternative being "extern" declarations, after that
all the interesting logic can sit in a file in lib/.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-09 12:10       ` Gabriele Paoloni
  (?)
  (?)
@ 2016-11-09 21:34         ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-09 21:34 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Gabriele Paoloni, Yuanzhichang, mark.rutland, devicetree,
	lorenzo.pieralisi, benh, minyard, catalin.marinas, John Garry,
	will.deacon, linux-kernel, xuwei (O),
	Linuxarm, olof, robh+dt, zourongrong, linux-serial, linux-pci,
	bhelgaas, liviu.dudau, kantyzc, zhichang.yuan02

On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni wrote:
> > On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
> > > +       /*
> > > +        * The first PCIBIOS_MIN_IO is reserved specifically for
> > indirectIO.
> > > +        * It will separate indirectIO range from pci host bridge to
> > > +        * avoid the possible PIO conflict.
> > > +        * Set the indirectIO range directly here.
> > > +        */
> > > +       lpcdev->io_ops.start = 0;
> > > +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> > > +       lpcdev->io_ops.devpara = lpcdev;
> > > +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> > > +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> > > +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> > > +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
> > 
> > I have to look at patch 2 in more detail again, after missing a few
> > review
> > rounds. I'm still a bit skeptical about hardcoding a logical I/O port
> > range here, and would hope that we can just go through the same
> > assignment of logical port ranges that we have for PCI buses,
> > decoupling
> > the bus addresses from the linux-internal ones.
> 
> The point here is that we want to avoid any conflict/overlap between
> the LPC I/O space and the PCI I/O space. With the assignment above
> we make sure that LPC never interfere with PCI I/O space.

But we already abstract the PCI I/O space using dynamic registration.
There is no need to hardcode the logical address for ISA, though
I think we can hardcode the bus address to start at zero here.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-09 21:34         ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-09 21:34 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Gabriele Paoloni, Yuanzhichang, mark.rutland, devicetree,
	lorenzo.pieralisi, benh, minyard, catalin.marinas, John Garry,
	will.deacon, linux-kernel, xuwei (O),
	Linuxarm, olof, robh+dt, zourongrong

On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni wrote:
> > On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
> > > +       /*
> > > +        * The first PCIBIOS_MIN_IO is reserved specifically for
> > indirectIO.
> > > +        * It will separate indirectIO range from pci host bridge to
> > > +        * avoid the possible PIO conflict.
> > > +        * Set the indirectIO range directly here.
> > > +        */
> > > +       lpcdev->io_ops.start = 0;
> > > +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> > > +       lpcdev->io_ops.devpara = lpcdev;
> > > +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> > > +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> > > +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> > > +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
> > 
> > I have to look at patch 2 in more detail again, after missing a few
> > review
> > rounds. I'm still a bit skeptical about hardcoding a logical I/O port
> > range here, and would hope that we can just go through the same
> > assignment of logical port ranges that we have for PCI buses,
> > decoupling
> > the bus addresses from the linux-internal ones.
> 
> The point here is that we want to avoid any conflict/overlap between
> the LPC I/O space and the PCI I/O space. With the assignment above
> we make sure that LPC never interfere with PCI I/O space.

But we already abstract the PCI I/O space using dynamic registration.
There is no need to hardcode the logical address for ISA, though
I think we can hardcode the bus address to start at zero here.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-09 21:34         ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-09 21:34 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: mark.rutland, catalin.marinas, Gabriele Paoloni, linux-pci,
	will.deacon, Linuxarm, lorenzo.pieralisi, xuwei (O),
	linux-serial, benh, devicetree, minyard, liviu.dudau, John Garry,
	olof, robh+dt, bhelgaas, kantyzc, zhichang.yuan02, linux-kernel,
	Yuanzhichang, zourongrong

On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni wrote:
> > On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
> > > +       /*
> > > +        * The first PCIBIOS_MIN_IO is reserved specifically for
> > indirectIO.
> > > +        * It will separate indirectIO range from pci host bridge to
> > > +        * avoid the possible PIO conflict.
> > > +        * Set the indirectIO range directly here.
> > > +        */
> > > +       lpcdev->io_ops.start = 0;
> > > +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> > > +       lpcdev->io_ops.devpara = lpcdev;
> > > +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> > > +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> > > +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> > > +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
> > 
> > I have to look at patch 2 in more detail again, after missing a few
> > review
> > rounds. I'm still a bit skeptical about hardcoding a logical I/O port
> > range here, and would hope that we can just go through the same
> > assignment of logical port ranges that we have for PCI buses,
> > decoupling
> > the bus addresses from the linux-internal ones.
> 
> The point here is that we want to avoid any conflict/overlap between
> the LPC I/O space and the PCI I/O space. With the assignment above
> we make sure that LPC never interfere with PCI I/O space.

But we already abstract the PCI I/O space using dynamic registration.
There is no need to hardcode the logical address for ISA, though
I think we can hardcode the bus address to start at zero here.

	Arnd

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-09 21:34         ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-09 21:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni wrote:
> > On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
> > > +       /*
> > > +        * The first PCIBIOS_MIN_IO is reserved specifically for
> > indirectIO.
> > > +        * It will separate indirectIO range from pci host bridge to
> > > +        * avoid the possible PIO conflict.
> > > +        * Set the indirectIO range directly here.
> > > +        */
> > > +       lpcdev->io_ops.start = 0;
> > > +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> > > +       lpcdev->io_ops.devpara = lpcdev;
> > > +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> > > +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> > > +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> > > +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
> > 
> > I have to look at patch 2 in more detail again, after missing a few
> > review
> > rounds. I'm still a bit skeptical about hardcoding a logical I/O port
> > range here, and would hope that we can just go through the same
> > assignment of logical port ranges that we have for PCI buses,
> > decoupling
> > the bus addresses from the linux-internal ones.
> 
> The point here is that we want to avoid any conflict/overlap between
> the LPC I/O space and the PCI I/O space. With the assignment above
> we make sure that LPC never interfere with PCI I/O space.

But we already abstract the PCI I/O space using dynamic registration.
There is no need to hardcode the logical address for ISA, though
I think we can hardcode the bus address to start at zero here.

	Arnd

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
  2016-11-09 13:54         ` One Thousand Gnomes
  (?)
@ 2016-11-09 21:38           ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-09 21:38 UTC (permalink / raw)
  To: One Thousand Gnomes
  Cc: Mark Rutland, zhichang.yuan, catalin.marinas, will.deacon,
	robh+dt, bhelgaas, olof, linux-arm-kernel, lorenzo.pieralisi,
	linux-kernel, linuxarm, devicetree, linux-pci, linux-serial,
	minyard, benh, liviu.dudau, zourongrong, john.garry,
	gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5, marc.zyngier

On Wednesday, November 9, 2016 1:54:53 PM CET One Thousand Gnomes wrote:
> > I think it is a relatively safe assumption that there is only one
> > ISA bridge. A lot of old drivers hardcode PIO or memory addresses
> 
> It's not a safe assumption for x86 at least. There are a few systems with
> multiple ISA busses particularly older laptops with a docking station.

But do they have multiple ISA domains? There is no real harm in supporting
it, the (small) downsides I can think of are:

- a few extra cycles for the lookup, from possibly walking a linked list
  to find the correct set of helpers and MMIO addresses
- making it too general could invite more people to design hardware
  around the infrastructure when we really want them to stop adding
  stuff like this.

	Arnd

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-09 21:38           ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-09 21:38 UTC (permalink / raw)
  To: One Thousand Gnomes
  Cc: Mark Rutland, gabriele.paoloni, benh, will.deacon, linuxarm,
	lorenzo.pieralisi, xuwei5, linux-serial, catalin.marinas,
	devicetree, minyard, marc.zyngier, liviu.dudau, john.garry,
	zourongrong, robh+dt, bhelgaas, kantyzc, zhichang.yuan02,
	linux-arm-kernel, linux-pci, linux-kernel, zhichang.yuan, olof

On Wednesday, November 9, 2016 1:54:53 PM CET One Thousand Gnomes wrote:
> > I think it is a relatively safe assumption that there is only one
> > ISA bridge. A lot of old drivers hardcode PIO or memory addresses
> 
> It's not a safe assumption for x86 at least. There are a few systems with
> multiple ISA busses particularly older laptops with a docking station.

But do they have multiple ISA domains? There is no real harm in supporting
it, the (small) downsides I can think of are:

- a few extra cycles for the lookup, from possibly walking a linked list
  to find the correct set of helpers and MMIO addresses
- making it too general could invite more people to design hardware
  around the infrastructure when we really want them to stop adding
  stuff like this.

	Arnd

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-09 21:38           ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-09 21:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday, November 9, 2016 1:54:53 PM CET One Thousand Gnomes wrote:
> > I think it is a relatively safe assumption that there is only one
> > ISA bridge. A lot of old drivers hardcode PIO or memory addresses
> 
> It's not a safe assumption for x86 at least. There are a few systems with
> multiple ISA busses particularly older laptops with a docking station.

But do they have multiple ISA domains? There is no real harm in supporting
it, the (small) downsides I can think of are:

- a few extra cycles for the lookup, from possibly walking a linked list
  to find the correct set of helpers and MMIO addresses
- making it too general could invite more people to design hardware
  around the infrastructure when we really want them to stop adding
  stuff like this.

	Arnd

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
  2016-11-09 16:50         ` liviu.dudau-5wv7dgnIgG8
  (?)
  (?)
@ 2016-11-10  6:24           ` zhichang.yuan
  -1 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-10  6:24 UTC (permalink / raw)
  To: liviu.dudau, Gabriele Paoloni
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, mark.rutland,
	olof, arnd, linux-arm-kernel, lorenzo.pieralisi, linux-kernel,
	Linuxarm, devicetree, linux-pci, linux-serial, minyard, benh,
	zourongrong, John Garry, zhichang.yuan02, kantyzc, xuwei (O)

Hi,Liviu,

Thanks for your comments!


On 2016/11/10 0:50, liviu.dudau@arm.com wrote:
> On Wed, Nov 09, 2016 at 04:16:17PM +0000, Gabriele Paoloni wrote:
>> Hi Liviu
>>
>> Thanks for reviewing
>>
> 
> [removed some irrelevant part of discussion, avoid crazy formatting]
> 
>>>> +/**
>>>> + * addr_is_indirect_io - check whether the input taddr is for
>>> indirectIO.
>>>> + * @taddr: the io address to be checked.
>>>> + *
>>>> + * Returns 1 when taddr is in the range; otherwise return 0.
>>>> + */
>>>> +int addr_is_indirect_io(u64 taddr)
>>>> +{
>>>> +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end <
>>> taddr)
>>>
>>> start >= taddr ?
>>
>> Nope... if  (taddr < arm64_extio_ops->start || taddr > arm64_extio_ops->end)
>> then taddr is outside the range [start; end] and will return 0; otherwise
>> it will return 1...
> 
> Oops, sorry, did not pay attention to the returned value. The check is
> correct as it is, no need to change then.
> 
>>
>>>
>>>> +		return 0;
>>>> +
>>>> +	return 1;
>>>> +}
>>>>
>>>>  BUILD_EXTIO(b, u8)
>>>>
>>>> diff --git a/drivers/of/address.c b/drivers/of/address.c
>>>> index 02b2903..cc2a05d 100644
>>>> --- a/drivers/of/address.c
>>>> +++ b/drivers/of/address.c
>>>> @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
>>> device_node *np)
>>>>  	return false;
>>>>  }
>>>>
>>>> +
>>>> +/*
>>>> + * of_isa_indirect_io - get the IO address from some isa reg
>>> property value.
>>>> + *	For some isa/lpc devices, no ranges property in ancestor node.
>>>> + *	The device addresses are described directly in their regs
>>> property.
>>>> + *	This fixup function will be called to get the IO address of
>>> isa/lpc
>>>> + *	devices when the normal of_translation failed.
>>>> + *
>>>> + * @parent:	points to the parent dts node;
>>>> + * @bus:		points to the of_bus which can be used to parse
>>> address;
>>>> + * @addr:	the address from reg property;
>>>> + * @na:		the address cell counter of @addr;
>>>> + * @presult:	store the address paresed from @addr;
>>>> + *
>>>> + * return 1 when successfully get the I/O address;
>>>> + * 0 will return for some failures.
>>>
>>> Bah, you are returning a signed int, why 0 for failure? Return a
>>> negative value with
>>> error codes. Otherwise change the return value into a bool.
>>
>> Yes we'll move to bool
>>
>>>
>>>> + */
>>>> +static int of_get_isa_indirect_io(struct device_node *parent,
>>>> +				struct of_bus *bus, __be32 *addr,
>>>> +				int na, u64 *presult)
>>>> +{
>>>> +	unsigned int flags;
>>>> +	unsigned int rlen;
>>>> +
>>>> +	/* whether support indirectIO */
>>>> +	if (!indirect_io_enabled())
>>>> +		return 0;
>>>> +
>>>> +	if (!of_bus_isa_match(parent))
>>>> +		return 0;
>>>> +
>>>> +	flags = bus->get_flags(addr);
>>>> +	if (!(flags & IORESOURCE_IO))
>>>> +		return 0;
>>>> +
>>>> +	/* there is ranges property, apply the normal translation
>>> directly. */
>>>
>>> s/there is ranges/if we have a 'ranges'/
>>
>> Thanks for spotting this
>>
>>>
>>>> +	if (of_get_property(parent, "ranges", &rlen))
>>>> +		return 0;
>>>> +
>>>> +	*presult = of_read_number(addr + 1, na - 1);
>>>> +	/* this fixup is only valid for specific I/O range. */
>>>> +	return addr_is_indirect_io(*presult);
>>>> +}
>>>> +
>>>>  static int of_translate_one(struct device_node *parent, struct
>>> of_bus *bus,
>>>>  			    struct of_bus *pbus, __be32 *addr,
>>>>  			    int na, int ns, int pna, const char *rprop)
>>>> @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
>>> device_node *dev,
>>>>  			result = of_read_number(addr, na);
>>>>  			break;
>>>>  		}
>>>> +		/*
>>>> +		 * For indirectIO device which has no ranges property, get
>>>> +		 * the address from reg directly.
>>>> +		 */
>>>> +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
>>>> +			pr_debug("isa indirectIO matched(%s)..addr =
>>> 0x%llx\n",
>>>> +				of_node_full_name(dev), result);
>>>> +			break;
>>>> +		}
>>>>
>>>>  		/* Get new parent bus and counts */
>>>>  		pbus = of_match_bus(parent);
>>>> @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
>>> device_node *dev,
>>>>  	if (taddr == OF_BAD_ADDR)
>>>>  		return -EINVAL;
>>>>  	memset(r, 0, sizeof(struct resource));
>>>> -	if (flags & IORESOURCE_IO) {
>>>> +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
>>>>  		unsigned long port;
>>>> +
>>>>  		port = pci_address_to_pio(taddr);
>>>>  		if (port == (unsigned long)-1)
>>>>  			return -EINVAL;
>>>> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
>>>> index ba34907..1a08511 100644
>>>> --- a/drivers/pci/pci.c
>>>> +++ b/drivers/pci/pci.c
>>>> @@ -3263,7 +3263,7 @@ 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;
>>>> +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
>>>>
>>>>  	/* check if the range hasn't been previously recorded */
>>>>  	spin_lock(&io_range_lock);
>>>> @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long
>>> pio)
>>>>
>>>>  #ifdef PCI_IOBASE
>>>>  	struct io_range *range;
>>>> -	resource_size_t allocated_size = 0;
>>>> +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
>>>
>>> Have you checked that pci_pio_to_address still returns valid values
>>> after this? I know that
>>> you are trying to take into account PCIBIOS_MIN_IO limit when
>>> allocating reserving the IO ranges,
>>> but the values added in the io_range_list are still starting from zero,
>>> no from PCIBIOS_MIN_IO,
>>
>> I think you're wrong here as in pci_address_to_pio we have:
>> +	resource_size_t offset = PCIBIOS_MIN_IO;
>>
>> This should be enough to guarantee that the PIOs start at
>> PCIBIOS_MIN_IO...right?
> 
> I don't think you can guarantee that the pio value that gets passed into
> pci_pio_to_address() always comes from a previously returned value by
> pci_address_to_pio(). Maybe you can add a check in pci_pio_to_address()
> 
> 	if (pio < PCIBIOS_MIN_IO)
> 		return address;
> 
> to avoid adding more checks in the list_for_each_entry() loop.
> 

I will register some ranges to the list and test it later.

But from my understanding, pci_pio_to_address() should can return the right
original physical address.


According to the algorithm, the output PIO ranges are consecutive, just like this:


					input pio of pci_pio_to_address()
						|
						V
|----------------|--------------------------|------|-----------|
					    ^
					    |
					allocated_size is here


The change of this patch just make the start PIO from ZERO to PCIBIOS_MIN_IO.

in pci_pio_to_address(), for one input pio which fall into any PIO segment, the
return address will be:

address = range->start + pio - allocated_size;

Since allocated_size is the total range size of all IO ranges before the one
where pio belong, then (pio - allocated_size) is the offset to the range start,
So....


Thanks!
Zhichang

> Best regards,
> Liviu
> 
>>
>>
>>> so the calculation of the address in this function could return
>>> negative values casted to pci_addr_t.
>>>
>>> Maybe you want to adjust the range->start value in
>>> pci_register_io_range() as well to have it
>>> offset by PCIBIOS_MIN_IO as well.
>>>
>>> Best regards,
>>> Liviu
>>>
>>>>
>>>>  	if (pio > IO_SPACE_LIMIT)
>>>>  		return address;
>>>> @@ -3335,7 +3335,7 @@ unsigned long __weak
>>> pci_address_to_pio(phys_addr_t address)
>>>>  {
>>>>  #ifdef PCI_IOBASE
>>>>  	struct io_range *res;
>>>> -	resource_size_t offset = 0;
>>>> +	resource_size_t offset = PCIBIOS_MIN_IO;
>>>>  	unsigned long addr = -1;
>>>>
>>>>  	spin_lock(&io_range_lock);
>>>> diff --git a/include/linux/of_address.h b/include/linux/of_address.h
>>>> index 3786473..deec469 100644
>>>> --- a/include/linux/of_address.h
>>>> +++ b/include/linux/of_address.h
>>>> @@ -24,6 +24,23 @@ struct of_pci_range {
>>>>  #define for_each_of_pci_range(parser, range) \
>>>>  	for (; of_pci_range_parser_one(parser, range);)
>>>>
>>>> +
>>>> +#ifndef indirect_io_enabled
>>>> +#define indirect_io_enabled indirect_io_enabled
>>>> +static inline bool indirect_io_enabled(void)
>>>> +{
>>>> +	return false;
>>>> +}
>>>> +#endif
>>>> +
>>>> +#ifndef addr_is_indirect_io
>>>> +#define addr_is_indirect_io addr_is_indirect_io
>>>> +static inline int addr_is_indirect_io(u64 taddr)
>>>> +{
>>>> +	return 0;
>>>> +}
>>>> +#endif
>>>> +
>>>>  /* Translate a DMA address from device space to CPU space */
>>>>  extern u64 of_translate_dma_address(struct device_node *dev,
>>>>  				    const __be32 *in_addr);
>>>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>>>> index 0e49f70..7f6bbb6 100644
>>>> --- a/include/linux/pci.h
>>>> +++ b/include/linux/pci.h
>>>> @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
>>> pci_bus *bus)
>>>>  /* provide the legacy pci_dma_* API */
>>>>  #include <linux/pci-dma-compat.h>
>>>>
>>>> +/*
>>>> + * define this macro here to refrain from compilation error for some
>>>> + * platforms. Please keep this macro at the end of this header file.
>>>> + */
>>>> +#ifndef PCIBIOS_MIN_IO
>>>> +#define PCIBIOS_MIN_IO		0
>>>> +#endif
>>>> +
>>>>  #endif /* LINUX_PCI_H */
>>>> --
>>>> 1.9.1
>>>>
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-pci"
>>> in
>>>> the body of a message to majordomo@vger.kernel.org
>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-10  6:24           ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-10  6:24 UTC (permalink / raw)
  To: liviu.dudau, Gabriele Paoloni
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, mark.rutland,
	olof, arnd, linux-arm-kernel, lorenzo.pieralisi, linux-kernel,
	Linuxarm, devicetree, linux-pci, linux-serial, minyard, benh

Hi,Liviu,

Thanks for your comments!


On 2016/11/10 0:50, liviu.dudau@arm.com wrote:
> On Wed, Nov 09, 2016 at 04:16:17PM +0000, Gabriele Paoloni wrote:
>> Hi Liviu
>>
>> Thanks for reviewing
>>
> 
> [removed some irrelevant part of discussion, avoid crazy formatting]
> 
>>>> +/**
>>>> + * addr_is_indirect_io - check whether the input taddr is for
>>> indirectIO.
>>>> + * @taddr: the io address to be checked.
>>>> + *
>>>> + * Returns 1 when taddr is in the range; otherwise return 0.
>>>> + */
>>>> +int addr_is_indirect_io(u64 taddr)
>>>> +{
>>>> +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end <
>>> taddr)
>>>
>>> start >= taddr ?
>>
>> Nope... if  (taddr < arm64_extio_ops->start || taddr > arm64_extio_ops->end)
>> then taddr is outside the range [start; end] and will return 0; otherwise
>> it will return 1...
> 
> Oops, sorry, did not pay attention to the returned value. The check is
> correct as it is, no need to change then.
> 
>>
>>>
>>>> +		return 0;
>>>> +
>>>> +	return 1;
>>>> +}
>>>>
>>>>  BUILD_EXTIO(b, u8)
>>>>
>>>> diff --git a/drivers/of/address.c b/drivers/of/address.c
>>>> index 02b2903..cc2a05d 100644
>>>> --- a/drivers/of/address.c
>>>> +++ b/drivers/of/address.c
>>>> @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
>>> device_node *np)
>>>>  	return false;
>>>>  }
>>>>
>>>> +
>>>> +/*
>>>> + * of_isa_indirect_io - get the IO address from some isa reg
>>> property value.
>>>> + *	For some isa/lpc devices, no ranges property in ancestor node.
>>>> + *	The device addresses are described directly in their regs
>>> property.
>>>> + *	This fixup function will be called to get the IO address of
>>> isa/lpc
>>>> + *	devices when the normal of_translation failed.
>>>> + *
>>>> + * @parent:	points to the parent dts node;
>>>> + * @bus:		points to the of_bus which can be used to parse
>>> address;
>>>> + * @addr:	the address from reg property;
>>>> + * @na:		the address cell counter of @addr;
>>>> + * @presult:	store the address paresed from @addr;
>>>> + *
>>>> + * return 1 when successfully get the I/O address;
>>>> + * 0 will return for some failures.
>>>
>>> Bah, you are returning a signed int, why 0 for failure? Return a
>>> negative value with
>>> error codes. Otherwise change the return value into a bool.
>>
>> Yes we'll move to bool
>>
>>>
>>>> + */
>>>> +static int of_get_isa_indirect_io(struct device_node *parent,
>>>> +				struct of_bus *bus, __be32 *addr,
>>>> +				int na, u64 *presult)
>>>> +{
>>>> +	unsigned int flags;
>>>> +	unsigned int rlen;
>>>> +
>>>> +	/* whether support indirectIO */
>>>> +	if (!indirect_io_enabled())
>>>> +		return 0;
>>>> +
>>>> +	if (!of_bus_isa_match(parent))
>>>> +		return 0;
>>>> +
>>>> +	flags = bus->get_flags(addr);
>>>> +	if (!(flags & IORESOURCE_IO))
>>>> +		return 0;
>>>> +
>>>> +	/* there is ranges property, apply the normal translation
>>> directly. */
>>>
>>> s/there is ranges/if we have a 'ranges'/
>>
>> Thanks for spotting this
>>
>>>
>>>> +	if (of_get_property(parent, "ranges", &rlen))
>>>> +		return 0;
>>>> +
>>>> +	*presult = of_read_number(addr + 1, na - 1);
>>>> +	/* this fixup is only valid for specific I/O range. */
>>>> +	return addr_is_indirect_io(*presult);
>>>> +}
>>>> +
>>>>  static int of_translate_one(struct device_node *parent, struct
>>> of_bus *bus,
>>>>  			    struct of_bus *pbus, __be32 *addr,
>>>>  			    int na, int ns, int pna, const char *rprop)
>>>> @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
>>> device_node *dev,
>>>>  			result = of_read_number(addr, na);
>>>>  			break;
>>>>  		}
>>>> +		/*
>>>> +		 * For indirectIO device which has no ranges property, get
>>>> +		 * the address from reg directly.
>>>> +		 */
>>>> +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
>>>> +			pr_debug("isa indirectIO matched(%s)..addr =
>>> 0x%llx\n",
>>>> +				of_node_full_name(dev), result);
>>>> +			break;
>>>> +		}
>>>>
>>>>  		/* Get new parent bus and counts */
>>>>  		pbus = of_match_bus(parent);
>>>> @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
>>> device_node *dev,
>>>>  	if (taddr == OF_BAD_ADDR)
>>>>  		return -EINVAL;
>>>>  	memset(r, 0, sizeof(struct resource));
>>>> -	if (flags & IORESOURCE_IO) {
>>>> +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
>>>>  		unsigned long port;
>>>> +
>>>>  		port = pci_address_to_pio(taddr);
>>>>  		if (port == (unsigned long)-1)
>>>>  			return -EINVAL;
>>>> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
>>>> index ba34907..1a08511 100644
>>>> --- a/drivers/pci/pci.c
>>>> +++ b/drivers/pci/pci.c
>>>> @@ -3263,7 +3263,7 @@ 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;
>>>> +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
>>>>
>>>>  	/* check if the range hasn't been previously recorded */
>>>>  	spin_lock(&io_range_lock);
>>>> @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long
>>> pio)
>>>>
>>>>  #ifdef PCI_IOBASE
>>>>  	struct io_range *range;
>>>> -	resource_size_t allocated_size = 0;
>>>> +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
>>>
>>> Have you checked that pci_pio_to_address still returns valid values
>>> after this? I know that
>>> you are trying to take into account PCIBIOS_MIN_IO limit when
>>> allocating reserving the IO ranges,
>>> but the values added in the io_range_list are still starting from zero,
>>> no from PCIBIOS_MIN_IO,
>>
>> I think you're wrong here as in pci_address_to_pio we have:
>> +	resource_size_t offset = PCIBIOS_MIN_IO;
>>
>> This should be enough to guarantee that the PIOs start at
>> PCIBIOS_MIN_IO...right?
> 
> I don't think you can guarantee that the pio value that gets passed into
> pci_pio_to_address() always comes from a previously returned value by
> pci_address_to_pio(). Maybe you can add a check in pci_pio_to_address()
> 
> 	if (pio < PCIBIOS_MIN_IO)
> 		return address;
> 
> to avoid adding more checks in the list_for_each_entry() loop.
> 

I will register some ranges to the list and test it later.

But from my understanding, pci_pio_to_address() should can return the right
original physical address.


According to the algorithm, the output PIO ranges are consecutive, just like this:


					input pio of pci_pio_to_address()
						|
						V
|----------------|--------------------------|------|-----------|
					    ^
					    |
					allocated_size is here


The change of this patch just make the start PIO from ZERO to PCIBIOS_MIN_IO.

in pci_pio_to_address(), for one input pio which fall into any PIO segment, the
return address will be:

address = range->start + pio - allocated_size;

Since allocated_size is the total range size of all IO ranges before the one
where pio belong, then (pio - allocated_size) is the offset to the range start,
So....


Thanks!
Zhichang

> Best regards,
> Liviu
> 
>>
>>
>>> so the calculation of the address in this function could return
>>> negative values casted to pci_addr_t.
>>>
>>> Maybe you want to adjust the range->start value in
>>> pci_register_io_range() as well to have it
>>> offset by PCIBIOS_MIN_IO as well.
>>>
>>> Best regards,
>>> Liviu
>>>
>>>>
>>>>  	if (pio > IO_SPACE_LIMIT)
>>>>  		return address;
>>>> @@ -3335,7 +3335,7 @@ unsigned long __weak
>>> pci_address_to_pio(phys_addr_t address)
>>>>  {
>>>>  #ifdef PCI_IOBASE
>>>>  	struct io_range *res;
>>>> -	resource_size_t offset = 0;
>>>> +	resource_size_t offset = PCIBIOS_MIN_IO;
>>>>  	unsigned long addr = -1;
>>>>
>>>>  	spin_lock(&io_range_lock);
>>>> diff --git a/include/linux/of_address.h b/include/linux/of_address.h
>>>> index 3786473..deec469 100644
>>>> --- a/include/linux/of_address.h
>>>> +++ b/include/linux/of_address.h
>>>> @@ -24,6 +24,23 @@ struct of_pci_range {
>>>>  #define for_each_of_pci_range(parser, range) \
>>>>  	for (; of_pci_range_parser_one(parser, range);)
>>>>
>>>> +
>>>> +#ifndef indirect_io_enabled
>>>> +#define indirect_io_enabled indirect_io_enabled
>>>> +static inline bool indirect_io_enabled(void)
>>>> +{
>>>> +	return false;
>>>> +}
>>>> +#endif
>>>> +
>>>> +#ifndef addr_is_indirect_io
>>>> +#define addr_is_indirect_io addr_is_indirect_io
>>>> +static inline int addr_is_indirect_io(u64 taddr)
>>>> +{
>>>> +	return 0;
>>>> +}
>>>> +#endif
>>>> +
>>>>  /* Translate a DMA address from device space to CPU space */
>>>>  extern u64 of_translate_dma_address(struct device_node *dev,
>>>>  				    const __be32 *in_addr);
>>>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>>>> index 0e49f70..7f6bbb6 100644
>>>> --- a/include/linux/pci.h
>>>> +++ b/include/linux/pci.h
>>>> @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
>>> pci_bus *bus)
>>>>  /* provide the legacy pci_dma_* API */
>>>>  #include <linux/pci-dma-compat.h>
>>>>
>>>> +/*
>>>> + * define this macro here to refrain from compilation error for some
>>>> + * platforms. Please keep this macro at the end of this header file.
>>>> + */
>>>> +#ifndef PCIBIOS_MIN_IO
>>>> +#define PCIBIOS_MIN_IO		0
>>>> +#endif
>>>> +
>>>>  #endif /* LINUX_PCI_H */
>>>> --
>>>> 1.9.1
>>>>
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-pci"
>>> in
>>>> the body of a message to majordomo@vger.kernel.org
>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-10  6:24           ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-10  6:24 UTC (permalink / raw)
  To: liviu.dudau, Gabriele Paoloni
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, mark.rutland,
	olof, arnd, linux-arm-kernel, lorenzo.pieralisi, linux-kernel,
	Linuxarm, devicetree, linux-pci, linux-serial, minyard, benh,
	zourongrong, John Garry, zhichang.yuan02, kantyzc, xuwei (O)

Hi,Liviu,

Thanks for your comments!


On 2016/11/10 0:50, liviu.dudau@arm.com wrote:
> On Wed, Nov 09, 2016 at 04:16:17PM +0000, Gabriele Paoloni wrote:
>> Hi Liviu
>>
>> Thanks for reviewing
>>
> 
> [removed some irrelevant part of discussion, avoid crazy formatting]
> 
>>>> +/**
>>>> + * addr_is_indirect_io - check whether the input taddr is for
>>> indirectIO.
>>>> + * @taddr: the io address to be checked.
>>>> + *
>>>> + * Returns 1 when taddr is in the range; otherwise return 0.
>>>> + */
>>>> +int addr_is_indirect_io(u64 taddr)
>>>> +{
>>>> +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end <
>>> taddr)
>>>
>>> start >= taddr ?
>>
>> Nope... if  (taddr < arm64_extio_ops->start || taddr > arm64_extio_ops->end)
>> then taddr is outside the range [start; end] and will return 0; otherwise
>> it will return 1...
> 
> Oops, sorry, did not pay attention to the returned value. The check is
> correct as it is, no need to change then.
> 
>>
>>>
>>>> +		return 0;
>>>> +
>>>> +	return 1;
>>>> +}
>>>>
>>>>  BUILD_EXTIO(b, u8)
>>>>
>>>> diff --git a/drivers/of/address.c b/drivers/of/address.c
>>>> index 02b2903..cc2a05d 100644
>>>> --- a/drivers/of/address.c
>>>> +++ b/drivers/of/address.c
>>>> @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
>>> device_node *np)
>>>>  	return false;
>>>>  }
>>>>
>>>> +
>>>> +/*
>>>> + * of_isa_indirect_io - get the IO address from some isa reg
>>> property value.
>>>> + *	For some isa/lpc devices, no ranges property in ancestor node.
>>>> + *	The device addresses are described directly in their regs
>>> property.
>>>> + *	This fixup function will be called to get the IO address of
>>> isa/lpc
>>>> + *	devices when the normal of_translation failed.
>>>> + *
>>>> + * @parent:	points to the parent dts node;
>>>> + * @bus:		points to the of_bus which can be used to parse
>>> address;
>>>> + * @addr:	the address from reg property;
>>>> + * @na:		the address cell counter of @addr;
>>>> + * @presult:	store the address paresed from @addr;
>>>> + *
>>>> + * return 1 when successfully get the I/O address;
>>>> + * 0 will return for some failures.
>>>
>>> Bah, you are returning a signed int, why 0 for failure? Return a
>>> negative value with
>>> error codes. Otherwise change the return value into a bool.
>>
>> Yes we'll move to bool
>>
>>>
>>>> + */
>>>> +static int of_get_isa_indirect_io(struct device_node *parent,
>>>> +				struct of_bus *bus, __be32 *addr,
>>>> +				int na, u64 *presult)
>>>> +{
>>>> +	unsigned int flags;
>>>> +	unsigned int rlen;
>>>> +
>>>> +	/* whether support indirectIO */
>>>> +	if (!indirect_io_enabled())
>>>> +		return 0;
>>>> +
>>>> +	if (!of_bus_isa_match(parent))
>>>> +		return 0;
>>>> +
>>>> +	flags = bus->get_flags(addr);
>>>> +	if (!(flags & IORESOURCE_IO))
>>>> +		return 0;
>>>> +
>>>> +	/* there is ranges property, apply the normal translation
>>> directly. */
>>>
>>> s/there is ranges/if we have a 'ranges'/
>>
>> Thanks for spotting this
>>
>>>
>>>> +	if (of_get_property(parent, "ranges", &rlen))
>>>> +		return 0;
>>>> +
>>>> +	*presult = of_read_number(addr + 1, na - 1);
>>>> +	/* this fixup is only valid for specific I/O range. */
>>>> +	return addr_is_indirect_io(*presult);
>>>> +}
>>>> +
>>>>  static int of_translate_one(struct device_node *parent, struct
>>> of_bus *bus,
>>>>  			    struct of_bus *pbus, __be32 *addr,
>>>>  			    int na, int ns, int pna, const char *rprop)
>>>> @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
>>> device_node *dev,
>>>>  			result = of_read_number(addr, na);
>>>>  			break;
>>>>  		}
>>>> +		/*
>>>> +		 * For indirectIO device which has no ranges property, get
>>>> +		 * the address from reg directly.
>>>> +		 */
>>>> +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
>>>> +			pr_debug("isa indirectIO matched(%s)..addr =
>>> 0x%llx\n",
>>>> +				of_node_full_name(dev), result);
>>>> +			break;
>>>> +		}
>>>>
>>>>  		/* Get new parent bus and counts */
>>>>  		pbus = of_match_bus(parent);
>>>> @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
>>> device_node *dev,
>>>>  	if (taddr == OF_BAD_ADDR)
>>>>  		return -EINVAL;
>>>>  	memset(r, 0, sizeof(struct resource));
>>>> -	if (flags & IORESOURCE_IO) {
>>>> +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
>>>>  		unsigned long port;
>>>> +
>>>>  		port = pci_address_to_pio(taddr);
>>>>  		if (port == (unsigned long)-1)
>>>>  			return -EINVAL;
>>>> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
>>>> index ba34907..1a08511 100644
>>>> --- a/drivers/pci/pci.c
>>>> +++ b/drivers/pci/pci.c
>>>> @@ -3263,7 +3263,7 @@ 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;
>>>> +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
>>>>
>>>>  	/* check if the range hasn't been previously recorded */
>>>>  	spin_lock(&io_range_lock);
>>>> @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long
>>> pio)
>>>>
>>>>  #ifdef PCI_IOBASE
>>>>  	struct io_range *range;
>>>> -	resource_size_t allocated_size = 0;
>>>> +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
>>>
>>> Have you checked that pci_pio_to_address still returns valid values
>>> after this? I know that
>>> you are trying to take into account PCIBIOS_MIN_IO limit when
>>> allocating reserving the IO ranges,
>>> but the values added in the io_range_list are still starting from zero,
>>> no from PCIBIOS_MIN_IO,
>>
>> I think you're wrong here as in pci_address_to_pio we have:
>> +	resource_size_t offset = PCIBIOS_MIN_IO;
>>
>> This should be enough to guarantee that the PIOs start at
>> PCIBIOS_MIN_IO...right?
> 
> I don't think you can guarantee that the pio value that gets passed into
> pci_pio_to_address() always comes from a previously returned value by
> pci_address_to_pio(). Maybe you can add a check in pci_pio_to_address()
> 
> 	if (pio < PCIBIOS_MIN_IO)
> 		return address;
> 
> to avoid adding more checks in the list_for_each_entry() loop.
> 

I will register some ranges to the list and test it later.

But from my understanding, pci_pio_to_address() should can return the right
original physical address.


According to the algorithm, the output PIO ranges are consecutive, just like this:


					input pio of pci_pio_to_address()
						|
						V
|----------------|--------------------------|------|-----------|
					    ^
					    |
					allocated_size is here


The change of this patch just make the start PIO from ZERO to PCIBIOS_MIN_IO.

in pci_pio_to_address(), for one input pio which fall into any PIO segment, the
return address will be:

address = range->start + pio - allocated_size;

Since allocated_size is the total range size of all IO ranges before the one
where pio belong, then (pio - allocated_size) is the offset to the range start,
So....


Thanks!
Zhichang

> Best regards,
> Liviu
> 
>>
>>
>>> so the calculation of the address in this function could return
>>> negative values casted to pci_addr_t.
>>>
>>> Maybe you want to adjust the range->start value in
>>> pci_register_io_range() as well to have it
>>> offset by PCIBIOS_MIN_IO as well.
>>>
>>> Best regards,
>>> Liviu
>>>
>>>>
>>>>  	if (pio > IO_SPACE_LIMIT)
>>>>  		return address;
>>>> @@ -3335,7 +3335,7 @@ unsigned long __weak
>>> pci_address_to_pio(phys_addr_t address)
>>>>  {
>>>>  #ifdef PCI_IOBASE
>>>>  	struct io_range *res;
>>>> -	resource_size_t offset = 0;
>>>> +	resource_size_t offset = PCIBIOS_MIN_IO;
>>>>  	unsigned long addr = -1;
>>>>
>>>>  	spin_lock(&io_range_lock);
>>>> diff --git a/include/linux/of_address.h b/include/linux/of_address.h
>>>> index 3786473..deec469 100644
>>>> --- a/include/linux/of_address.h
>>>> +++ b/include/linux/of_address.h
>>>> @@ -24,6 +24,23 @@ struct of_pci_range {
>>>>  #define for_each_of_pci_range(parser, range) \
>>>>  	for (; of_pci_range_parser_one(parser, range);)
>>>>
>>>> +
>>>> +#ifndef indirect_io_enabled
>>>> +#define indirect_io_enabled indirect_io_enabled
>>>> +static inline bool indirect_io_enabled(void)
>>>> +{
>>>> +	return false;
>>>> +}
>>>> +#endif
>>>> +
>>>> +#ifndef addr_is_indirect_io
>>>> +#define addr_is_indirect_io addr_is_indirect_io
>>>> +static inline int addr_is_indirect_io(u64 taddr)
>>>> +{
>>>> +	return 0;
>>>> +}
>>>> +#endif
>>>> +
>>>>  /* Translate a DMA address from device space to CPU space */
>>>>  extern u64 of_translate_dma_address(struct device_node *dev,
>>>>  				    const __be32 *in_addr);
>>>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>>>> index 0e49f70..7f6bbb6 100644
>>>> --- a/include/linux/pci.h
>>>> +++ b/include/linux/pci.h
>>>> @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
>>> pci_bus *bus)
>>>>  /* provide the legacy pci_dma_* API */
>>>>  #include <linux/pci-dma-compat.h>
>>>>
>>>> +/*
>>>> + * define this macro here to refrain from compilation error for some
>>>> + * platforms. Please keep this macro at the end of this header file.
>>>> + */
>>>> +#ifndef PCIBIOS_MIN_IO
>>>> +#define PCIBIOS_MIN_IO		0
>>>> +#endif
>>>> +
>>>>  #endif /* LINUX_PCI_H */
>>>> --
>>>> 1.9.1
>>>>
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-pci"
>>> in
>>>> the body of a message to majordomo@vger.kernel.org
>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


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

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-10  6:24           ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-10  6:24 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,Liviu,

Thanks for your comments!


On 2016/11/10 0:50, liviu.dudau at arm.com wrote:
> On Wed, Nov 09, 2016 at 04:16:17PM +0000, Gabriele Paoloni wrote:
>> Hi Liviu
>>
>> Thanks for reviewing
>>
> 
> [removed some irrelevant part of discussion, avoid crazy formatting]
> 
>>>> +/**
>>>> + * addr_is_indirect_io - check whether the input taddr is for
>>> indirectIO.
>>>> + * @taddr: the io address to be checked.
>>>> + *
>>>> + * Returns 1 when taddr is in the range; otherwise return 0.
>>>> + */
>>>> +int addr_is_indirect_io(u64 taddr)
>>>> +{
>>>> +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end <
>>> taddr)
>>>
>>> start >= taddr ?
>>
>> Nope... if  (taddr < arm64_extio_ops->start || taddr > arm64_extio_ops->end)
>> then taddr is outside the range [start; end] and will return 0; otherwise
>> it will return 1...
> 
> Oops, sorry, did not pay attention to the returned value. The check is
> correct as it is, no need to change then.
> 
>>
>>>
>>>> +		return 0;
>>>> +
>>>> +	return 1;
>>>> +}
>>>>
>>>>  BUILD_EXTIO(b, u8)
>>>>
>>>> diff --git a/drivers/of/address.c b/drivers/of/address.c
>>>> index 02b2903..cc2a05d 100644
>>>> --- a/drivers/of/address.c
>>>> +++ b/drivers/of/address.c
>>>> @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
>>> device_node *np)
>>>>  	return false;
>>>>  }
>>>>
>>>> +
>>>> +/*
>>>> + * of_isa_indirect_io - get the IO address from some isa reg
>>> property value.
>>>> + *	For some isa/lpc devices, no ranges property in ancestor node.
>>>> + *	The device addresses are described directly in their regs
>>> property.
>>>> + *	This fixup function will be called to get the IO address of
>>> isa/lpc
>>>> + *	devices when the normal of_translation failed.
>>>> + *
>>>> + * @parent:	points to the parent dts node;
>>>> + * @bus:		points to the of_bus which can be used to parse
>>> address;
>>>> + * @addr:	the address from reg property;
>>>> + * @na:		the address cell counter of @addr;
>>>> + * @presult:	store the address paresed from @addr;
>>>> + *
>>>> + * return 1 when successfully get the I/O address;
>>>> + * 0 will return for some failures.
>>>
>>> Bah, you are returning a signed int, why 0 for failure? Return a
>>> negative value with
>>> error codes. Otherwise change the return value into a bool.
>>
>> Yes we'll move to bool
>>
>>>
>>>> + */
>>>> +static int of_get_isa_indirect_io(struct device_node *parent,
>>>> +				struct of_bus *bus, __be32 *addr,
>>>> +				int na, u64 *presult)
>>>> +{
>>>> +	unsigned int flags;
>>>> +	unsigned int rlen;
>>>> +
>>>> +	/* whether support indirectIO */
>>>> +	if (!indirect_io_enabled())
>>>> +		return 0;
>>>> +
>>>> +	if (!of_bus_isa_match(parent))
>>>> +		return 0;
>>>> +
>>>> +	flags = bus->get_flags(addr);
>>>> +	if (!(flags & IORESOURCE_IO))
>>>> +		return 0;
>>>> +
>>>> +	/* there is ranges property, apply the normal translation
>>> directly. */
>>>
>>> s/there is ranges/if we have a 'ranges'/
>>
>> Thanks for spotting this
>>
>>>
>>>> +	if (of_get_property(parent, "ranges", &rlen))
>>>> +		return 0;
>>>> +
>>>> +	*presult = of_read_number(addr + 1, na - 1);
>>>> +	/* this fixup is only valid for specific I/O range. */
>>>> +	return addr_is_indirect_io(*presult);
>>>> +}
>>>> +
>>>>  static int of_translate_one(struct device_node *parent, struct
>>> of_bus *bus,
>>>>  			    struct of_bus *pbus, __be32 *addr,
>>>>  			    int na, int ns, int pna, const char *rprop)
>>>> @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
>>> device_node *dev,
>>>>  			result = of_read_number(addr, na);
>>>>  			break;
>>>>  		}
>>>> +		/*
>>>> +		 * For indirectIO device which has no ranges property, get
>>>> +		 * the address from reg directly.
>>>> +		 */
>>>> +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
>>>> +			pr_debug("isa indirectIO matched(%s)..addr =
>>> 0x%llx\n",
>>>> +				of_node_full_name(dev), result);
>>>> +			break;
>>>> +		}
>>>>
>>>>  		/* Get new parent bus and counts */
>>>>  		pbus = of_match_bus(parent);
>>>> @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
>>> device_node *dev,
>>>>  	if (taddr == OF_BAD_ADDR)
>>>>  		return -EINVAL;
>>>>  	memset(r, 0, sizeof(struct resource));
>>>> -	if (flags & IORESOURCE_IO) {
>>>> +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
>>>>  		unsigned long port;
>>>> +
>>>>  		port = pci_address_to_pio(taddr);
>>>>  		if (port == (unsigned long)-1)
>>>>  			return -EINVAL;
>>>> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
>>>> index ba34907..1a08511 100644
>>>> --- a/drivers/pci/pci.c
>>>> +++ b/drivers/pci/pci.c
>>>> @@ -3263,7 +3263,7 @@ 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;
>>>> +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
>>>>
>>>>  	/* check if the range hasn't been previously recorded */
>>>>  	spin_lock(&io_range_lock);
>>>> @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long
>>> pio)
>>>>
>>>>  #ifdef PCI_IOBASE
>>>>  	struct io_range *range;
>>>> -	resource_size_t allocated_size = 0;
>>>> +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
>>>
>>> Have you checked that pci_pio_to_address still returns valid values
>>> after this? I know that
>>> you are trying to take into account PCIBIOS_MIN_IO limit when
>>> allocating reserving the IO ranges,
>>> but the values added in the io_range_list are still starting from zero,
>>> no from PCIBIOS_MIN_IO,
>>
>> I think you're wrong here as in pci_address_to_pio we have:
>> +	resource_size_t offset = PCIBIOS_MIN_IO;
>>
>> This should be enough to guarantee that the PIOs start at
>> PCIBIOS_MIN_IO...right?
> 
> I don't think you can guarantee that the pio value that gets passed into
> pci_pio_to_address() always comes from a previously returned value by
> pci_address_to_pio(). Maybe you can add a check in pci_pio_to_address()
> 
> 	if (pio < PCIBIOS_MIN_IO)
> 		return address;
> 
> to avoid adding more checks in the list_for_each_entry() loop.
> 

I will register some ranges to the list and test it later.

But from my understanding, pci_pio_to_address() should can return the right
original physical address.


According to the algorithm, the output PIO ranges are consecutive? just like this:


					input pio of pci_pio_to_address()
						|
						V
|----------------|--------------------------|------|-----------|
					    ^
					    |
					allocated_size is here


The change of this patch just make the start PIO from ZERO to PCIBIOS_MIN_IO.

in pci_pio_to_address(), for one input pio which fall into any PIO segment, the
return address will be:

address = range->start + pio - allocated_size;

Since allocated_size is the total range size of all IO ranges before the one
where pio belong, then (pio - allocated_size) is the offset to the range start,
So....


Thanks!
Zhichang

> Best regards,
> Liviu
> 
>>
>>
>>> so the calculation of the address in this function could return
>>> negative values casted to pci_addr_t.
>>>
>>> Maybe you want to adjust the range->start value in
>>> pci_register_io_range() as well to have it
>>> offset by PCIBIOS_MIN_IO as well.
>>>
>>> Best regards,
>>> Liviu
>>>
>>>>
>>>>  	if (pio > IO_SPACE_LIMIT)
>>>>  		return address;
>>>> @@ -3335,7 +3335,7 @@ unsigned long __weak
>>> pci_address_to_pio(phys_addr_t address)
>>>>  {
>>>>  #ifdef PCI_IOBASE
>>>>  	struct io_range *res;
>>>> -	resource_size_t offset = 0;
>>>> +	resource_size_t offset = PCIBIOS_MIN_IO;
>>>>  	unsigned long addr = -1;
>>>>
>>>>  	spin_lock(&io_range_lock);
>>>> diff --git a/include/linux/of_address.h b/include/linux/of_address.h
>>>> index 3786473..deec469 100644
>>>> --- a/include/linux/of_address.h
>>>> +++ b/include/linux/of_address.h
>>>> @@ -24,6 +24,23 @@ struct of_pci_range {
>>>>  #define for_each_of_pci_range(parser, range) \
>>>>  	for (; of_pci_range_parser_one(parser, range);)
>>>>
>>>> +
>>>> +#ifndef indirect_io_enabled
>>>> +#define indirect_io_enabled indirect_io_enabled
>>>> +static inline bool indirect_io_enabled(void)
>>>> +{
>>>> +	return false;
>>>> +}
>>>> +#endif
>>>> +
>>>> +#ifndef addr_is_indirect_io
>>>> +#define addr_is_indirect_io addr_is_indirect_io
>>>> +static inline int addr_is_indirect_io(u64 taddr)
>>>> +{
>>>> +	return 0;
>>>> +}
>>>> +#endif
>>>> +
>>>>  /* Translate a DMA address from device space to CPU space */
>>>>  extern u64 of_translate_dma_address(struct device_node *dev,
>>>>  				    const __be32 *in_addr);
>>>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>>>> index 0e49f70..7f6bbb6 100644
>>>> --- a/include/linux/pci.h
>>>> +++ b/include/linux/pci.h
>>>> @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
>>> pci_bus *bus)
>>>>  /* provide the legacy pci_dma_* API */
>>>>  #include <linux/pci-dma-compat.h>
>>>>
>>>> +/*
>>>> + * define this macro here to refrain from compilation error for some
>>>> + * platforms. Please keep this macro at the end of this header file.
>>>> + */
>>>> +#ifndef PCIBIOS_MIN_IO
>>>> +#define PCIBIOS_MIN_IO		0
>>>> +#endif
>>>> +
>>>>  #endif /* LINUX_PCI_H */
>>>> --
>>>> 1.9.1
>>>>
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-pci"
>>> in
>>>> the body of a message to majordomo at vger.kernel.org
>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-09 21:34         ` Arnd Bergmann
  (?)
@ 2016-11-10  6:40           ` zhichang.yuan
  -1 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-10  6:40 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: Gabriele Paoloni, mark.rutland, devicetree, lorenzo.pieralisi,
	benh, minyard, catalin.marinas, John Garry, will.deacon,
	linux-kernel, xuwei (O),
	Linuxarm, olof, robh+dt, zourongrong, linux-serial, linux-pci,
	bhelgaas, liviu.dudau, kantyzc, zhichang.yuan02

Hi, Arnd,

On 2016/11/10 5:34, Arnd Bergmann wrote:
> On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni wrote:
>>> On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
>>>> +       /*
>>>> +        * The first PCIBIOS_MIN_IO is reserved specifically for
>>> indirectIO.
>>>> +        * It will separate indirectIO range from pci host bridge to
>>>> +        * avoid the possible PIO conflict.
>>>> +        * Set the indirectIO range directly here.
>>>> +        */
>>>> +       lpcdev->io_ops.start = 0;
>>>> +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
>>>> +       lpcdev->io_ops.devpara = lpcdev;
>>>> +       lpcdev->io_ops.pfin = hisilpc_comm_in;
>>>> +       lpcdev->io_ops.pfout = hisilpc_comm_out;
>>>> +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
>>>> +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
>>>
>>> I have to look at patch 2 in more detail again, after missing a few
>>> review
>>> rounds. I'm still a bit skeptical about hardcoding a logical I/O port
>>> range here, and would hope that we can just go through the same
>>> assignment of logical port ranges that we have for PCI buses,
>>> decoupling
>>> the bus addresses from the linux-internal ones.
>>
>> The point here is that we want to avoid any conflict/overlap between
>> the LPC I/O space and the PCI I/O space. With the assignment above
>> we make sure that LPC never interfere with PCI I/O space.
> 
> But we already abstract the PCI I/O space using dynamic registration.
> There is no need to hardcode the logical address for ISA, though
> I think we can hardcode the bus address to start at zero here.

Do you means that we can pick up the maximal I/O address from all children's
device resources??

Thanks,
Zhichang

> 
> 	Arnd
> 
> .
> 

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-10  6:40           ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-10  6:40 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Gabriele Paoloni, mark.rutland-5wv7dgnIgG8,
	devicetree-u79uwXL29TY76Z2rM5mHXA, lorenzo.pieralisi-5wv7dgnIgG8,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, minyard-HInyCGIudOg,
	catalin.marinas-5wv7dgnIgG8, John Garry, will.deacon-5wv7dgnIgG8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, xuwei (O),
	Linuxarm, olof-nZhT3qVonbNeoWH0uzbU5w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, linux-pci-fy+rA21nqHI

Hi, Arnd,

On 2016/11/10 5:34, Arnd Bergmann wrote:
> On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni wrote:
>>> On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
>>>> +       /*
>>>> +        * The first PCIBIOS_MIN_IO is reserved specifically for
>>> indirectIO.
>>>> +        * It will separate indirectIO range from pci host bridge to
>>>> +        * avoid the possible PIO conflict.
>>>> +        * Set the indirectIO range directly here.
>>>> +        */
>>>> +       lpcdev->io_ops.start = 0;
>>>> +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
>>>> +       lpcdev->io_ops.devpara = lpcdev;
>>>> +       lpcdev->io_ops.pfin = hisilpc_comm_in;
>>>> +       lpcdev->io_ops.pfout = hisilpc_comm_out;
>>>> +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
>>>> +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
>>>
>>> I have to look at patch 2 in more detail again, after missing a few
>>> review
>>> rounds. I'm still a bit skeptical about hardcoding a logical I/O port
>>> range here, and would hope that we can just go through the same
>>> assignment of logical port ranges that we have for PCI buses,
>>> decoupling
>>> the bus addresses from the linux-internal ones.
>>
>> The point here is that we want to avoid any conflict/overlap between
>> the LPC I/O space and the PCI I/O space. With the assignment above
>> we make sure that LPC never interfere with PCI I/O space.
> 
> But we already abstract the PCI I/O space using dynamic registration.
> There is no need to hardcode the logical address for ISA, though
> I think we can hardcode the bus address to start at zero here.

Do you means that we can pick up the maximal I/O address from all children's
device resources??

Thanks,
Zhichang

> 
> 	Arnd
> 
> .
> 

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-10  6:40           ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-10  6:40 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, Arnd,

On 2016/11/10 5:34, Arnd Bergmann wrote:
> On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni wrote:
>>> On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
>>>> +       /*
>>>> +        * The first PCIBIOS_MIN_IO is reserved specifically for
>>> indirectIO.
>>>> +        * It will separate indirectIO range from pci host bridge to
>>>> +        * avoid the possible PIO conflict.
>>>> +        * Set the indirectIO range directly here.
>>>> +        */
>>>> +       lpcdev->io_ops.start = 0;
>>>> +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
>>>> +       lpcdev->io_ops.devpara = lpcdev;
>>>> +       lpcdev->io_ops.pfin = hisilpc_comm_in;
>>>> +       lpcdev->io_ops.pfout = hisilpc_comm_out;
>>>> +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
>>>> +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
>>>
>>> I have to look at patch 2 in more detail again, after missing a few
>>> review
>>> rounds. I'm still a bit skeptical about hardcoding a logical I/O port
>>> range here, and would hope that we can just go through the same
>>> assignment of logical port ranges that we have for PCI buses,
>>> decoupling
>>> the bus addresses from the linux-internal ones.
>>
>> The point here is that we want to avoid any conflict/overlap between
>> the LPC I/O space and the PCI I/O space. With the assignment above
>> we make sure that LPC never interfere with PCI I/O space.
> 
> But we already abstract the PCI I/O space using dynamic registration.
> There is no need to hardcode the logical address for ISA, though
> I think we can hardcode the bus address to start at zero here.

Do you means that we can pick up the maximal I/O address from all children's
device resources??

Thanks,
Zhichang

> 
> 	Arnd
> 
> .
> 

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
  2016-11-09 11:20         ` Mark Rutland
  (?)
@ 2016-11-10  7:08           ` Benjamin Herrenschmidt
  -1 siblings, 0 replies; 286+ messages in thread
From: Benjamin Herrenschmidt @ 2016-11-10  7:08 UTC (permalink / raw)
  To: Mark Rutland
  Cc: zhichang.yuan, catalin.marinas, will.deacon, robh+dt, bhelgaas,
	olof, arnd, linux-arm-kernel, lorenzo.pieralisi, linux-kernel,
	linuxarm, devicetree, linux-pci, linux-serial, minyard,
	liviu.dudau, zourongrong, john.garry, gabriele.paoloni,
	zhichang.yuan02, kantyzc, xuwei5, marc.zyngier

On Wed, 2016-11-09 at 11:20 +0000, Mark Rutland wrote:
> The big change would be to handle !MMIO translations, for which we'd
> need a runtime registry of ISA bus instance to find the relevant
> accessor ops and instance-specific data.

Yes. We do something a bit like that on ppc, we find the PCI bus
for which the IO ports match and I have a hook to register the
special indirect ISA.

It's a bit messy, we could do something nicer generically.

Cheers,
Ben.

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-10  7:08           ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 286+ messages in thread
From: Benjamin Herrenschmidt @ 2016-11-10  7:08 UTC (permalink / raw)
  To: Mark Rutland
  Cc: zhichang.yuan, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, olof-nZhT3qVonbNeoWH0uzbU5w,
	arnd-r2nGTMty4D4,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	lorenzo.pieralisi-5wv7dgnIgG8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linuxarm-hv44wF8Li93QT0dZR+AlfA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, minyard-HInyCGIudOg,
	liviu.dudau-5wv7dgnIgG8, zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
	john.garry-hv44wF8Li93QT0dZR+AlfA,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w, kantyzc-9Onoh4P/yGk,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q, marc.zyngier-5wv7dgnIgG8

On Wed, 2016-11-09 at 11:20 +0000, Mark Rutland wrote:
> The big change would be to handle !MMIO translations, for which we'd
> need a runtime registry of ISA bus instance to find the relevant
> accessor ops and instance-specific data.

Yes. We do something a bit like that on ppc, we find the PCI bus
for which the IO ports match and I have a hook to register the
special indirect ISA.

It's a bit messy, we could do something nicer generically.

Cheers,
Ben.

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

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-10  7:08           ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 286+ messages in thread
From: Benjamin Herrenschmidt @ 2016-11-10  7:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 2016-11-09 at 11:20 +0000, Mark Rutland wrote:
> The big change would be to handle !MMIO translations, for which we'd
> need a runtime registry of ISA bus instance to find the relevant
> accessor ops and instance-specific data.

Yes. We do something a bit like that on ppc, we find the PCI bus
for which the IO ports match and I have a hook to register the
special indirect ISA.

It's a bit messy, we could do something nicer generically.

Cheers,
Ben.

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-11-08 23:16       ` Benjamin Herrenschmidt
  (?)
@ 2016-11-10  8:33         ` zhichang.yuan
  -1 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-10  8:33 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Mark Rutland
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, olof, arnd,
	linux-arm-kernel, lorenzo.pieralisi, linux-kernel, linuxarm,
	devicetree, linux-pci, linux-serial, minyard, liviu.dudau,
	zourongrong, john.garry, gabriele.paoloni, zhichang.yuan02,
	kantyzc, xuwei5, marc.zyngier

Hi, Ben,


On 2016/11/9 7:16, Benjamin Herrenschmidt wrote:
> On Tue, 2016-11-08 at 12:03 +0000, Mark Rutland wrote:
>> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>>>
>>> For arm64, there is no I/O space as other architectural platforms, such as
>>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>>> known port addresses are used to control the corresponding target devices, for
>>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>>> normal MMIO mode in using.
>>
>> This has nothing to do with arm64. Hardware with this kind of indirect
>> bus access could be integrated with a variety of CPU architectures. It
>> simply hasn't been, yet.
> 
> On some ppc's we also use similar indirect access methods for IOs. We
> have a generic infrastructure for re-routing some memory or IO regions
> to hooks.
> 
I am interested on the generic infrastructure on PPC.
Could you point out where those drivers are?
want to take a look..

Thanks,
Zhichang

> On POWER8, our PCIe doesn't do IO at all, but we have an LPC bus behind
> firmware calls ;-) We use that infrastructure to plumb in the LPC bus.
> 
>>> To drive these devices, this patch introduces a method named indirect-IO.
>>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>>> redefined. When upper layer drivers call in/out with those known legacy port
>>> addresses to access the peripherals, the hooking functions corrresponding to
>>> those target peripherals will be called. Through this way, those upper layer
>>> drivers which depend on in/out can run on Hip06 without any changes.
>>
>> As above, this has nothing to do with arm64, and as such, should live in
>> generic code, exactly as we would do if we had higher-level ISA
>> accessor ops.
>>
>> Regardless, given the multi-instance case, I don't think this is
>> sufficient in general (and I think we need higher-level ISA accessors
>> to handle the indirection).
> 
> Multi-instance with IO is tricky to do generically because archs already
> have all sort of hacks to deal with the fact that inb/outb don't require
> an explicit ioremap, so an IO resource can take all sort of shape depending
> on the arch.
> 
> Overall it boils down to applying some kind of per-instance "offset" to
> the IO port number though.
> 

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-10  8:33         ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-10  8:33 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Mark Rutland
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, olof, arnd,
	linux-arm-kernel, lorenzo.pieralisi, linux-kernel, linuxarm,
	devicetree, linux-pci, linux-serial, minyard, liviu.dudau,
	zourongrong, john.garry, gabriele.paoloni, zhichang.yuan02,
	kantyzc, xuwei5, marc.zyngier

Hi, Ben,


On 2016/11/9 7:16, Benjamin Herrenschmidt wrote:
> On Tue, 2016-11-08 at 12:03 +0000, Mark Rutland wrote:
>> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>>>
>>> For arm64, there is no I/O space as other architectural platforms, such as
>>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>>> known port addresses are used to control the corresponding target devices, for
>>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>>> normal MMIO mode in using.
>>
>> This has nothing to do with arm64. Hardware with this kind of indirect
>> bus access could be integrated with a variety of CPU architectures. It
>> simply hasn't been, yet.
> 
> On some ppc's we also use similar indirect access methods for IOs. We
> have a generic infrastructure for re-routing some memory or IO regions
> to hooks.
> 
I am interested on the generic infrastructure on PPC.
Could you point out where those drivers are?
want to take a look..

Thanks,
Zhichang

> On POWER8, our PCIe doesn't do IO at all, but we have an LPC bus behind
> firmware calls ;-) We use that infrastructure to plumb in the LPC bus.
> 
>>> To drive these devices, this patch introduces a method named indirect-IO.
>>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>>> redefined. When upper layer drivers call in/out with those known legacy port
>>> addresses to access the peripherals, the hooking functions corrresponding to
>>> those target peripherals will be called. Through this way, those upper layer
>>> drivers which depend on in/out can run on Hip06 without any changes.
>>
>> As above, this has nothing to do with arm64, and as such, should live in
>> generic code, exactly as we would do if we had higher-level ISA
>> accessor ops.
>>
>> Regardless, given the multi-instance case, I don't think this is
>> sufficient in general (and I think we need higher-level ISA accessors
>> to handle the indirection).
> 
> Multi-instance with IO is tricky to do generically because archs already
> have all sort of hacks to deal with the fact that inb/outb don't require
> an explicit ioremap, so an IO resource can take all sort of shape depending
> on the arch.
> 
> Overall it boils down to applying some kind of per-instance "offset" to
> the IO port number though.
> 

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-10  8:33         ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-10  8:33 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, Ben,


On 2016/11/9 7:16, Benjamin Herrenschmidt wrote:
> On Tue, 2016-11-08 at 12:03 +0000, Mark Rutland wrote:
>> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>>>
>>> For arm64, there is no I/O space as other architectural platforms, such as
>>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>>> known port addresses are used to control the corresponding target devices, for
>>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>>> normal MMIO mode in using.
>>
>> This has nothing to do with arm64. Hardware with this kind of indirect
>> bus access could be integrated with a variety of CPU architectures. It
>> simply hasn't been, yet.
> 
> On some ppc's we also use similar indirect access methods for IOs. We
> have a generic infrastructure for re-routing some memory or IO regions
> to hooks.
> 
I am interested on the generic infrastructure on PPC.
Could you point out where those drivers are?
want to take a look..

Thanks,
Zhichang

> On POWER8, our PCIe doesn't do IO at all, but we have an LPC bus behind
> firmware calls ;-) We use that infrastructure to plumb in the LPC bus.
> 
>>> To drive these devices, this patch introduces a method named indirect-IO.
>>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>>> redefined. When upper layer drivers call in/out with those known legacy port
>>> addresses to access the peripherals, the hooking functions corrresponding to
>>> those target peripherals will be called. Through this way, those upper layer
>>> drivers which depend on in/out can run on Hip06 without any changes.
>>
>> As above, this has nothing to do with arm64, and as such, should live in
>> generic code, exactly as we would do if we had higher-level ISA
>> accessor ops.
>>
>> Regardless, given the multi-instance case, I don't think this is
>> sufficient in general (and I think we need higher-level ISA accessors
>> to handle the indirection).
> 
> Multi-instance with IO is tricky to do generically because archs already
> have all sort of hacks to deal with the fact that inb/outb don't require
> an explicit ioremap, so an IO resource can take all sort of shape depending
> on the arch.
> 
> Overall it boils down to applying some kind of per-instance "offset" to
> the IO port number though.
> 

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-10  6:40           ` zhichang.yuan
  (?)
@ 2016-11-10  9:12             ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-10  9:12 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: zhichang.yuan, mark.rutland, devicetree, lorenzo.pieralisi,
	Gabriele Paoloni, minyard, linux-pci, benh, John Garry,
	will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, liviu.dudau, bhelgaas, zhichang.yuan02

On Thursday, November 10, 2016 2:40:26 PM CET zhichang.yuan wrote:
> On 2016/11/10 5:34, Arnd Bergmann wrote:
> > On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni wrote:
> >>> On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
> >>>> +       /*
> >>>> +        * The first PCIBIOS_MIN_IO is reserved specifically for
> >>> indirectIO.
> >>>> +        * It will separate indirectIO range from pci host bridge to
> >>>> +        * avoid the possible PIO conflict.
> >>>> +        * Set the indirectIO range directly here.
> >>>> +        */
> >>>> +       lpcdev->io_ops.start = 0;
> >>>> +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> >>>> +       lpcdev->io_ops.devpara = lpcdev;
> >>>> +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> >>>> +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> >>>> +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> >>>> +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
> >>>
> >>> I have to look at patch 2 in more detail again, after missing a few
> >>> review
> >>> rounds. I'm still a bit skeptical about hardcoding a logical I/O port
> >>> range here, and would hope that we can just go through the same
> >>> assignment of logical port ranges that we have for PCI buses,
> >>> decoupling
> >>> the bus addresses from the linux-internal ones.
> >>
> >> The point here is that we want to avoid any conflict/overlap between
> >> the LPC I/O space and the PCI I/O space. With the assignment above
> >> we make sure that LPC never interfere with PCI I/O space.
> > 
> > But we already abstract the PCI I/O space using dynamic registration.
> > There is no need to hardcode the logical address for ISA, though
> > I think we can hardcode the bus address to start at zero here.
> 
> Do you means that we can pick up the maximal I/O address from all children's
> device resources??

The driver should not look at the resources of its children, just
register a range of addresses dynamically, as I suggested in an
earlier review.


Your current version has

        if (arm64_extio_ops->pfout)                             \
                arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
                       addr, value, sizeof(type));             \

Instead, just subtract the start of the range from the logical
port number to transform it back into a bus-local port number:

        if (arm64_extio_ops->pfout)                             \
                arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
                       addr - arm64_extio_ops->start, value, sizeof(type)); \

We know that the ISA/LPC bus can only have up to 65536 ports,
so you can register all of those, or possibly limit it further to
1024 or 4096 ports, whichever matches the bus implementation.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-10  9:12             ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-10  9:12 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: zhichang.yuan, mark.rutland, devicetree, lorenzo.pieralisi,
	Gabriele Paoloni, minyard, linux-pci, benh, John Garry,
	will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial

On Thursday, November 10, 2016 2:40:26 PM CET zhichang.yuan wrote:
> On 2016/11/10 5:34, Arnd Bergmann wrote:
> > On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni wrote:
> >>> On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
> >>>> +       /*
> >>>> +        * The first PCIBIOS_MIN_IO is reserved specifically for
> >>> indirectIO.
> >>>> +        * It will separate indirectIO range from pci host bridge to
> >>>> +        * avoid the possible PIO conflict.
> >>>> +        * Set the indirectIO range directly here.
> >>>> +        */
> >>>> +       lpcdev->io_ops.start = 0;
> >>>> +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> >>>> +       lpcdev->io_ops.devpara = lpcdev;
> >>>> +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> >>>> +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> >>>> +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> >>>> +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
> >>>
> >>> I have to look at patch 2 in more detail again, after missing a few
> >>> review
> >>> rounds. I'm still a bit skeptical about hardcoding a logical I/O port
> >>> range here, and would hope that we can just go through the same
> >>> assignment of logical port ranges that we have for PCI buses,
> >>> decoupling
> >>> the bus addresses from the linux-internal ones.
> >>
> >> The point here is that we want to avoid any conflict/overlap between
> >> the LPC I/O space and the PCI I/O space. With the assignment above
> >> we make sure that LPC never interfere with PCI I/O space.
> > 
> > But we already abstract the PCI I/O space using dynamic registration.
> > There is no need to hardcode the logical address for ISA, though
> > I think we can hardcode the bus address to start at zero here.
> 
> Do you means that we can pick up the maximal I/O address from all children's
> device resources??

The driver should not look at the resources of its children, just
register a range of addresses dynamically, as I suggested in an
earlier review.


Your current version has

        if (arm64_extio_ops->pfout)                             \
                arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
                       addr, value, sizeof(type));             \

Instead, just subtract the start of the range from the logical
port number to transform it back into a bus-local port number:

        if (arm64_extio_ops->pfout)                             \
                arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
                       addr - arm64_extio_ops->start, value, sizeof(type)); \

We know that the ISA/LPC bus can only have up to 65536 ports,
so you can register all of those, or possibly limit it further to
1024 or 4096 ports, whichever matches the bus implementation.

	Arnd

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-10  9:12             ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-10  9:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday, November 10, 2016 2:40:26 PM CET zhichang.yuan wrote:
> On 2016/11/10 5:34, Arnd Bergmann wrote:
> > On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni wrote:
> >>> On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
> >>>> +       /*
> >>>> +        * The first PCIBIOS_MIN_IO is reserved specifically for
> >>> indirectIO.
> >>>> +        * It will separate indirectIO range from pci host bridge to
> >>>> +        * avoid the possible PIO conflict.
> >>>> +        * Set the indirectIO range directly here.
> >>>> +        */
> >>>> +       lpcdev->io_ops.start = 0;
> >>>> +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> >>>> +       lpcdev->io_ops.devpara = lpcdev;
> >>>> +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> >>>> +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> >>>> +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> >>>> +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
> >>>
> >>> I have to look at patch 2 in more detail again, after missing a few
> >>> review
> >>> rounds. I'm still a bit skeptical about hardcoding a logical I/O port
> >>> range here, and would hope that we can just go through the same
> >>> assignment of logical port ranges that we have for PCI buses,
> >>> decoupling
> >>> the bus addresses from the linux-internal ones.
> >>
> >> The point here is that we want to avoid any conflict/overlap between
> >> the LPC I/O space and the PCI I/O space. With the assignment above
> >> we make sure that LPC never interfere with PCI I/O space.
> > 
> > But we already abstract the PCI I/O space using dynamic registration.
> > There is no need to hardcode the logical address for ISA, though
> > I think we can hardcode the bus address to start at zero here.
> 
> Do you means that we can pick up the maximal I/O address from all children's
> device resources??

The driver should not look at the resources of its children, just
register a range of addresses dynamically, as I suggested in an
earlier review.


Your current version has

        if (arm64_extio_ops->pfout)                             \
                arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
                       addr, value, sizeof(type));             \

Instead, just subtract the start of the range from the logical
port number to transform it back into a bus-local port number:

        if (arm64_extio_ops->pfout)                             \
                arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
                       addr - arm64_extio_ops->start, value, sizeof(type)); \

We know that the ISA/LPC bus can only have up to 65536 ports,
so you can register all of those, or possibly limit it further to
1024 or 4096 ports, whichever matches the bus implementation.

	Arnd

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-11-08 23:16       ` Benjamin Herrenschmidt
@ 2016-11-10 11:22         ` Mark Rutland
  -1 siblings, 0 replies; 286+ messages in thread
From: Mark Rutland @ 2016-11-10 11:22 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: zhichang.yuan, catalin.marinas, will.deacon, robh+dt, bhelgaas,
	olof, arnd, linux-arm-kernel, lorenzo.pieralisi, linux-kernel,
	linuxarm, devicetree, linux-pci, linux-serial, minyard,
	liviu.dudau, zourongrong, john.garry, gabriele.paoloni,
	zhichang.yuan02, kantyzc, xuwei5, marc.zyngier

On Wed, Nov 09, 2016 at 10:16:42AM +1100, Benjamin Herrenschmidt wrote:
> On Tue, 2016-11-08 at 12:03 +0000, Mark Rutland wrote:
> > On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> > > 
> > > For arm64, there is no I/O space as other architectural platforms, such as
> > > X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> > > such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> > > known port addresses are used to control the corresponding target devices, for
> > > example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> > > normal MMIO mode in using.
> > 
> > This has nothing to do with arm64. Hardware with this kind of indirect
> > bus access could be integrated with a variety of CPU architectures. It
> > simply hasn't been, yet.
> 
> On some ppc's we also use similar indirect access methods for IOs. We
> have a generic infrastructure for re-routing some memory or IO regions
> to hooks.
> 
> On POWER8, our PCIe doesn't do IO at all, but we have an LPC bus behind
> firmware calls ;-) We use that infrastructure to plumb in the LPC bus.

Just to check, do you hook that in your inb/outb/etc?

Generally, it would seem nicer if we could have higher-level
isa_{inb,outb,whatever} accessors that we could hook separately from
other IO.

We don't necessarily have to move all ISA drivers over to that if we had
a separate symbol for that interface.

Thanks,
Mark.

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-10 11:22         ` Mark Rutland
  0 siblings, 0 replies; 286+ messages in thread
From: Mark Rutland @ 2016-11-10 11:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Nov 09, 2016 at 10:16:42AM +1100, Benjamin Herrenschmidt wrote:
> On Tue, 2016-11-08 at 12:03 +0000, Mark Rutland wrote:
> > On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
> > > 
> > > For arm64, there is no I/O space as other architectural platforms, such as
> > > X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> > > such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> > > known port addresses are used to control the corresponding target devices, for
> > > example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> > > normal MMIO mode in using.
> > 
> > This has nothing to do with arm64. Hardware with this kind of indirect
> > bus access could be integrated with a variety of CPU architectures. It
> > simply hasn't been, yet.
> 
> On some ppc's we also use similar indirect access methods for IOs. We
> have a generic infrastructure for re-routing some memory or IO regions
> to hooks.
> 
> On POWER8, our PCIe doesn't do IO at all, but we have an LPC bus behind
> firmware calls ;-) We use that infrastructure to plumb in the LPC bus.

Just to check, do you hook that in your inb/outb/etc?

Generally, it would seem nicer if we could have higher-level
isa_{inb,outb,whatever} accessors that we could hook separately from
other IO.

We don't necessarily have to move all ISA drivers over to that if we had
a separate symbol for that interface.

Thanks,
Mark.

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-10  9:12             ` Arnd Bergmann
  (?)
@ 2016-11-10 12:36               ` zhichang.yuan
  -1 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-10 12:36 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: mark.rutland, devicetree, lorenzo.pieralisi, Gabriele Paoloni,
	minyard, linux-pci, benh, John Garry, will.deacon, linux-kernel,
	xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, liviu.dudau, bhelgaas, zhichang.yuan02

Hi, Arnd,

On 2016/11/10 17:12, Arnd Bergmann wrote:
> On Thursday, November 10, 2016 2:40:26 PM CET zhichang.yuan wrote:
>> On 2016/11/10 5:34, Arnd Bergmann wrote:
>>> On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni wrote:
>>>>> On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
>>>>>> +       /*
>>>>>> +        * The first PCIBIOS_MIN_IO is reserved specifically for
>>>>> indirectIO.
>>>>>> +        * It will separate indirectIO range from pci host bridge to
>>>>>> +        * avoid the possible PIO conflict.
>>>>>> +        * Set the indirectIO range directly here.
>>>>>> +        */
>>>>>> +       lpcdev->io_ops.start = 0;
>>>>>> +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
>>>>>> +       lpcdev->io_ops.devpara = lpcdev;
>>>>>> +       lpcdev->io_ops.pfin = hisilpc_comm_in;
>>>>>> +       lpcdev->io_ops.pfout = hisilpc_comm_out;
>>>>>> +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
>>>>>> +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
>>>>>
>>>>> I have to look at patch 2 in more detail again, after missing a few
>>>>> review
>>>>> rounds. I'm still a bit skeptical about hardcoding a logical I/O port
>>>>> range here, and would hope that we can just go through the same
>>>>> assignment of logical port ranges that we have for PCI buses,
>>>>> decoupling
>>>>> the bus addresses from the linux-internal ones.
>>>>
>>>> The point here is that we want to avoid any conflict/overlap between
>>>> the LPC I/O space and the PCI I/O space. With the assignment above
>>>> we make sure that LPC never interfere with PCI I/O space.
>>>
>>> But we already abstract the PCI I/O space using dynamic registration.
>>> There is no need to hardcode the logical address for ISA, though
>>> I think we can hardcode the bus address to start at zero here.
>>
>> Do you means that we can pick up the maximal I/O address from all children's
>> device resources??
> 
> The driver should not look at the resources of its children, just
> register a range of addresses dynamically, as I suggested in an
> earlier review.
>
Sorry! I can't catch your idea yet:(

When to register the I/O range? Is it done just after the successfully
of_translate_address() during the children scanning?

If yes, when a child is scanning, there is no range data in arm64_extio_ops. The
addr_is_indirect_io() calling in of_get_isa_indirect_io() don't need. All we can
check is just whether the address to be translated is IO and is under a parent
device which has no 'ranges' property.

> 
> Your current version has
> 
>         if (arm64_extio_ops->pfout)                             \
>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>                        addr, value, sizeof(type));             \
> 
> Instead, just subtract the start of the range from the logical
> port number to transform it back into a bus-local port number:
> 
>         if (arm64_extio_ops->pfout)                             \
>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>                        addr - arm64_extio_ops->start, value, sizeof(type)); \
> 
I think there is some information needed sync.
In the old patch-set, we don't bypass the pci_address_to_pio() after
successfully of_translate_address(). In this way, we don't need to reserve any
PIO space for our LPC since the logical port are from the same mapping
algorithm. Based on this way, the port number in the device resource is logical
one, then we need to subtract the start of the resource to get back the
bus-local port.

>From V3, we don't apply the mapping based on pci_address_to_pio(), the
of_translate_address() return the bus-local port directly and store into
relevant device resource. So, in the current arm64_extio_ops->pfout(), the
reverse translation don't need anymore. The input "addr" is bus-local port now.


Thanks,
Zhichang


> We know that the ISA/LPC bus can only have up to 65536 ports,
> so you can register all of those, or possibly limit it further to
> 1024 or 4096 ports, whichever matches the bus implementation.
> 
> 	Arnd
> 
> .
> 

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-10 12:36               ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-10 12:36 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: mark.rutland, devicetree, lorenzo.pieralisi, Gabriele Paoloni,
	minyard, linux-pci, benh, John Garry, will.deacon, linux-kernel,
	xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.mar

Hi, Arnd,

On 2016/11/10 17:12, Arnd Bergmann wrote:
> On Thursday, November 10, 2016 2:40:26 PM CET zhichang.yuan wrote:
>> On 2016/11/10 5:34, Arnd Bergmann wrote:
>>> On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni wrote:
>>>>> On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
>>>>>> +       /*
>>>>>> +        * The first PCIBIOS_MIN_IO is reserved specifically for
>>>>> indirectIO.
>>>>>> +        * It will separate indirectIO range from pci host bridge to
>>>>>> +        * avoid the possible PIO conflict.
>>>>>> +        * Set the indirectIO range directly here.
>>>>>> +        */
>>>>>> +       lpcdev->io_ops.start = 0;
>>>>>> +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
>>>>>> +       lpcdev->io_ops.devpara = lpcdev;
>>>>>> +       lpcdev->io_ops.pfin = hisilpc_comm_in;
>>>>>> +       lpcdev->io_ops.pfout = hisilpc_comm_out;
>>>>>> +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
>>>>>> +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
>>>>>
>>>>> I have to look at patch 2 in more detail again, after missing a few
>>>>> review
>>>>> rounds. I'm still a bit skeptical about hardcoding a logical I/O port
>>>>> range here, and would hope that we can just go through the same
>>>>> assignment of logical port ranges that we have for PCI buses,
>>>>> decoupling
>>>>> the bus addresses from the linux-internal ones.
>>>>
>>>> The point here is that we want to avoid any conflict/overlap between
>>>> the LPC I/O space and the PCI I/O space. With the assignment above
>>>> we make sure that LPC never interfere with PCI I/O space.
>>>
>>> But we already abstract the PCI I/O space using dynamic registration.
>>> There is no need to hardcode the logical address for ISA, though
>>> I think we can hardcode the bus address to start at zero here.
>>
>> Do you means that we can pick up the maximal I/O address from all children's
>> device resources??
> 
> The driver should not look at the resources of its children, just
> register a range of addresses dynamically, as I suggested in an
> earlier review.
>
Sorry! I can't catch your idea yet:(

When to register the I/O range? Is it done just after the successfully
of_translate_address() during the children scanning?

If yes, when a child is scanning, there is no range data in arm64_extio_ops. The
addr_is_indirect_io() calling in of_get_isa_indirect_io() don't need. All we can
check is just whether the address to be translated is IO and is under a parent
device which has no 'ranges' property.

> 
> Your current version has
> 
>         if (arm64_extio_ops->pfout)                             \
>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>                        addr, value, sizeof(type));             \
> 
> Instead, just subtract the start of the range from the logical
> port number to transform it back into a bus-local port number:
> 
>         if (arm64_extio_ops->pfout)                             \
>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>                        addr - arm64_extio_ops->start, value, sizeof(type)); \
> 
I think there is some information needed sync.
In the old patch-set, we don't bypass the pci_address_to_pio() after
successfully of_translate_address(). In this way, we don't need to reserve any
PIO space for our LPC since the logical port are from the same mapping
algorithm. Based on this way, the port number in the device resource is logical
one, then we need to subtract the start of the resource to get back the
bus-local port.

>From V3, we don't apply the mapping based on pci_address_to_pio(), the
of_translate_address() return the bus-local port directly and store into
relevant device resource. So, in the current arm64_extio_ops->pfout(), the
reverse translation don't need anymore. The input "addr" is bus-local port now.


Thanks,
Zhichang


> We know that the ISA/LPC bus can only have up to 65536 ports,
> so you can register all of those, or possibly limit it further to
> 1024 or 4096 ports, whichever matches the bus implementation.
> 
> 	Arnd
> 
> .
> 

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-10 12:36               ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-10 12:36 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, Arnd,

On 2016/11/10 17:12, Arnd Bergmann wrote:
> On Thursday, November 10, 2016 2:40:26 PM CET zhichang.yuan wrote:
>> On 2016/11/10 5:34, Arnd Bergmann wrote:
>>> On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni wrote:
>>>>> On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
>>>>>> +       /*
>>>>>> +        * The first PCIBIOS_MIN_IO is reserved specifically for
>>>>> indirectIO.
>>>>>> +        * It will separate indirectIO range from pci host bridge to
>>>>>> +        * avoid the possible PIO conflict.
>>>>>> +        * Set the indirectIO range directly here.
>>>>>> +        */
>>>>>> +       lpcdev->io_ops.start = 0;
>>>>>> +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
>>>>>> +       lpcdev->io_ops.devpara = lpcdev;
>>>>>> +       lpcdev->io_ops.pfin = hisilpc_comm_in;
>>>>>> +       lpcdev->io_ops.pfout = hisilpc_comm_out;
>>>>>> +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
>>>>>> +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
>>>>>
>>>>> I have to look at patch 2 in more detail again, after missing a few
>>>>> review
>>>>> rounds. I'm still a bit skeptical about hardcoding a logical I/O port
>>>>> range here, and would hope that we can just go through the same
>>>>> assignment of logical port ranges that we have for PCI buses,
>>>>> decoupling
>>>>> the bus addresses from the linux-internal ones.
>>>>
>>>> The point here is that we want to avoid any conflict/overlap between
>>>> the LPC I/O space and the PCI I/O space. With the assignment above
>>>> we make sure that LPC never interfere with PCI I/O space.
>>>
>>> But we already abstract the PCI I/O space using dynamic registration.
>>> There is no need to hardcode the logical address for ISA, though
>>> I think we can hardcode the bus address to start at zero here.
>>
>> Do you means that we can pick up the maximal I/O address from all children's
>> device resources??
> 
> The driver should not look at the resources of its children, just
> register a range of addresses dynamically, as I suggested in an
> earlier review.
>
Sorry! I can't catch your idea yet:(

When to register the I/O range? Is it done just after the successfully
of_translate_address() during the children scanning?

If yes, when a child is scanning, there is no range data in arm64_extio_ops. The
addr_is_indirect_io() calling in of_get_isa_indirect_io() don't need. All we can
check is just whether the address to be translated is IO and is under a parent
device which has no 'ranges' property.

> 
> Your current version has
> 
>         if (arm64_extio_ops->pfout)                             \
>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>                        addr, value, sizeof(type));             \
> 
> Instead, just subtract the start of the range from the logical
> port number to transform it back into a bus-local port number:
> 
>         if (arm64_extio_ops->pfout)                             \
>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>                        addr - arm64_extio_ops->start, value, sizeof(type)); \
> 
I think there is some information needed sync.
In the old patch-set, we don't bypass the pci_address_to_pio() after
successfully of_translate_address(). In this way, we don't need to reserve any
PIO space for our LPC since the logical port are from the same mapping
algorithm. Based on this way, the port number in the device resource is logical
one, then we need to subtract the start of the resource to get back the
bus-local port.

>From V3, we don't apply the mapping based on pci_address_to_pio(), the
of_translate_address() return the bus-local port directly and store into
relevant device resource. So, in the current arm64_extio_ops->pfout(), the
reverse translation don't need anymore. The input "addr" is bus-local port now.


Thanks,
Zhichang


> We know that the ISA/LPC bus can only have up to 65536 ports,
> so you can register all of those, or possibly limit it further to
> 1024 or 4096 ports, whichever matches the bus implementation.
> 
> 	Arnd
> 
> .
> 

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-10  9:12             ` Arnd Bergmann
  (?)
  (?)
@ 2016-11-10 15:36               ` Gabriele Paoloni
  -1 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-10 15:36 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: Yuanzhichang, mark.rutland, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, benh, John Garry, will.deacon, linux-kernel,
	xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, liviu.dudau, bhelgaas, zhichang.yuan02

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 10 November 2016 09:12
> To: linux-arm-kernel@lists.infradead.org
> Cc: Yuanzhichang; mark.rutland@arm.com; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; Gabriele Paoloni; minyard@acm.org; linux-
> pci@vger.kernel.org; benh@kernel.crashing.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; xuwei (O); Linuxarm;
> zourongrong@gmail.com; robh+dt@kernel.org; kantyzc@163.com; linux-
> serial@vger.kernel.org; catalin.marinas@arm.com; olof@lixom.net;
> liviu.dudau@arm.com; bhelgaas@google.com; zhichang.yuan02@gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, November 10, 2016 2:40:26 PM CET zhichang.yuan wrote:
> > On 2016/11/10 5:34, Arnd Bergmann wrote:
> > > On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni
> wrote:
> > >>> On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
> > >>>> +       /*
> > >>>> +        * The first PCIBIOS_MIN_IO is reserved specifically for
> > >>> indirectIO.
> > >>>> +        * It will separate indirectIO range from pci host
> bridge to
> > >>>> +        * avoid the possible PIO conflict.
> > >>>> +        * Set the indirectIO range directly here.
> > >>>> +        */
> > >>>> +       lpcdev->io_ops.start = 0;
> > >>>> +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> > >>>> +       lpcdev->io_ops.devpara = lpcdev;
> > >>>> +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> > >>>> +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> > >>>> +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> > >>>> +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
> > >>>
> > >>> I have to look at patch 2 in more detail again, after missing a
> few
> > >>> review
> > >>> rounds. I'm still a bit skeptical about hardcoding a logical I/O
> port
> > >>> range here, and would hope that we can just go through the same
> > >>> assignment of logical port ranges that we have for PCI buses,
> > >>> decoupling
> > >>> the bus addresses from the linux-internal ones.
> > >>
> > >> The point here is that we want to avoid any conflict/overlap
> between
> > >> the LPC I/O space and the PCI I/O space. With the assignment above
> > >> we make sure that LPC never interfere with PCI I/O space.
> > >
> > > But we already abstract the PCI I/O space using dynamic
> registration.
> > > There is no need to hardcode the logical address for ISA, though
> > > I think we can hardcode the bus address to start at zero here.
> >
> > Do you means that we can pick up the maximal I/O address from all
> children's
> > device resources??
> 
> The driver should not look at the resources of its children, just
> register a range of addresses dynamically, as I suggested in an
> earlier review.

Where should we get the range from? For LPC we know that it is going
Work on anything that is not used by PCI I/O space, and this is 
why we use [0, PCIBIOS_MIN_IO]

> 
> 
> Your current version has
> 
>         if (arm64_extio_ops->pfout)                             \
>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>                        addr, value, sizeof(type));             \
> 
> Instead, just subtract the start of the range from the logical
> port number to transform it back into a bus-local port number:

These accessors do not operate on IO tokens:

If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
addr is not going to be an I/O token; in fact patch 2/3 imposes that
the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to PCIBIOS_MIN_IO
we have free physical addresses that the accessors can operate on.

Thanks

Gab 

> 
>         if (arm64_extio_ops->pfout)                             \
>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>                        addr - arm64_extio_ops->start, value,
> sizeof(type)); \
> 
> We know that the ISA/LPC bus can only have up to 65536 ports,
> so you can register all of those, or possibly limit it further to
> 1024 or 4096 ports, whichever matches the bus implementation.
> 
> 	Arnd

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-10 15:36               ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-10 15:36 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: Yuanzhichang, mark.rutland, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, benh, John Garry, will.deacon, linux-kernel,
	xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 10 November 2016 09:12
> To: linux-arm-kernel@lists.infradead.org
> Cc: Yuanzhichang; mark.rutland@arm.com; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; Gabriele Paoloni; minyard@acm.org; linux-
> pci@vger.kernel.org; benh@kernel.crashing.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; xuwei (O); Linuxarm;
> zourongrong@gmail.com; robh+dt@kernel.org; kantyzc@163.com; linux-
> serial@vger.kernel.org; catalin.marinas@arm.com; olof@lixom.net;
> liviu.dudau@arm.com; bhelgaas@google.com; zhichang.yuan02@gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, November 10, 2016 2:40:26 PM CET zhichang.yuan wrote:
> > On 2016/11/10 5:34, Arnd Bergmann wrote:
> > > On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni
> wrote:
> > >>> On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
> > >>>> +       /*
> > >>>> +        * The first PCIBIOS_MIN_IO is reserved specifically for
> > >>> indirectIO.
> > >>>> +        * It will separate indirectIO range from pci host
> bridge to
> > >>>> +        * avoid the possible PIO conflict.
> > >>>> +        * Set the indirectIO range directly here.
> > >>>> +        */
> > >>>> +       lpcdev->io_ops.start = 0;
> > >>>> +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> > >>>> +       lpcdev->io_ops.devpara = lpcdev;
> > >>>> +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> > >>>> +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> > >>>> +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> > >>>> +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
> > >>>
> > >>> I have to look at patch 2 in more detail again, after missing a
> few
> > >>> review
> > >>> rounds. I'm still a bit skeptical about hardcoding a logical I/O
> port
> > >>> range here, and would hope that we can just go through the same
> > >>> assignment of logical port ranges that we have for PCI buses,
> > >>> decoupling
> > >>> the bus addresses from the linux-internal ones.
> > >>
> > >> The point here is that we want to avoid any conflict/overlap
> between
> > >> the LPC I/O space and the PCI I/O space. With the assignment above
> > >> we make sure that LPC never interfere with PCI I/O space.
> > >
> > > But we already abstract the PCI I/O space using dynamic
> registration.
> > > There is no need to hardcode the logical address for ISA, though
> > > I think we can hardcode the bus address to start at zero here.
> >
> > Do you means that we can pick up the maximal I/O address from all
> children's
> > device resources??
> 
> The driver should not look at the resources of its children, just
> register a range of addresses dynamically, as I suggested in an
> earlier review.

Where should we get the range from? For LPC we know that it is going
Work on anything that is not used by PCI I/O space, and this is 
why we use [0, PCIBIOS_MIN_IO]

> 
> 
> Your current version has
> 
>         if (arm64_extio_ops->pfout)                             \
>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>                        addr, value, sizeof(type));             \
> 
> Instead, just subtract the start of the range from the logical
> port number to transform it back into a bus-local port number:

These accessors do not operate on IO tokens:

If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
addr is not going to be an I/O token; in fact patch 2/3 imposes that
the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to PCIBIOS_MIN_IO
we have free physical addresses that the accessors can operate on.

Thanks

Gab 

> 
>         if (arm64_extio_ops->pfout)                             \
>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>                        addr - arm64_extio_ops->start, value,
> sizeof(type)); \
> 
> We know that the ISA/LPC bus can only have up to 65536 ports,
> so you can register all of those, or possibly limit it further to
> 1024 or 4096 ports, whichever matches the bus implementation.
> 
> 	Arnd

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-10 15:36               ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-10 15:36 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: Yuanzhichang, mark.rutland, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, benh, John Garry, will.deacon, linux-kernel,
	xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, liviu.dudau, bhelgaas, zhichang.yuan02

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 10 November 2016 09:12
> To: linux-arm-kernel@lists.infradead.org
> Cc: Yuanzhichang; mark.rutland@arm.com; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; Gabriele Paoloni; minyard@acm.org; linux-
> pci@vger.kernel.org; benh@kernel.crashing.org; John Garry;
> will.deacon@arm.com; linux-kernel@vger.kernel.org; xuwei (O); Linuxarm;
> zourongrong@gmail.com; robh+dt@kernel.org; kantyzc@163.com; linux-
> serial@vger.kernel.org; catalin.marinas@arm.com; olof@lixom.net;
> liviu.dudau@arm.com; bhelgaas@google.com; zhichang.yuan02@gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, November 10, 2016 2:40:26 PM CET zhichang.yuan wrote:
> > On 2016/11/10 5:34, Arnd Bergmann wrote:
> > > On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni
> wrote:
> > >>> On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
> > >>>> +       /*
> > >>>> +        * The first PCIBIOS_MIN_IO is reserved specifically for
> > >>> indirectIO.
> > >>>> +        * It will separate indirectIO range from pci host
> bridge to
> > >>>> +        * avoid the possible PIO conflict.
> > >>>> +        * Set the indirectIO range directly here.
> > >>>> +        */
> > >>>> +       lpcdev->io_ops.start = 0;
> > >>>> +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> > >>>> +       lpcdev->io_ops.devpara = lpcdev;
> > >>>> +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> > >>>> +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> > >>>> +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> > >>>> +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
> > >>>
> > >>> I have to look at patch 2 in more detail again, after missing a
> few
> > >>> review
> > >>> rounds. I'm still a bit skeptical about hardcoding a logical I/O
> port
> > >>> range here, and would hope that we can just go through the same
> > >>> assignment of logical port ranges that we have for PCI buses,
> > >>> decoupling
> > >>> the bus addresses from the linux-internal ones.
> > >>
> > >> The point here is that we want to avoid any conflict/overlap
> between
> > >> the LPC I/O space and the PCI I/O space. With the assignment above
> > >> we make sure that LPC never interfere with PCI I/O space.
> > >
> > > But we already abstract the PCI I/O space using dynamic
> registration.
> > > There is no need to hardcode the logical address for ISA, though
> > > I think we can hardcode the bus address to start at zero here.
> >
> > Do you means that we can pick up the maximal I/O address from all
> children's
> > device resources??
> 
> The driver should not look at the resources of its children, just
> register a range of addresses dynamically, as I suggested in an
> earlier review.

Where should we get the range from? For LPC we know that it is going
Work on anything that is not used by PCI I/O space, and this is 
why we use [0, PCIBIOS_MIN_IO]

> 
> 
> Your current version has
> 
>         if (arm64_extio_ops->pfout)                             \
>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>                        addr, value, sizeof(type));             \
> 
> Instead, just subtract the start of the range from the logical
> port number to transform it back into a bus-local port number:

These accessors do not operate on IO tokens:

If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
addr is not going to be an I/O token; in fact patch 2/3 imposes that
the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to PCIBIOS_MIN_IO
we have free physical addresses that the accessors can operate on.

Thanks

Gab 

> 
>         if (arm64_extio_ops->pfout)                             \
>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>                        addr - arm64_extio_ops->start, value,
> sizeof(type)); \
> 
> We know that the ISA/LPC bus can only have up to 65536 ports,
> so you can register all of those, or possibly limit it further to
> 1024 or 4096 ports, whichever matches the bus implementation.
> 
> 	Arnd

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-10 15:36               ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-10 15:36 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 10 November 2016 09:12
> To: linux-arm-kernel at lists.infradead.org
> Cc: Yuanzhichang; mark.rutland at arm.com; devicetree at vger.kernel.org;
> lorenzo.pieralisi at arm.com; Gabriele Paoloni; minyard at acm.org; linux-
> pci at vger.kernel.org; benh at kernel.crashing.org; John Garry;
> will.deacon at arm.com; linux-kernel at vger.kernel.org; xuwei (O); Linuxarm;
> zourongrong at gmail.com; robh+dt at kernel.org; kantyzc at 163.com; linux-
> serial at vger.kernel.org; catalin.marinas at arm.com; olof at lixom.net;
> liviu.dudau at arm.com; bhelgaas at google.com; zhichang.yuan02 at gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, November 10, 2016 2:40:26 PM CET zhichang.yuan wrote:
> > On 2016/11/10 5:34, Arnd Bergmann wrote:
> > > On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni
> wrote:
> > >>> On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:
> > >>>> +       /*
> > >>>> +        * The first PCIBIOS_MIN_IO is reserved specifically for
> > >>> indirectIO.
> > >>>> +        * It will separate indirectIO range from pci host
> bridge to
> > >>>> +        * avoid the possible PIO conflict.
> > >>>> +        * Set the indirectIO range directly here.
> > >>>> +        */
> > >>>> +       lpcdev->io_ops.start = 0;
> > >>>> +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> > >>>> +       lpcdev->io_ops.devpara = lpcdev;
> > >>>> +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> > >>>> +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> > >>>> +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> > >>>> +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;
> > >>>
> > >>> I have to look at patch 2 in more detail again, after missing a
> few
> > >>> review
> > >>> rounds. I'm still a bit skeptical about hardcoding a logical I/O
> port
> > >>> range here, and would hope that we can just go through the same
> > >>> assignment of logical port ranges that we have for PCI buses,
> > >>> decoupling
> > >>> the bus addresses from the linux-internal ones.
> > >>
> > >> The point here is that we want to avoid any conflict/overlap
> between
> > >> the LPC I/O space and the PCI I/O space. With the assignment above
> > >> we make sure that LPC never interfere with PCI I/O space.
> > >
> > > But we already abstract the PCI I/O space using dynamic
> registration.
> > > There is no need to hardcode the logical address for ISA, though
> > > I think we can hardcode the bus address to start at zero here.
> >
> > Do you means that we can pick up the maximal I/O address from all
> children's
> > device resources??
> 
> The driver should not look at the resources of its children, just
> register a range of addresses dynamically, as I suggested in an
> earlier review.

Where should we get the range from? For LPC we know that it is going
Work on anything that is not used by PCI I/O space, and this is 
why we use [0, PCIBIOS_MIN_IO]

> 
> 
> Your current version has
> 
>         if (arm64_extio_ops->pfout)                             \
>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>                        addr, value, sizeof(type));             \
> 
> Instead, just subtract the start of the range from the logical
> port number to transform it back into a bus-local port number:

These accessors do not operate on IO tokens:

If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
addr is not going to be an I/O token; in fact patch 2/3 imposes that
the I/O tokens will start@PCIBIOS_MIN_IO. So from 0 to PCIBIOS_MIN_IO
we have free physical addresses that the accessors can operate on.

Thanks

Gab 

> 
>         if (arm64_extio_ops->pfout)                             \
>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>                        addr - arm64_extio_ops->start, value,
> sizeof(type)); \
> 
> We know that the ISA/LPC bus can only have up to 65536 ports,
> so you can register all of those, or possibly limit it further to
> 1024 or 4096 ports, whichever matches the bus implementation.
> 
> 	Arnd

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

* RE: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-10 16:06           ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-10 16:06 UTC (permalink / raw)
  To: liviu.dudau
  Cc: Yuanzhichang, catalin.marinas, will.deacon, robh+dt, bhelgaas,
	mark.rutland, olof, arnd, linux-arm-kernel, lorenzo.pieralisi,
	linux-kernel, Linuxarm, devicetree, linux-pci, linux-serial,
	minyard, benh, zourongrong, John Garry, zhichang.yuan02, kantyzc,
	xuwei (O)

Hi Liviu

> -----Original Message-----
> From: liviu.dudau@arm.com [mailto:liviu.dudau@arm.com]
> Sent: 09 November 2016 16:51
> To: Gabriele Paoloni
> Cc: Yuanzhichang; catalin.marinas@arm.com; will.deacon@arm.com;
> robh+dt@kernel.org; bhelgaas@google.com; mark.rutland@arm.com;
> olof@lixom.net; arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> lorenzo.pieralisi@arm.com; linux-kernel@vger.kernel.org; Linuxarm;
> devicetree@vger.kernel.org; linux-pci@vger.kernel.org; linux-
> serial@vger.kernel.org; minyard@acm.org; benh@kernel.crashing.org;
> zourongrong@gmail.com; John Garry; zhichang.yuan02@gmail.com;
> kantyzc@163.com; xuwei (O)
> Subject: Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for
> special ISA
> 
> On Wed, Nov 09, 2016 at 04:16:17PM +0000, Gabriele Paoloni wrote:
> > Hi Liviu
> >
> > Thanks for reviewing
> >
> 
> [removed some irrelevant part of discussion, avoid crazy formatting]
> 
> > > > +/**
> > > > + * addr_is_indirect_io - check whether the input taddr is for
> > > indirectIO.
> > > > + * @taddr: the io address to be checked.
> > > > + *
> > > > + * Returns 1 when taddr is in the range; otherwise return 0.
> > > > + */
> > > > +int addr_is_indirect_io(u64 taddr)
> > > > +{
> > > > +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end
> <
> > > taddr)
> > >
> > > start >= taddr ?
> >
> > Nope... if  (taddr < arm64_extio_ops->start || taddr >
> arm64_extio_ops->end)
> > then taddr is outside the range [start; end] and will return 0;
> otherwise
> > it will return 1...
> 
> Oops, sorry, did not pay attention to the returned value. The check is
> correct as it is, no need to change then.
> 
> >
> > >
> > > > +		return 0;
> > > > +
> > > > +	return 1;
> > > > +}
> > > >
> > > >  BUILD_EXTIO(b, u8)
> > > >
> > > > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > > > index 02b2903..cc2a05d 100644
> > > > --- a/drivers/of/address.c
> > > > +++ b/drivers/of/address.c
> > > > @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
> > > device_node *np)
> > > >  	return false;
> > > >  }
> > > >
> > > > +
> > > > +/*
> > > > + * of_isa_indirect_io - get the IO address from some isa reg
> > > property value.
> > > > + *	For some isa/lpc devices, no ranges property in ancestor
> node.
> > > > + *	The device addresses are described directly in their regs
> > > property.
> > > > + *	This fixup function will be called to get the IO address of
> > > isa/lpc
> > > > + *	devices when the normal of_translation failed.
> > > > + *
> > > > + * @parent:	points to the parent dts node;
> > > > + * @bus:		points to the of_bus which can be used to parse
> > > address;
> > > > + * @addr:	the address from reg property;
> > > > + * @na:		the address cell counter of @addr;
> > > > + * @presult:	store the address paresed from @addr;
> > > > + *
> > > > + * return 1 when successfully get the I/O address;
> > > > + * 0 will return for some failures.
> > >
> > > Bah, you are returning a signed int, why 0 for failure? Return a
> > > negative value with
> > > error codes. Otherwise change the return value into a bool.
> >
> > Yes we'll move to bool
> >
> > >
> > > > + */
> > > > +static int of_get_isa_indirect_io(struct device_node *parent,
> > > > +				struct of_bus *bus, __be32 *addr,
> > > > +				int na, u64 *presult)
> > > > +{
> > > > +	unsigned int flags;
> > > > +	unsigned int rlen;
> > > > +
> > > > +	/* whether support indirectIO */
> > > > +	if (!indirect_io_enabled())
> > > > +		return 0;
> > > > +
> > > > +	if (!of_bus_isa_match(parent))
> > > > +		return 0;
> > > > +
> > > > +	flags = bus->get_flags(addr);
> > > > +	if (!(flags & IORESOURCE_IO))
> > > > +		return 0;
> > > > +
> > > > +	/* there is ranges property, apply the normal translation
> > > directly. */
> > >
> > > s/there is ranges/if we have a 'ranges'/
> >
> > Thanks for spotting this
> >
> > >
> > > > +	if (of_get_property(parent, "ranges", &rlen))
> > > > +		return 0;
> > > > +
> > > > +	*presult = of_read_number(addr + 1, na - 1);
> > > > +	/* this fixup is only valid for specific I/O range. */
> > > > +	return addr_is_indirect_io(*presult);
> > > > +}
> > > > +
> > > >  static int of_translate_one(struct device_node *parent, struct
> > > of_bus *bus,
> > > >  			    struct of_bus *pbus, __be32 *addr,
> > > >  			    int na, int ns, int pna, const char *rprop)
> > > > @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
> > > device_node *dev,
> > > >  			result = of_read_number(addr, na);
> > > >  			break;
> > > >  		}
> > > > +		/*
> > > > +		 * For indirectIO device which has no ranges
> property, get
> > > > +		 * the address from reg directly.
> > > > +		 */
> > > > +		if (of_get_isa_indirect_io(dev, bus, addr, na,
> &result)) {
> > > > +			pr_debug("isa indirectIO matched(%s)..addr =
> > > 0x%llx\n",
> > > > +				of_node_full_name(dev), result);
> > > > +			break;
> > > > +		}
> > > >
> > > >  		/* Get new parent bus and counts */
> > > >  		pbus = of_match_bus(parent);
> > > > @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
> > > device_node *dev,
> > > >  	if (taddr == OF_BAD_ADDR)
> > > >  		return -EINVAL;
> > > >  	memset(r, 0, sizeof(struct resource));
> > > > -	if (flags & IORESOURCE_IO) {
> > > > +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
> > > >  		unsigned long port;
> > > > +
> > > >  		port = pci_address_to_pio(taddr);
> > > >  		if (port == (unsigned long)-1)
> > > >  			return -EINVAL;
> > > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > > > index ba34907..1a08511 100644
> > > > --- a/drivers/pci/pci.c
> > > > +++ b/drivers/pci/pci.c
> > > > @@ -3263,7 +3263,7 @@ 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;
> > > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > > >
> > > >  	/* check if the range hasn't been previously recorded */
> > > >  	spin_lock(&io_range_lock);
> > > > @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned
> long
> > > pio)
> > > >
> > > >  #ifdef PCI_IOBASE
> > > >  	struct io_range *range;
> > > > -	resource_size_t allocated_size = 0;
> > > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > >
> > > Have you checked that pci_pio_to_address still returns valid values
> > > after this? I know that
> > > you are trying to take into account PCIBIOS_MIN_IO limit when
> > > allocating reserving the IO ranges,
> > > but the values added in the io_range_list are still starting from
> zero,
> > > no from PCIBIOS_MIN_IO,
> >
> > I think you're wrong here as in pci_address_to_pio we have:
> > +	resource_size_t offset = PCIBIOS_MIN_IO;
> >
> > This should be enough to guarantee that the PIOs start at
> > PCIBIOS_MIN_IO...right?
> 
> I don't think you can guarantee that the pio value that gets passed
> into
> pci_pio_to_address() always comes from a previously returned value by
> pci_address_to_pio(). Maybe you can add a check in pci_pio_to_address()

Maybe I am missing something...could you make an exampleof a case
where an IO toke doesn’t come from pci_address_to_pio() ?

Thanks

Gab


> 
> 	if (pio < PCIBIOS_MIN_IO)
> 		return address;
> 
> to avoid adding more checks in the list_for_each_entry() loop.
> 
> Best regards,
> Liviu
> 
> >
> >
> > > so the calculation of the address in this function could return
> > > negative values casted to pci_addr_t.
> > >
> > > Maybe you want to adjust the range->start value in
> > > pci_register_io_range() as well to have it
> > > offset by PCIBIOS_MIN_IO as well.
> > >
> > > Best regards,
> > > Liviu
> > >
> > > >
> > > >  	if (pio > IO_SPACE_LIMIT)
> > > >  		return address;
> > > > @@ -3335,7 +3335,7 @@ unsigned long __weak
> > > pci_address_to_pio(phys_addr_t address)
> > > >  {
> > > >  #ifdef PCI_IOBASE
> > > >  	struct io_range *res;
> > > > -	resource_size_t offset = 0;
> > > > +	resource_size_t offset = PCIBIOS_MIN_IO;
> > > >  	unsigned long addr = -1;
> > > >
> > > >  	spin_lock(&io_range_lock);
> > > > diff --git a/include/linux/of_address.h
> b/include/linux/of_address.h
> > > > index 3786473..deec469 100644
> > > > --- a/include/linux/of_address.h
> > > > +++ b/include/linux/of_address.h
> > > > @@ -24,6 +24,23 @@ struct of_pci_range {
> > > >  #define for_each_of_pci_range(parser, range) \
> > > >  	for (; of_pci_range_parser_one(parser, range);)
> > > >
> > > > +
> > > > +#ifndef indirect_io_enabled
> > > > +#define indirect_io_enabled indirect_io_enabled
> > > > +static inline bool indirect_io_enabled(void)
> > > > +{
> > > > +	return false;
> > > > +}
> > > > +#endif
> > > > +
> > > > +#ifndef addr_is_indirect_io
> > > > +#define addr_is_indirect_io addr_is_indirect_io
> > > > +static inline int addr_is_indirect_io(u64 taddr)
> > > > +{
> > > > +	return 0;
> > > > +}
> > > > +#endif
> > > > +
> > > >  /* Translate a DMA address from device space to CPU space */
> > > >  extern u64 of_translate_dma_address(struct device_node *dev,
> > > >  				    const __be32 *in_addr);
> > > > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > > > index 0e49f70..7f6bbb6 100644
> > > > --- a/include/linux/pci.h
> > > > +++ b/include/linux/pci.h
> > > > @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
> > > pci_bus *bus)
> > > >  /* provide the legacy pci_dma_* API */
> > > >  #include <linux/pci-dma-compat.h>
> > > >
> > > > +/*
> > > > + * define this macro here to refrain from compilation error for
> some
> > > > + * platforms. Please keep this macro at the end of this header
> file.
> > > > + */
> > > > +#ifndef PCIBIOS_MIN_IO
> > > > +#define PCIBIOS_MIN_IO		0
> > > > +#endif
> > > > +
> > > >  #endif /* LINUX_PCI_H */
> > > > --
> > > > 1.9.1
> > > >
> > > > --
> > > > To unsubscribe from this list: send the line "unsubscribe linux-
> pci"
> > > in
> > > > the body of a message to majordomo@vger.kernel.org
> > > > More majordomo info at  http://vger.kernel.org/majordomo-
> info.html
> 
> --
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ¯\_(ツ)_/¯

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

* RE: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-10 16:06           ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-10 16:06 UTC (permalink / raw)
  To: liviu.dudau-5wv7dgnIgG8
  Cc: Yuanzhichang, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, mark.rutland-5wv7dgnIgG8,
	olof-nZhT3qVonbNeoWH0uzbU5w, arnd-r2nGTMty4D4,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	lorenzo.pieralisi-5wv7dgnIgG8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Linuxarm,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	minyard-HInyCGIudOg@public.gmane.org

Hi Liviu

> -----Original Message-----
> From: liviu.dudau@arm.com [mailto:liviu.dudau@arm.com]
> Sent: 09 November 2016 16:51
> To: Gabriele Paoloni
> Cc: Yuanzhichang; catalin.marinas@arm.com; will.deacon@arm.com;
> robh+dt@kernel.org; bhelgaas@google.com; mark.rutland@arm.com;
> olof@lixom.net; arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> lorenzo.pieralisi@arm.com; linux-kernel@vger.kernel.org; Linuxarm;
> devicetree@vger.kernel.org; linux-pci@vger.kernel.org; linux-
> serial@vger.kernel.org; minyard@acm.org; benh@kernel.crashing.org;
> zourongrong@gmail.com; John Garry; zhichang.yuan02@gmail.com;
> kantyzc@163.com; xuwei (O)
> Subject: Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for
> special ISA
> 
> On Wed, Nov 09, 2016 at 04:16:17PM +0000, Gabriele Paoloni wrote:
> > Hi Liviu
> >
> > Thanks for reviewing
> >
> 
> [removed some irrelevant part of discussion, avoid crazy formatting]
> 
> > > > +/**
> > > > + * addr_is_indirect_io - check whether the input taddr is for
> > > indirectIO.
> > > > + * @taddr: the io address to be checked.
> > > > + *
> > > > + * Returns 1 when taddr is in the range; otherwise return 0.
> > > > + */
> > > > +int addr_is_indirect_io(u64 taddr)
> > > > +{
> > > > +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end
> <
> > > taddr)
> > >
> > > start >= taddr ?
> >
> > Nope... if  (taddr < arm64_extio_ops->start || taddr >
> arm64_extio_ops->end)
> > then taddr is outside the range [start; end] and will return 0;
> otherwise
> > it will return 1...
> 
> Oops, sorry, did not pay attention to the returned value. The check is
> correct as it is, no need to change then.
> 
> >
> > >
> > > > +		return 0;
> > > > +
> > > > +	return 1;
> > > > +}
> > > >
> > > >  BUILD_EXTIO(b, u8)
> > > >
> > > > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > > > index 02b2903..cc2a05d 100644
> > > > --- a/drivers/of/address.c
> > > > +++ b/drivers/of/address.c
> > > > @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
> > > device_node *np)
> > > >  	return false;
> > > >  }
> > > >
> > > > +
> > > > +/*
> > > > + * of_isa_indirect_io - get the IO address from some isa reg
> > > property value.
> > > > + *	For some isa/lpc devices, no ranges property in ancestor
> node.
> > > > + *	The device addresses are described directly in their regs
> > > property.
> > > > + *	This fixup function will be called to get the IO address of
> > > isa/lpc
> > > > + *	devices when the normal of_translation failed.
> > > > + *
> > > > + * @parent:	points to the parent dts node;
> > > > + * @bus:		points to the of_bus which can be used to parse
> > > address;
> > > > + * @addr:	the address from reg property;
> > > > + * @na:		the address cell counter of @addr;
> > > > + * @presult:	store the address paresed from @addr;
> > > > + *
> > > > + * return 1 when successfully get the I/O address;
> > > > + * 0 will return for some failures.
> > >
> > > Bah, you are returning a signed int, why 0 for failure? Return a
> > > negative value with
> > > error codes. Otherwise change the return value into a bool.
> >
> > Yes we'll move to bool
> >
> > >
> > > > + */
> > > > +static int of_get_isa_indirect_io(struct device_node *parent,
> > > > +				struct of_bus *bus, __be32 *addr,
> > > > +				int na, u64 *presult)
> > > > +{
> > > > +	unsigned int flags;
> > > > +	unsigned int rlen;
> > > > +
> > > > +	/* whether support indirectIO */
> > > > +	if (!indirect_io_enabled())
> > > > +		return 0;
> > > > +
> > > > +	if (!of_bus_isa_match(parent))
> > > > +		return 0;
> > > > +
> > > > +	flags = bus->get_flags(addr);
> > > > +	if (!(flags & IORESOURCE_IO))
> > > > +		return 0;
> > > > +
> > > > +	/* there is ranges property, apply the normal translation
> > > directly. */
> > >
> > > s/there is ranges/if we have a 'ranges'/
> >
> > Thanks for spotting this
> >
> > >
> > > > +	if (of_get_property(parent, "ranges", &rlen))
> > > > +		return 0;
> > > > +
> > > > +	*presult = of_read_number(addr + 1, na - 1);
> > > > +	/* this fixup is only valid for specific I/O range. */
> > > > +	return addr_is_indirect_io(*presult);
> > > > +}
> > > > +
> > > >  static int of_translate_one(struct device_node *parent, struct
> > > of_bus *bus,
> > > >  			    struct of_bus *pbus, __be32 *addr,
> > > >  			    int na, int ns, int pna, const char *rprop)
> > > > @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
> > > device_node *dev,
> > > >  			result = of_read_number(addr, na);
> > > >  			break;
> > > >  		}
> > > > +		/*
> > > > +		 * For indirectIO device which has no ranges
> property, get
> > > > +		 * the address from reg directly.
> > > > +		 */
> > > > +		if (of_get_isa_indirect_io(dev, bus, addr, na,
> &result)) {
> > > > +			pr_debug("isa indirectIO matched(%s)..addr =
> > > 0x%llx\n",
> > > > +				of_node_full_name(dev), result);
> > > > +			break;
> > > > +		}
> > > >
> > > >  		/* Get new parent bus and counts */
> > > >  		pbus = of_match_bus(parent);
> > > > @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
> > > device_node *dev,
> > > >  	if (taddr == OF_BAD_ADDR)
> > > >  		return -EINVAL;
> > > >  	memset(r, 0, sizeof(struct resource));
> > > > -	if (flags & IORESOURCE_IO) {
> > > > +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
> > > >  		unsigned long port;
> > > > +
> > > >  		port = pci_address_to_pio(taddr);
> > > >  		if (port == (unsigned long)-1)
> > > >  			return -EINVAL;
> > > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > > > index ba34907..1a08511 100644
> > > > --- a/drivers/pci/pci.c
> > > > +++ b/drivers/pci/pci.c
> > > > @@ -3263,7 +3263,7 @@ 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;
> > > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > > >
> > > >  	/* check if the range hasn't been previously recorded */
> > > >  	spin_lock(&io_range_lock);
> > > > @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned
> long
> > > pio)
> > > >
> > > >  #ifdef PCI_IOBASE
> > > >  	struct io_range *range;
> > > > -	resource_size_t allocated_size = 0;
> > > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > >
> > > Have you checked that pci_pio_to_address still returns valid values
> > > after this? I know that
> > > you are trying to take into account PCIBIOS_MIN_IO limit when
> > > allocating reserving the IO ranges,
> > > but the values added in the io_range_list are still starting from
> zero,
> > > no from PCIBIOS_MIN_IO,
> >
> > I think you're wrong here as in pci_address_to_pio we have:
> > +	resource_size_t offset = PCIBIOS_MIN_IO;
> >
> > This should be enough to guarantee that the PIOs start at
> > PCIBIOS_MIN_IO...right?
> 
> I don't think you can guarantee that the pio value that gets passed
> into
> pci_pio_to_address() always comes from a previously returned value by
> pci_address_to_pio(). Maybe you can add a check in pci_pio_to_address()

Maybe I am missing something...could you make an exampleof a case
where an IO toke doesn’t come from pci_address_to_pio() ?

Thanks

Gab


> 
> 	if (pio < PCIBIOS_MIN_IO)
> 		return address;
> 
> to avoid adding more checks in the list_for_each_entry() loop.
> 
> Best regards,
> Liviu
> 
> >
> >
> > > so the calculation of the address in this function could return
> > > negative values casted to pci_addr_t.
> > >
> > > Maybe you want to adjust the range->start value in
> > > pci_register_io_range() as well to have it
> > > offset by PCIBIOS_MIN_IO as well.
> > >
> > > Best regards,
> > > Liviu
> > >
> > > >
> > > >  	if (pio > IO_SPACE_LIMIT)
> > > >  		return address;
> > > > @@ -3335,7 +3335,7 @@ unsigned long __weak
> > > pci_address_to_pio(phys_addr_t address)
> > > >  {
> > > >  #ifdef PCI_IOBASE
> > > >  	struct io_range *res;
> > > > -	resource_size_t offset = 0;
> > > > +	resource_size_t offset = PCIBIOS_MIN_IO;
> > > >  	unsigned long addr = -1;
> > > >
> > > >  	spin_lock(&io_range_lock);
> > > > diff --git a/include/linux/of_address.h
> b/include/linux/of_address.h
> > > > index 3786473..deec469 100644
> > > > --- a/include/linux/of_address.h
> > > > +++ b/include/linux/of_address.h
> > > > @@ -24,6 +24,23 @@ struct of_pci_range {
> > > >  #define for_each_of_pci_range(parser, range) \
> > > >  	for (; of_pci_range_parser_one(parser, range);)
> > > >
> > > > +
> > > > +#ifndef indirect_io_enabled
> > > > +#define indirect_io_enabled indirect_io_enabled
> > > > +static inline bool indirect_io_enabled(void)
> > > > +{
> > > > +	return false;
> > > > +}
> > > > +#endif
> > > > +
> > > > +#ifndef addr_is_indirect_io
> > > > +#define addr_is_indirect_io addr_is_indirect_io
> > > > +static inline int addr_is_indirect_io(u64 taddr)
> > > > +{
> > > > +	return 0;
> > > > +}
> > > > +#endif
> > > > +
> > > >  /* Translate a DMA address from device space to CPU space */
> > > >  extern u64 of_translate_dma_address(struct device_node *dev,
> > > >  				    const __be32 *in_addr);
> > > > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > > > index 0e49f70..7f6bbb6 100644
> > > > --- a/include/linux/pci.h
> > > > +++ b/include/linux/pci.h
> > > > @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
> > > pci_bus *bus)
> > > >  /* provide the legacy pci_dma_* API */
> > > >  #include <linux/pci-dma-compat.h>
> > > >
> > > > +/*
> > > > + * define this macro here to refrain from compilation error for
> some
> > > > + * platforms. Please keep this macro at the end of this header
> file.
> > > > + */
> > > > +#ifndef PCIBIOS_MIN_IO
> > > > +#define PCIBIOS_MIN_IO		0
> > > > +#endif
> > > > +
> > > >  #endif /* LINUX_PCI_H */
> > > > --
> > > > 1.9.1
> > > >
> > > > --
> > > > To unsubscribe from this list: send the line "unsubscribe linux-
> pci"
> > > in
> > > > the body of a message to majordomo@vger.kernel.org
> > > > More majordomo info at  http://vger.kernel.org/majordomo-
> info.html
> 
> --
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ¯\_(ツ)_/¯

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

* RE: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-10 16:06           ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-10 16:06 UTC (permalink / raw)
  To: liviu.dudau
  Cc: Yuanzhichang, catalin.marinas, will.deacon, robh+dt, bhelgaas,
	mark.rutland, olof, arnd, linux-arm-kernel, lorenzo.pieralisi,
	linux-kernel, Linuxarm, devicetree, linux-pci, linux-serial,
	minyard, benh, zourongrong, John Garry, zhichang.yuan02, kantyzc,
	xuwei (O)

SGkgTGl2aXUNCg0KPiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBsaXZpdS5k
dWRhdUBhcm0uY29tIFttYWlsdG86bGl2aXUuZHVkYXVAYXJtLmNvbV0NCj4gU2VudDogMDkgTm92
ZW1iZXIgMjAxNiAxNjo1MQ0KPiBUbzogR2FicmllbGUgUGFvbG9uaQ0KPiBDYzogWXVhbnpoaWNo
YW5nOyBjYXRhbGluLm1hcmluYXNAYXJtLmNvbTsgd2lsbC5kZWFjb25AYXJtLmNvbTsNCj4gcm9i
aCtkdEBrZXJuZWwub3JnOyBiaGVsZ2Fhc0Bnb29nbGUuY29tOyBtYXJrLnJ1dGxhbmRAYXJtLmNv
bTsNCj4gb2xvZkBsaXhvbS5uZXQ7IGFybmRAYXJuZGIuZGU7IGxpbnV4LWFybS1rZXJuZWxAbGlz
dHMuaW5mcmFkZWFkLm9yZzsNCj4gbG9yZW56by5waWVyYWxpc2lAYXJtLmNvbTsgbGludXgta2Vy
bmVsQHZnZXIua2VybmVsLm9yZzsgTGludXhhcm07DQo+IGRldmljZXRyZWVAdmdlci5rZXJuZWwu
b3JnOyBsaW51eC1wY2lAdmdlci5rZXJuZWwub3JnOyBsaW51eC0NCj4gc2VyaWFsQHZnZXIua2Vy
bmVsLm9yZzsgbWlueWFyZEBhY20ub3JnOyBiZW5oQGtlcm5lbC5jcmFzaGluZy5vcmc7DQo+IHpv
dXJvbmdyb25nQGdtYWlsLmNvbTsgSm9obiBHYXJyeTsgemhpY2hhbmcueXVhbjAyQGdtYWlsLmNv
bTsNCj4ga2FudHl6Y0AxNjMuY29tOyB4dXdlaSAoTykNCj4gU3ViamVjdDogUmU6IFtQQVRDSCBW
NSAyLzNdIEFSTTY0IExQQzogQWRkIG1pc3NpbmcgcmFuZ2UgZXhjZXB0aW9uIGZvcg0KPiBzcGVj
aWFsIElTQQ0KPiANCj4gT24gV2VkLCBOb3YgMDksIDIwMTYgYXQgMDQ6MTY6MTdQTSArMDAwMCwg
R2FicmllbGUgUGFvbG9uaSB3cm90ZToNCj4gPiBIaSBMaXZpdQ0KPiA+DQo+ID4gVGhhbmtzIGZv
ciByZXZpZXdpbmcNCj4gPg0KPiANCj4gW3JlbW92ZWQgc29tZSBpcnJlbGV2YW50IHBhcnQgb2Yg
ZGlzY3Vzc2lvbiwgYXZvaWQgY3JhenkgZm9ybWF0dGluZ10NCj4gDQo+ID4gPiA+ICsvKioNCj4g
PiA+ID4gKyAqIGFkZHJfaXNfaW5kaXJlY3RfaW8gLSBjaGVjayB3aGV0aGVyIHRoZSBpbnB1dCB0
YWRkciBpcyBmb3INCj4gPiA+IGluZGlyZWN0SU8uDQo+ID4gPiA+ICsgKiBAdGFkZHI6IHRoZSBp
byBhZGRyZXNzIHRvIGJlIGNoZWNrZWQuDQo+ID4gPiA+ICsgKg0KPiA+ID4gPiArICogUmV0dXJu
cyAxIHdoZW4gdGFkZHIgaXMgaW4gdGhlIHJhbmdlOyBvdGhlcndpc2UgcmV0dXJuIDAuDQo+ID4g
PiA+ICsgKi8NCj4gPiA+ID4gK2ludCBhZGRyX2lzX2luZGlyZWN0X2lvKHU2NCB0YWRkcikNCj4g
PiA+ID4gK3sNCj4gPiA+ID4gKwlpZiAoYXJtNjRfZXh0aW9fb3BzLT5zdGFydCA+IHRhZGRyIHx8
IGFybTY0X2V4dGlvX29wcy0+ZW5kDQo+IDwNCj4gPiA+IHRhZGRyKQ0KPiA+ID4NCj4gPiA+IHN0
YXJ0ID49IHRhZGRyID8NCj4gPg0KPiA+IE5vcGUuLi4gaWYgICh0YWRkciA8IGFybTY0X2V4dGlv
X29wcy0+c3RhcnQgfHwgdGFkZHIgPg0KPiBhcm02NF9leHRpb19vcHMtPmVuZCkNCj4gPiB0aGVu
IHRhZGRyIGlzIG91dHNpZGUgdGhlIHJhbmdlIFtzdGFydDsgZW5kXSBhbmQgd2lsbCByZXR1cm4g
MDsNCj4gb3RoZXJ3aXNlDQo+ID4gaXQgd2lsbCByZXR1cm4gMS4uLg0KPiANCj4gT29wcywgc29y
cnksIGRpZCBub3QgcGF5IGF0dGVudGlvbiB0byB0aGUgcmV0dXJuZWQgdmFsdWUuIFRoZSBjaGVj
ayBpcw0KPiBjb3JyZWN0IGFzIGl0IGlzLCBubyBuZWVkIHRvIGNoYW5nZSB0aGVuLg0KPiANCj4g
Pg0KPiA+ID4NCj4gPiA+ID4gKwkJcmV0dXJuIDA7DQo+ID4gPiA+ICsNCj4gPiA+ID4gKwlyZXR1
cm4gMTsNCj4gPiA+ID4gK30NCj4gPiA+ID4NCj4gPiA+ID4gIEJVSUxEX0VYVElPKGIsIHU4KQ0K
PiA+ID4gPg0KPiA+ID4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9vZi9hZGRyZXNzLmMgYi9kcml2
ZXJzL29mL2FkZHJlc3MuYw0KPiA+ID4gPiBpbmRleCAwMmIyOTAzLi5jYzJhMDVkIDEwMDY0NA0K
PiA+ID4gPiAtLS0gYS9kcml2ZXJzL29mL2FkZHJlc3MuYw0KPiA+ID4gPiArKysgYi9kcml2ZXJz
L29mL2FkZHJlc3MuYw0KPiA+ID4gPiBAQCAtNDc5LDYgKzQ3OSw1MCBAQCBzdGF0aWMgaW50IG9m
X2VtcHR5X3Jhbmdlc19xdWlyayhzdHJ1Y3QNCj4gPiA+IGRldmljZV9ub2RlICpucCkNCj4gPiA+
ID4gIAlyZXR1cm4gZmFsc2U7DQo+ID4gPiA+ICB9DQo+ID4gPiA+DQo+ID4gPiA+ICsNCj4gPiA+
ID4gKy8qDQo+ID4gPiA+ICsgKiBvZl9pc2FfaW5kaXJlY3RfaW8gLSBnZXQgdGhlIElPIGFkZHJl
c3MgZnJvbSBzb21lIGlzYSByZWcNCj4gPiA+IHByb3BlcnR5IHZhbHVlLg0KPiA+ID4gPiArICoJ
Rm9yIHNvbWUgaXNhL2xwYyBkZXZpY2VzLCBubyByYW5nZXMgcHJvcGVydHkgaW4gYW5jZXN0b3IN
Cj4gbm9kZS4NCj4gPiA+ID4gKyAqCVRoZSBkZXZpY2UgYWRkcmVzc2VzIGFyZSBkZXNjcmliZWQg
ZGlyZWN0bHkgaW4gdGhlaXIgcmVncw0KPiA+ID4gcHJvcGVydHkuDQo+ID4gPiA+ICsgKglUaGlz
IGZpeHVwIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIHRvIGdldCB0aGUgSU8gYWRkcmVzcyBvZg0K
PiA+ID4gaXNhL2xwYw0KPiA+ID4gPiArICoJZGV2aWNlcyB3aGVuIHRoZSBub3JtYWwgb2ZfdHJh
bnNsYXRpb24gZmFpbGVkLg0KPiA+ID4gPiArICoNCj4gPiA+ID4gKyAqIEBwYXJlbnQ6CXBvaW50
cyB0byB0aGUgcGFyZW50IGR0cyBub2RlOw0KPiA+ID4gPiArICogQGJ1czoJCXBvaW50cyB0byB0
aGUgb2ZfYnVzIHdoaWNoIGNhbiBiZSB1c2VkIHRvIHBhcnNlDQo+ID4gPiBhZGRyZXNzOw0KPiA+
ID4gPiArICogQGFkZHI6CXRoZSBhZGRyZXNzIGZyb20gcmVnIHByb3BlcnR5Ow0KPiA+ID4gPiAr
ICogQG5hOgkJdGhlIGFkZHJlc3MgY2VsbCBjb3VudGVyIG9mIEBhZGRyOw0KPiA+ID4gPiArICog
QHByZXN1bHQ6CXN0b3JlIHRoZSBhZGRyZXNzIHBhcmVzZWQgZnJvbSBAYWRkcjsNCj4gPiA+ID4g
KyAqDQo+ID4gPiA+ICsgKiByZXR1cm4gMSB3aGVuIHN1Y2Nlc3NmdWxseSBnZXQgdGhlIEkvTyBh
ZGRyZXNzOw0KPiA+ID4gPiArICogMCB3aWxsIHJldHVybiBmb3Igc29tZSBmYWlsdXJlcy4NCj4g
PiA+DQo+ID4gPiBCYWgsIHlvdSBhcmUgcmV0dXJuaW5nIGEgc2lnbmVkIGludCwgd2h5IDAgZm9y
IGZhaWx1cmU/IFJldHVybiBhDQo+ID4gPiBuZWdhdGl2ZSB2YWx1ZSB3aXRoDQo+ID4gPiBlcnJv
ciBjb2Rlcy4gT3RoZXJ3aXNlIGNoYW5nZSB0aGUgcmV0dXJuIHZhbHVlIGludG8gYSBib29sLg0K
PiA+DQo+ID4gWWVzIHdlJ2xsIG1vdmUgdG8gYm9vbA0KPiA+DQo+ID4gPg0KPiA+ID4gPiArICov
DQo+ID4gPiA+ICtzdGF0aWMgaW50IG9mX2dldF9pc2FfaW5kaXJlY3RfaW8oc3RydWN0IGRldmlj
ZV9ub2RlICpwYXJlbnQsDQo+ID4gPiA+ICsJCQkJc3RydWN0IG9mX2J1cyAqYnVzLCBfX2JlMzIg
KmFkZHIsDQo+ID4gPiA+ICsJCQkJaW50IG5hLCB1NjQgKnByZXN1bHQpDQo+ID4gPiA+ICt7DQo+
ID4gPiA+ICsJdW5zaWduZWQgaW50IGZsYWdzOw0KPiA+ID4gPiArCXVuc2lnbmVkIGludCBybGVu
Ow0KPiA+ID4gPiArDQo+ID4gPiA+ICsJLyogd2hldGhlciBzdXBwb3J0IGluZGlyZWN0SU8gKi8N
Cj4gPiA+ID4gKwlpZiAoIWluZGlyZWN0X2lvX2VuYWJsZWQoKSkNCj4gPiA+ID4gKwkJcmV0dXJu
IDA7DQo+ID4gPiA+ICsNCj4gPiA+ID4gKwlpZiAoIW9mX2J1c19pc2FfbWF0Y2gocGFyZW50KSkN
Cj4gPiA+ID4gKwkJcmV0dXJuIDA7DQo+ID4gPiA+ICsNCj4gPiA+ID4gKwlmbGFncyA9IGJ1cy0+
Z2V0X2ZsYWdzKGFkZHIpOw0KPiA+ID4gPiArCWlmICghKGZsYWdzICYgSU9SRVNPVVJDRV9JTykp
DQo+ID4gPiA+ICsJCXJldHVybiAwOw0KPiA+ID4gPiArDQo+ID4gPiA+ICsJLyogdGhlcmUgaXMg
cmFuZ2VzIHByb3BlcnR5LCBhcHBseSB0aGUgbm9ybWFsIHRyYW5zbGF0aW9uDQo+ID4gPiBkaXJl
Y3RseS4gKi8NCj4gPiA+DQo+ID4gPiBzL3RoZXJlIGlzIHJhbmdlcy9pZiB3ZSBoYXZlIGEgJ3Jh
bmdlcycvDQo+ID4NCj4gPiBUaGFua3MgZm9yIHNwb3R0aW5nIHRoaXMNCj4gPg0KPiA+ID4NCj4g
PiA+ID4gKwlpZiAob2ZfZ2V0X3Byb3BlcnR5KHBhcmVudCwgInJhbmdlcyIsICZybGVuKSkNCj4g
PiA+ID4gKwkJcmV0dXJuIDA7DQo+ID4gPiA+ICsNCj4gPiA+ID4gKwkqcHJlc3VsdCA9IG9mX3Jl
YWRfbnVtYmVyKGFkZHIgKyAxLCBuYSAtIDEpOw0KPiA+ID4gPiArCS8qIHRoaXMgZml4dXAgaXMg
b25seSB2YWxpZCBmb3Igc3BlY2lmaWMgSS9PIHJhbmdlLiAqLw0KPiA+ID4gPiArCXJldHVybiBh
ZGRyX2lzX2luZGlyZWN0X2lvKCpwcmVzdWx0KTsNCj4gPiA+ID4gK30NCj4gPiA+ID4gKw0KPiA+
ID4gPiAgc3RhdGljIGludCBvZl90cmFuc2xhdGVfb25lKHN0cnVjdCBkZXZpY2Vfbm9kZSAqcGFy
ZW50LCBzdHJ1Y3QNCj4gPiA+IG9mX2J1cyAqYnVzLA0KPiA+ID4gPiAgCQkJICAgIHN0cnVjdCBv
Zl9idXMgKnBidXMsIF9fYmUzMiAqYWRkciwNCj4gPiA+ID4gIAkJCSAgICBpbnQgbmEsIGludCBu
cywgaW50IHBuYSwgY29uc3QgY2hhciAqcnByb3ApDQo+ID4gPiA+IEBAIC01OTUsNiArNjM5LDE1
IEBAIHN0YXRpYyB1NjQgX19vZl90cmFuc2xhdGVfYWRkcmVzcyhzdHJ1Y3QNCj4gPiA+IGRldmlj
ZV9ub2RlICpkZXYsDQo+ID4gPiA+ICAJCQlyZXN1bHQgPSBvZl9yZWFkX251bWJlcihhZGRyLCBu
YSk7DQo+ID4gPiA+ICAJCQlicmVhazsNCj4gPiA+ID4gIAkJfQ0KPiA+ID4gPiArCQkvKg0KPiA+
ID4gPiArCQkgKiBGb3IgaW5kaXJlY3RJTyBkZXZpY2Ugd2hpY2ggaGFzIG5vIHJhbmdlcw0KPiBw
cm9wZXJ0eSwgZ2V0DQo+ID4gPiA+ICsJCSAqIHRoZSBhZGRyZXNzIGZyb20gcmVnIGRpcmVjdGx5
Lg0KPiA+ID4gPiArCQkgKi8NCj4gPiA+ID4gKwkJaWYgKG9mX2dldF9pc2FfaW5kaXJlY3RfaW8o
ZGV2LCBidXMsIGFkZHIsIG5hLA0KPiAmcmVzdWx0KSkgew0KPiA+ID4gPiArCQkJcHJfZGVidWco
ImlzYSBpbmRpcmVjdElPIG1hdGNoZWQoJXMpLi5hZGRyID0NCj4gPiA+IDB4JWxseFxuIiwNCj4g
PiA+ID4gKwkJCQlvZl9ub2RlX2Z1bGxfbmFtZShkZXYpLCByZXN1bHQpOw0KPiA+ID4gPiArCQkJ
YnJlYWs7DQo+ID4gPiA+ICsJCX0NCj4gPiA+ID4NCj4gPiA+ID4gIAkJLyogR2V0IG5ldyBwYXJl
bnQgYnVzIGFuZCBjb3VudHMgKi8NCj4gPiA+ID4gIAkJcGJ1cyA9IG9mX21hdGNoX2J1cyhwYXJl
bnQpOw0KPiA+ID4gPiBAQCAtNjg4LDggKzc0MSw5IEBAIHN0YXRpYyBpbnQgX19vZl9hZGRyZXNz
X3RvX3Jlc291cmNlKHN0cnVjdA0KPiA+ID4gZGV2aWNlX25vZGUgKmRldiwNCj4gPiA+ID4gIAlp
ZiAodGFkZHIgPT0gT0ZfQkFEX0FERFIpDQo+ID4gPiA+ICAJCXJldHVybiAtRUlOVkFMOw0KPiA+
ID4gPiAgCW1lbXNldChyLCAwLCBzaXplb2Yoc3RydWN0IHJlc291cmNlKSk7DQo+ID4gPiA+IC0J
aWYgKGZsYWdzICYgSU9SRVNPVVJDRV9JTykgew0KPiA+ID4gPiArCWlmIChmbGFncyAmIElPUkVT
T1VSQ0VfSU8gJiYgdGFkZHIgPj0gUENJQklPU19NSU5fSU8pIHsNCj4gPiA+ID4gIAkJdW5zaWdu
ZWQgbG9uZyBwb3J0Ow0KPiA+ID4gPiArDQo+ID4gPiA+ICAJCXBvcnQgPSBwY2lfYWRkcmVzc190
b19waW8odGFkZHIpOw0KPiA+ID4gPiAgCQlpZiAocG9ydCA9PSAodW5zaWduZWQgbG9uZyktMSkN
Cj4gPiA+ID4gIAkJCXJldHVybiAtRUlOVkFMOw0KPiA+ID4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVy
cy9wY2kvcGNpLmMgYi9kcml2ZXJzL3BjaS9wY2kuYw0KPiA+ID4gPiBpbmRleCBiYTM0OTA3Li4x
YTA4NTExIDEwMDY0NA0KPiA+ID4gPiAtLS0gYS9kcml2ZXJzL3BjaS9wY2kuYw0KPiA+ID4gPiAr
KysgYi9kcml2ZXJzL3BjaS9wY2kuYw0KPiA+ID4gPiBAQCAtMzI2Myw3ICszMjYzLDcgQEAgaW50
IF9fd2Vhaw0KPiBwY2lfcmVnaXN0ZXJfaW9fcmFuZ2UocGh5c19hZGRyX3QNCj4gPiA+IGFkZHIs
IHJlc291cmNlX3NpemVfdCBzaXplKQ0KPiA+ID4gPg0KPiA+ID4gPiAgI2lmZGVmIFBDSV9JT0JB
U0UNCj4gPiA+ID4gIAlzdHJ1Y3QgaW9fcmFuZ2UgKnJhbmdlOw0KPiA+ID4gPiAtCXJlc291cmNl
X3NpemVfdCBhbGxvY2F0ZWRfc2l6ZSA9IDA7DQo+ID4gPiA+ICsJcmVzb3VyY2Vfc2l6ZV90IGFs
bG9jYXRlZF9zaXplID0gUENJQklPU19NSU5fSU87DQo+ID4gPiA+DQo+ID4gPiA+ICAJLyogY2hl
Y2sgaWYgdGhlIHJhbmdlIGhhc24ndCBiZWVuIHByZXZpb3VzbHkgcmVjb3JkZWQgKi8NCj4gPiA+
ID4gIAlzcGluX2xvY2soJmlvX3JhbmdlX2xvY2spOw0KPiA+ID4gPiBAQCAtMzMxMiw3ICszMzEy
LDcgQEAgcGh5c19hZGRyX3QgcGNpX3Bpb190b19hZGRyZXNzKHVuc2lnbmVkDQo+IGxvbmcNCj4g
PiA+IHBpbykNCj4gPiA+ID4NCj4gPiA+ID4gICNpZmRlZiBQQ0lfSU9CQVNFDQo+ID4gPiA+ICAJ
c3RydWN0IGlvX3JhbmdlICpyYW5nZTsNCj4gPiA+ID4gLQlyZXNvdXJjZV9zaXplX3QgYWxsb2Nh
dGVkX3NpemUgPSAwOw0KPiA+ID4gPiArCXJlc291cmNlX3NpemVfdCBhbGxvY2F0ZWRfc2l6ZSA9
IFBDSUJJT1NfTUlOX0lPOw0KPiA+ID4NCj4gPiA+IEhhdmUgeW91IGNoZWNrZWQgdGhhdCBwY2lf
cGlvX3RvX2FkZHJlc3Mgc3RpbGwgcmV0dXJucyB2YWxpZCB2YWx1ZXMNCj4gPiA+IGFmdGVyIHRo
aXM/IEkga25vdyB0aGF0DQo+ID4gPiB5b3UgYXJlIHRyeWluZyB0byB0YWtlIGludG8gYWNjb3Vu
dCBQQ0lCSU9TX01JTl9JTyBsaW1pdCB3aGVuDQo+ID4gPiBhbGxvY2F0aW5nIHJlc2VydmluZyB0
aGUgSU8gcmFuZ2VzLA0KPiA+ID4gYnV0IHRoZSB2YWx1ZXMgYWRkZWQgaW4gdGhlIGlvX3Jhbmdl
X2xpc3QgYXJlIHN0aWxsIHN0YXJ0aW5nIGZyb20NCj4gemVybywNCj4gPiA+IG5vIGZyb20gUENJ
QklPU19NSU5fSU8sDQo+ID4NCj4gPiBJIHRoaW5rIHlvdSdyZSB3cm9uZyBoZXJlIGFzIGluIHBj
aV9hZGRyZXNzX3RvX3BpbyB3ZSBoYXZlOg0KPiA+ICsJcmVzb3VyY2Vfc2l6ZV90IG9mZnNldCA9
IFBDSUJJT1NfTUlOX0lPOw0KPiA+DQo+ID4gVGhpcyBzaG91bGQgYmUgZW5vdWdoIHRvIGd1YXJh
bnRlZSB0aGF0IHRoZSBQSU9zIHN0YXJ0IGF0DQo+ID4gUENJQklPU19NSU5fSU8uLi5yaWdodD8N
Cj4gDQo+IEkgZG9uJ3QgdGhpbmsgeW91IGNhbiBndWFyYW50ZWUgdGhhdCB0aGUgcGlvIHZhbHVl
IHRoYXQgZ2V0cyBwYXNzZWQNCj4gaW50bw0KPiBwY2lfcGlvX3RvX2FkZHJlc3MoKSBhbHdheXMg
Y29tZXMgZnJvbSBhIHByZXZpb3VzbHkgcmV0dXJuZWQgdmFsdWUgYnkNCj4gcGNpX2FkZHJlc3Nf
dG9fcGlvKCkuIE1heWJlIHlvdSBjYW4gYWRkIGEgY2hlY2sgaW4gcGNpX3Bpb190b19hZGRyZXNz
KCkNCg0KTWF5YmUgSSBhbSBtaXNzaW5nIHNvbWV0aGluZy4uLmNvdWxkIHlvdSBtYWtlIGFuIGV4
YW1wbGVvZiBhIGNhc2UNCndoZXJlIGFuIElPIHRva2UgZG9lc27igJl0IGNvbWUgZnJvbSBwY2lf
YWRkcmVzc190b19waW8oKSA/DQoNClRoYW5rcw0KDQpHYWINCg0KDQo+IA0KPiAJaWYgKHBpbyA8
IFBDSUJJT1NfTUlOX0lPKQ0KPiAJCXJldHVybiBhZGRyZXNzOw0KPiANCj4gdG8gYXZvaWQgYWRk
aW5nIG1vcmUgY2hlY2tzIGluIHRoZSBsaXN0X2Zvcl9lYWNoX2VudHJ5KCkgbG9vcC4NCj4gDQo+
IEJlc3QgcmVnYXJkcywNCj4gTGl2aXUNCj4gDQo+ID4NCj4gPg0KPiA+ID4gc28gdGhlIGNhbGN1
bGF0aW9uIG9mIHRoZSBhZGRyZXNzIGluIHRoaXMgZnVuY3Rpb24gY291bGQgcmV0dXJuDQo+ID4g
PiBuZWdhdGl2ZSB2YWx1ZXMgY2FzdGVkIHRvIHBjaV9hZGRyX3QuDQo+ID4gPg0KPiA+ID4gTWF5
YmUgeW91IHdhbnQgdG8gYWRqdXN0IHRoZSByYW5nZS0+c3RhcnQgdmFsdWUgaW4NCj4gPiA+IHBj
aV9yZWdpc3Rlcl9pb19yYW5nZSgpIGFzIHdlbGwgdG8gaGF2ZSBpdA0KPiA+ID4gb2Zmc2V0IGJ5
IFBDSUJJT1NfTUlOX0lPIGFzIHdlbGwuDQo+ID4gPg0KPiA+ID4gQmVzdCByZWdhcmRzLA0KPiA+
ID4gTGl2aXUNCj4gPiA+DQo+ID4gPiA+DQo+ID4gPiA+ICAJaWYgKHBpbyA+IElPX1NQQUNFX0xJ
TUlUKQ0KPiA+ID4gPiAgCQlyZXR1cm4gYWRkcmVzczsNCj4gPiA+ID4gQEAgLTMzMzUsNyArMzMz
NSw3IEBAIHVuc2lnbmVkIGxvbmcgX193ZWFrDQo+ID4gPiBwY2lfYWRkcmVzc190b19waW8ocGh5
c19hZGRyX3QgYWRkcmVzcykNCj4gPiA+ID4gIHsNCj4gPiA+ID4gICNpZmRlZiBQQ0lfSU9CQVNF
DQo+ID4gPiA+ICAJc3RydWN0IGlvX3JhbmdlICpyZXM7DQo+ID4gPiA+IC0JcmVzb3VyY2Vfc2l6
ZV90IG9mZnNldCA9IDA7DQo+ID4gPiA+ICsJcmVzb3VyY2Vfc2l6ZV90IG9mZnNldCA9IFBDSUJJ
T1NfTUlOX0lPOw0KPiA+ID4gPiAgCXVuc2lnbmVkIGxvbmcgYWRkciA9IC0xOw0KPiA+ID4gPg0K
PiA+ID4gPiAgCXNwaW5fbG9jaygmaW9fcmFuZ2VfbG9jayk7DQo+ID4gPiA+IGRpZmYgLS1naXQg
YS9pbmNsdWRlL2xpbnV4L29mX2FkZHJlc3MuaA0KPiBiL2luY2x1ZGUvbGludXgvb2ZfYWRkcmVz
cy5oDQo+ID4gPiA+IGluZGV4IDM3ODY0NzMuLmRlZWM0NjkgMTAwNjQ0DQo+ID4gPiA+IC0tLSBh
L2luY2x1ZGUvbGludXgvb2ZfYWRkcmVzcy5oDQo+ID4gPiA+ICsrKyBiL2luY2x1ZGUvbGludXgv
b2ZfYWRkcmVzcy5oDQo+ID4gPiA+IEBAIC0yNCw2ICsyNCwyMyBAQCBzdHJ1Y3Qgb2ZfcGNpX3Jh
bmdlIHsNCj4gPiA+ID4gICNkZWZpbmUgZm9yX2VhY2hfb2ZfcGNpX3JhbmdlKHBhcnNlciwgcmFu
Z2UpIFwNCj4gPiA+ID4gIAlmb3IgKDsgb2ZfcGNpX3JhbmdlX3BhcnNlcl9vbmUocGFyc2VyLCBy
YW5nZSk7KQ0KPiA+ID4gPg0KPiA+ID4gPiArDQo+ID4gPiA+ICsjaWZuZGVmIGluZGlyZWN0X2lv
X2VuYWJsZWQNCj4gPiA+ID4gKyNkZWZpbmUgaW5kaXJlY3RfaW9fZW5hYmxlZCBpbmRpcmVjdF9p
b19lbmFibGVkDQo+ID4gPiA+ICtzdGF0aWMgaW5saW5lIGJvb2wgaW5kaXJlY3RfaW9fZW5hYmxl
ZCh2b2lkKQ0KPiA+ID4gPiArew0KPiA+ID4gPiArCXJldHVybiBmYWxzZTsNCj4gPiA+ID4gK30N
Cj4gPiA+ID4gKyNlbmRpZg0KPiA+ID4gPiArDQo+ID4gPiA+ICsjaWZuZGVmIGFkZHJfaXNfaW5k
aXJlY3RfaW8NCj4gPiA+ID4gKyNkZWZpbmUgYWRkcl9pc19pbmRpcmVjdF9pbyBhZGRyX2lzX2lu
ZGlyZWN0X2lvDQo+ID4gPiA+ICtzdGF0aWMgaW5saW5lIGludCBhZGRyX2lzX2luZGlyZWN0X2lv
KHU2NCB0YWRkcikNCj4gPiA+ID4gK3sNCj4gPiA+ID4gKwlyZXR1cm4gMDsNCj4gPiA+ID4gK30N
Cj4gPiA+ID4gKyNlbmRpZg0KPiA+ID4gPiArDQo+ID4gPiA+ICAvKiBUcmFuc2xhdGUgYSBETUEg
YWRkcmVzcyBmcm9tIGRldmljZSBzcGFjZSB0byBDUFUgc3BhY2UgKi8NCj4gPiA+ID4gIGV4dGVy
biB1NjQgb2ZfdHJhbnNsYXRlX2RtYV9hZGRyZXNzKHN0cnVjdCBkZXZpY2Vfbm9kZSAqZGV2LA0K
PiA+ID4gPiAgCQkJCSAgICBjb25zdCBfX2JlMzIgKmluX2FkZHIpOw0KPiA+ID4gPiBkaWZmIC0t
Z2l0IGEvaW5jbHVkZS9saW51eC9wY2kuaCBiL2luY2x1ZGUvbGludXgvcGNpLmgNCj4gPiA+ID4g
aW5kZXggMGU0OWY3MC4uN2Y2YmJiNiAxMDA2NDQNCj4gPiA+ID4gLS0tIGEvaW5jbHVkZS9saW51
eC9wY2kuaA0KPiA+ID4gPiArKysgYi9pbmNsdWRlL2xpbnV4L3BjaS5oDQo+ID4gPiA+IEBAIC0y
MTMwLDQgKzIxMzAsMTIgQEAgc3RhdGljIGlubGluZSBib29sIHBjaV9hcmlfZW5hYmxlZChzdHJ1
Y3QNCj4gPiA+IHBjaV9idXMgKmJ1cykNCj4gPiA+ID4gIC8qIHByb3ZpZGUgdGhlIGxlZ2FjeSBw
Y2lfZG1hXyogQVBJICovDQo+ID4gPiA+ICAjaW5jbHVkZSA8bGludXgvcGNpLWRtYS1jb21wYXQu
aD4NCj4gPiA+ID4NCj4gPiA+ID4gKy8qDQo+ID4gPiA+ICsgKiBkZWZpbmUgdGhpcyBtYWNybyBo
ZXJlIHRvIHJlZnJhaW4gZnJvbSBjb21waWxhdGlvbiBlcnJvciBmb3INCj4gc29tZQ0KPiA+ID4g
PiArICogcGxhdGZvcm1zLiBQbGVhc2Uga2VlcCB0aGlzIG1hY3JvIGF0IHRoZSBlbmQgb2YgdGhp
cyBoZWFkZXINCj4gZmlsZS4NCj4gPiA+ID4gKyAqLw0KPiA+ID4gPiArI2lmbmRlZiBQQ0lCSU9T
X01JTl9JTw0KPiA+ID4gPiArI2RlZmluZSBQQ0lCSU9TX01JTl9JTwkJMA0KPiA+ID4gPiArI2Vu
ZGlmDQo+ID4gPiA+ICsNCj4gPiA+ID4gICNlbmRpZiAvKiBMSU5VWF9QQ0lfSCAqLw0KPiA+ID4g
PiAtLQ0KPiA+ID4gPiAxLjkuMQ0KPiA+ID4gPg0KPiA+ID4gPiAtLQ0KPiA+ID4gPiBUbyB1bnN1
YnNjcmliZSBmcm9tIHRoaXMgbGlzdDogc2VuZCB0aGUgbGluZSAidW5zdWJzY3JpYmUgbGludXgt
DQo+IHBjaSINCj4gPiA+IGluDQo+ID4gPiA+IHRoZSBib2R5IG9mIGEgbWVzc2FnZSB0byBtYWpv
cmRvbW9Admdlci5rZXJuZWwub3JnDQo+ID4gPiA+IE1vcmUgbWFqb3Jkb21vIGluZm8gYXQgIGh0
dHA6Ly92Z2VyLmtlcm5lbC5vcmcvbWFqb3Jkb21vLQ0KPiBpbmZvLmh0bWwNCj4gDQo+IC0tDQo+
ID09PT09PT09PT09PT09PT09PT09DQo+IHwgSSB3b3VsZCBsaWtlIHRvIHwNCj4gfCBmaXggdGhl
IHdvcmxkLCAgfA0KPiB8IGJ1dCB0aGV5J3JlIG5vdCB8DQo+IHwgZ2l2aW5nIG1lIHRoZSAgIHwN
Cj4gIFwgc291cmNlIGNvZGUhICAvDQo+ICAgLS0tLS0tLS0tLS0tLS0tDQo+ICAgICDCr1xfKOOD
hClfL8KvDQo=

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

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-10 16:06           ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-10 16:06 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Liviu

> -----Original Message-----
> From: liviu.dudau at arm.com [mailto:liviu.dudau at arm.com]
> Sent: 09 November 2016 16:51
> To: Gabriele Paoloni
> Cc: Yuanzhichang; catalin.marinas at arm.com; will.deacon at arm.com;
> robh+dt at kernel.org; bhelgaas at google.com; mark.rutland at arm.com;
> olof at lixom.net; arnd at arndb.de; linux-arm-kernel at lists.infradead.org;
> lorenzo.pieralisi at arm.com; linux-kernel at vger.kernel.org; Linuxarm;
> devicetree at vger.kernel.org; linux-pci at vger.kernel.org; linux-
> serial at vger.kernel.org; minyard at acm.org; benh at kernel.crashing.org;
> zourongrong at gmail.com; John Garry; zhichang.yuan02 at gmail.com;
> kantyzc at 163.com; xuwei (O)
> Subject: Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for
> special ISA
> 
> On Wed, Nov 09, 2016 at 04:16:17PM +0000, Gabriele Paoloni wrote:
> > Hi Liviu
> >
> > Thanks for reviewing
> >
> 
> [removed some irrelevant part of discussion, avoid crazy formatting]
> 
> > > > +/**
> > > > + * addr_is_indirect_io - check whether the input taddr is for
> > > indirectIO.
> > > > + * @taddr: the io address to be checked.
> > > > + *
> > > > + * Returns 1 when taddr is in the range; otherwise return 0.
> > > > + */
> > > > +int addr_is_indirect_io(u64 taddr)
> > > > +{
> > > > +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end
> <
> > > taddr)
> > >
> > > start >= taddr ?
> >
> > Nope... if  (taddr < arm64_extio_ops->start || taddr >
> arm64_extio_ops->end)
> > then taddr is outside the range [start; end] and will return 0;
> otherwise
> > it will return 1...
> 
> Oops, sorry, did not pay attention to the returned value. The check is
> correct as it is, no need to change then.
> 
> >
> > >
> > > > +		return 0;
> > > > +
> > > > +	return 1;
> > > > +}
> > > >
> > > >  BUILD_EXTIO(b, u8)
> > > >
> > > > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > > > index 02b2903..cc2a05d 100644
> > > > --- a/drivers/of/address.c
> > > > +++ b/drivers/of/address.c
> > > > @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
> > > device_node *np)
> > > >  	return false;
> > > >  }
> > > >
> > > > +
> > > > +/*
> > > > + * of_isa_indirect_io - get the IO address from some isa reg
> > > property value.
> > > > + *	For some isa/lpc devices, no ranges property in ancestor
> node.
> > > > + *	The device addresses are described directly in their regs
> > > property.
> > > > + *	This fixup function will be called to get the IO address of
> > > isa/lpc
> > > > + *	devices when the normal of_translation failed.
> > > > + *
> > > > + * @parent:	points to the parent dts node;
> > > > + * @bus:		points to the of_bus which can be used to parse
> > > address;
> > > > + * @addr:	the address from reg property;
> > > > + * @na:		the address cell counter of @addr;
> > > > + * @presult:	store the address paresed from @addr;
> > > > + *
> > > > + * return 1 when successfully get the I/O address;
> > > > + * 0 will return for some failures.
> > >
> > > Bah, you are returning a signed int, why 0 for failure? Return a
> > > negative value with
> > > error codes. Otherwise change the return value into a bool.
> >
> > Yes we'll move to bool
> >
> > >
> > > > + */
> > > > +static int of_get_isa_indirect_io(struct device_node *parent,
> > > > +				struct of_bus *bus, __be32 *addr,
> > > > +				int na, u64 *presult)
> > > > +{
> > > > +	unsigned int flags;
> > > > +	unsigned int rlen;
> > > > +
> > > > +	/* whether support indirectIO */
> > > > +	if (!indirect_io_enabled())
> > > > +		return 0;
> > > > +
> > > > +	if (!of_bus_isa_match(parent))
> > > > +		return 0;
> > > > +
> > > > +	flags = bus->get_flags(addr);
> > > > +	if (!(flags & IORESOURCE_IO))
> > > > +		return 0;
> > > > +
> > > > +	/* there is ranges property, apply the normal translation
> > > directly. */
> > >
> > > s/there is ranges/if we have a 'ranges'/
> >
> > Thanks for spotting this
> >
> > >
> > > > +	if (of_get_property(parent, "ranges", &rlen))
> > > > +		return 0;
> > > > +
> > > > +	*presult = of_read_number(addr + 1, na - 1);
> > > > +	/* this fixup is only valid for specific I/O range. */
> > > > +	return addr_is_indirect_io(*presult);
> > > > +}
> > > > +
> > > >  static int of_translate_one(struct device_node *parent, struct
> > > of_bus *bus,
> > > >  			    struct of_bus *pbus, __be32 *addr,
> > > >  			    int na, int ns, int pna, const char *rprop)
> > > > @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
> > > device_node *dev,
> > > >  			result = of_read_number(addr, na);
> > > >  			break;
> > > >  		}
> > > > +		/*
> > > > +		 * For indirectIO device which has no ranges
> property, get
> > > > +		 * the address from reg directly.
> > > > +		 */
> > > > +		if (of_get_isa_indirect_io(dev, bus, addr, na,
> &result)) {
> > > > +			pr_debug("isa indirectIO matched(%s)..addr =
> > > 0x%llx\n",
> > > > +				of_node_full_name(dev), result);
> > > > +			break;
> > > > +		}
> > > >
> > > >  		/* Get new parent bus and counts */
> > > >  		pbus = of_match_bus(parent);
> > > > @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
> > > device_node *dev,
> > > >  	if (taddr == OF_BAD_ADDR)
> > > >  		return -EINVAL;
> > > >  	memset(r, 0, sizeof(struct resource));
> > > > -	if (flags & IORESOURCE_IO) {
> > > > +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
> > > >  		unsigned long port;
> > > > +
> > > >  		port = pci_address_to_pio(taddr);
> > > >  		if (port == (unsigned long)-1)
> > > >  			return -EINVAL;
> > > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > > > index ba34907..1a08511 100644
> > > > --- a/drivers/pci/pci.c
> > > > +++ b/drivers/pci/pci.c
> > > > @@ -3263,7 +3263,7 @@ 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;
> > > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > > >
> > > >  	/* check if the range hasn't been previously recorded */
> > > >  	spin_lock(&io_range_lock);
> > > > @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned
> long
> > > pio)
> > > >
> > > >  #ifdef PCI_IOBASE
> > > >  	struct io_range *range;
> > > > -	resource_size_t allocated_size = 0;
> > > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > >
> > > Have you checked that pci_pio_to_address still returns valid values
> > > after this? I know that
> > > you are trying to take into account PCIBIOS_MIN_IO limit when
> > > allocating reserving the IO ranges,
> > > but the values added in the io_range_list are still starting from
> zero,
> > > no from PCIBIOS_MIN_IO,
> >
> > I think you're wrong here as in pci_address_to_pio we have:
> > +	resource_size_t offset = PCIBIOS_MIN_IO;
> >
> > This should be enough to guarantee that the PIOs start at
> > PCIBIOS_MIN_IO...right?
> 
> I don't think you can guarantee that the pio value that gets passed
> into
> pci_pio_to_address() always comes from a previously returned value by
> pci_address_to_pio(). Maybe you can add a check in pci_pio_to_address()

Maybe I am missing something...could you make an exampleof a case
where an IO toke doesn?t come from pci_address_to_pio() ?

Thanks

Gab


> 
> 	if (pio < PCIBIOS_MIN_IO)
> 		return address;
> 
> to avoid adding more checks in the list_for_each_entry() loop.
> 
> Best regards,
> Liviu
> 
> >
> >
> > > so the calculation of the address in this function could return
> > > negative values casted to pci_addr_t.
> > >
> > > Maybe you want to adjust the range->start value in
> > > pci_register_io_range() as well to have it
> > > offset by PCIBIOS_MIN_IO as well.
> > >
> > > Best regards,
> > > Liviu
> > >
> > > >
> > > >  	if (pio > IO_SPACE_LIMIT)
> > > >  		return address;
> > > > @@ -3335,7 +3335,7 @@ unsigned long __weak
> > > pci_address_to_pio(phys_addr_t address)
> > > >  {
> > > >  #ifdef PCI_IOBASE
> > > >  	struct io_range *res;
> > > > -	resource_size_t offset = 0;
> > > > +	resource_size_t offset = PCIBIOS_MIN_IO;
> > > >  	unsigned long addr = -1;
> > > >
> > > >  	spin_lock(&io_range_lock);
> > > > diff --git a/include/linux/of_address.h
> b/include/linux/of_address.h
> > > > index 3786473..deec469 100644
> > > > --- a/include/linux/of_address.h
> > > > +++ b/include/linux/of_address.h
> > > > @@ -24,6 +24,23 @@ struct of_pci_range {
> > > >  #define for_each_of_pci_range(parser, range) \
> > > >  	for (; of_pci_range_parser_one(parser, range);)
> > > >
> > > > +
> > > > +#ifndef indirect_io_enabled
> > > > +#define indirect_io_enabled indirect_io_enabled
> > > > +static inline bool indirect_io_enabled(void)
> > > > +{
> > > > +	return false;
> > > > +}
> > > > +#endif
> > > > +
> > > > +#ifndef addr_is_indirect_io
> > > > +#define addr_is_indirect_io addr_is_indirect_io
> > > > +static inline int addr_is_indirect_io(u64 taddr)
> > > > +{
> > > > +	return 0;
> > > > +}
> > > > +#endif
> > > > +
> > > >  /* Translate a DMA address from device space to CPU space */
> > > >  extern u64 of_translate_dma_address(struct device_node *dev,
> > > >  				    const __be32 *in_addr);
> > > > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > > > index 0e49f70..7f6bbb6 100644
> > > > --- a/include/linux/pci.h
> > > > +++ b/include/linux/pci.h
> > > > @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
> > > pci_bus *bus)
> > > >  /* provide the legacy pci_dma_* API */
> > > >  #include <linux/pci-dma-compat.h>
> > > >
> > > > +/*
> > > > + * define this macro here to refrain from compilation error for
> some
> > > > + * platforms. Please keep this macro at the end of this header
> file.
> > > > + */
> > > > +#ifndef PCIBIOS_MIN_IO
> > > > +#define PCIBIOS_MIN_IO		0
> > > > +#endif
> > > > +
> > > >  #endif /* LINUX_PCI_H */
> > > > --
> > > > 1.9.1
> > > >
> > > > --
> > > > 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] 286+ messages in thread

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-10 15:36               ` Gabriele Paoloni
  (?)
  (?)
@ 2016-11-10 16:07                 ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-10 16:07 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: linux-arm-kernel, Yuanzhichang, mark.rutland, devicetree,
	lorenzo.pieralisi, minyard, linux-pci, benh, John Garry,
	will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, liviu.dudau, bhelgaas, zhichang.yuan02

On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
> 
> Where should we get the range from? For LPC we know that it is going
> Work on anything that is not used by PCI I/O space, and this is 
> why we use [0, PCIBIOS_MIN_IO]

It should be allocated the same way we allocate PCI config space
segments. This is currently done with the io_range list in
drivers/pci/pci.c, which isn't perfect but could be extended
if necessary. Based on what others commented here, I'd rather
make the differences between ISA/LPC and PCI I/O ranges smaller
than larger.

> > Your current version has
> > 
> >         if (arm64_extio_ops->pfout)                             \
> >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> >                        addr, value, sizeof(type));             \
> > 
> > Instead, just subtract the start of the range from the logical
> > port number to transform it back into a bus-local port number:
> 
> These accessors do not operate on IO tokens:
> 
> If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> addr is not going to be an I/O token; in fact patch 2/3 imposes that
> the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to PCIBIOS_MIN_IO
> we have free physical addresses that the accessors can operate on.

Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
the logical I/O tokens, the purpose of that macro is really meant
for allocating PCI I/O port numbers within the address space of
one bus.

Note that it's equally likely that whichever next platform needs
non-mapped I/O access like this actually needs them for PCI I/O space,
and that will use it on addresses registered to a PCI host bridge.

If we separate the two steps:

a) assign a range of logical I/O port numbers to a bus
b) register a set of helpers for redirecting logical I/O
   port to a helper function

then I think the code will get cleaner and more flexible.
It should actually then be able to replace the powerpc
specific implementation.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-10 16:07                 ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-10 16:07 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: mark.rutland, benh, catalin.marinas, will.deacon, Linuxarm,
	lorenzo.pieralisi, xuwei (O),
	linux-serial, linux-pci, devicetree, minyard, liviu.dudau,
	John Garry, zourongrong, robh+dt, bhelgaas, kantyzc,
	zhichang.yuan02, linux-arm-kernel

On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
> 
> Where should we get the range from? For LPC we know that it is going
> Work on anything that is not used by PCI I/O space, and this is 
> why we use [0, PCIBIOS_MIN_IO]

It should be allocated the same way we allocate PCI config space
segments. This is currently done with the io_range list in
drivers/pci/pci.c, which isn't perfect but could be extended
if necessary. Based on what others commented here, I'd rather
make the differences between ISA/LPC and PCI I/O ranges smaller
than larger.

> > Your current version has
> > 
> >         if (arm64_extio_ops->pfout)                             \
> >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> >                        addr, value, sizeof(type));             \
> > 
> > Instead, just subtract the start of the range from the logical
> > port number to transform it back into a bus-local port number:
> 
> These accessors do not operate on IO tokens:
> 
> If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> addr is not going to be an I/O token; in fact patch 2/3 imposes that
> the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to PCIBIOS_MIN_IO
> we have free physical addresses that the accessors can operate on.

Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
the logical I/O tokens, the purpose of that macro is really meant
for allocating PCI I/O port numbers within the address space of
one bus.

Note that it's equally likely that whichever next platform needs
non-mapped I/O access like this actually needs them for PCI I/O space,
and that will use it on addresses registered to a PCI host bridge.

If we separate the two steps:

a) assign a range of logical I/O port numbers to a bus
b) register a set of helpers for redirecting logical I/O
   port to a helper function

then I think the code will get cleaner and more flexible.
It should actually then be able to replace the powerpc
specific implementation.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-10 16:07                 ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-10 16:07 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: linux-arm-kernel, Yuanzhichang, mark.rutland, devicetree,
	lorenzo.pieralisi, minyard, linux-pci, benh, John Garry,
	will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, liviu.dudau, bhelgaas, zhichang.yuan02

On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
> 
> Where should we get the range from? For LPC we know that it is going
> Work on anything that is not used by PCI I/O space, and this is 
> why we use [0, PCIBIOS_MIN_IO]

It should be allocated the same way we allocate PCI config space
segments. This is currently done with the io_range list in
drivers/pci/pci.c, which isn't perfect but could be extended
if necessary. Based on what others commented here, I'd rather
make the differences between ISA/LPC and PCI I/O ranges smaller
than larger.

> > Your current version has
> > 
> >         if (arm64_extio_ops->pfout)                             \
> >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> >                        addr, value, sizeof(type));             \
> > 
> > Instead, just subtract the start of the range from the logical
> > port number to transform it back into a bus-local port number:
> 
> These accessors do not operate on IO tokens:
> 
> If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> addr is not going to be an I/O token; in fact patch 2/3 imposes that
> the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to PCIBIOS_MIN_IO
> we have free physical addresses that the accessors can operate on.

Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
the logical I/O tokens, the purpose of that macro is really meant
for allocating PCI I/O port numbers within the address space of
one bus.

Note that it's equally likely that whichever next platform needs
non-mapped I/O access like this actually needs them for PCI I/O space,
and that will use it on addresses registered to a PCI host bridge.

If we separate the two steps:

a) assign a range of logical I/O port numbers to a bus
b) register a set of helpers for redirecting logical I/O
   port to a helper function

then I think the code will get cleaner and more flexible.
It should actually then be able to replace the powerpc
specific implementation.

	Arnd

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-10 16:07                 ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-10 16:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
> 
> Where should we get the range from? For LPC we know that it is going
> Work on anything that is not used by PCI I/O space, and this is 
> why we use [0, PCIBIOS_MIN_IO]

It should be allocated the same way we allocate PCI config space
segments. This is currently done with the io_range list in
drivers/pci/pci.c, which isn't perfect but could be extended
if necessary. Based on what others commented here, I'd rather
make the differences between ISA/LPC and PCI I/O ranges smaller
than larger.

> > Your current version has
> > 
> >         if (arm64_extio_ops->pfout)                             \
> >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> >                        addr, value, sizeof(type));             \
> > 
> > Instead, just subtract the start of the range from the logical
> > port number to transform it back into a bus-local port number:
> 
> These accessors do not operate on IO tokens:
> 
> If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> addr is not going to be an I/O token; in fact patch 2/3 imposes that
> the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to PCIBIOS_MIN_IO
> we have free physical addresses that the accessors can operate on.

Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
the logical I/O tokens, the purpose of that macro is really meant
for allocating PCI I/O port numbers within the address space of
one bus.

Note that it's equally likely that whichever next platform needs
non-mapped I/O access like this actually needs them for PCI I/O space,
and that will use it on addresses registered to a PCI host bridge.

If we separate the two steps:

a) assign a range of logical I/O port numbers to a bus
b) register a set of helpers for redirecting logical I/O
   port to a helper function

then I think the code will get cleaner and more flexible.
It should actually then be able to replace the powerpc
specific implementation.

	Arnd

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-11-10 11:22         ` Mark Rutland
  (?)
  (?)
@ 2016-11-10 19:32           ` Benjamin Herrenschmidt
  -1 siblings, 0 replies; 286+ messages in thread
From: Benjamin Herrenschmidt @ 2016-11-10 19:32 UTC (permalink / raw)
  To: Mark Rutland
  Cc: zhichang.yuan, catalin.marinas, will.deacon, robh+dt, bhelgaas,
	olof, arnd, linux-arm-kernel, lorenzo.pieralisi, linux-kernel,
	linuxarm, devicetree, linux-pci, linux-serial, minyard,
	liviu.dudau, zourongrong, john.garry, gabriele.paoloni,
	zhichang.yuan02, kantyzc, xuwei5, marc.zyngier

On Thu, 2016-11-10 at 11:22 +0000, Mark Rutland wrote:
> On POWER8, our PCIe doesn't do IO at all, but we have an LPC bus behind
> > firmware calls ;-) We use that infrastructure to plumb in the LPC bus.
> 
> Just to check, do you hook that in your inb/outb/etc?

Yes.

> Generally, it would seem nicer if we could have higher-level
> isa_{inb,outb,whatever} accessors that we could hook separately from
> other IO.

Maybe but generally speaking, we don't discriminate accessors per bus,
ie, readl etc... work on all memory mapped busses, inb... works on all
busses with an "IO space", at least that's been the idea. It probably
all comes from the fact that PCI IO and ISA are the same space on
x86 and most other platforms (not all).

> We don't necessarily have to move all ISA drivers over to that if we had
> a separate symbol for that interface.

What I do on ppc today is that I have a chunk of virtual address space
that is reserved for "IO space". The first 64k are "reserved" in that
they route to "the primary" ISA bus (for legacy crap that uses hard
coded addresses, though I use that for my LPC bus too). I "allocate"
space for the PCI IO spaces higher in that space. Was I to support more
LPC busses I could allocate them up there too.

The IO resource of a given device thus becomes the actual IO port plus
the offset of the base of the segment it's in.

For memory mapped IO, inb/outb will just add the virtual address of
the base of all IO space to that. The hooking mechanism will pickup
the stuff that isn't memory mapped.

It's a bit messy but then IO space performance has never been a huge
worry since IO cycles tend to be very slow to begin with.

Note: We also have the ISA memory and ISA FW spaces that we don't have
good accessors for. They somewhat exist (I think the fbdev layer uses
some for vga) but it's messy.

Cheers,
Ben.

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-10 19:32           ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 286+ messages in thread
From: Benjamin Herrenschmidt @ 2016-11-10 19:32 UTC (permalink / raw)
  To: Mark Rutland
  Cc: zhichang.yuan, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, olof-nZhT3qVonbNeoWH0uzbU5w,
	arnd-r2nGTMty4D4,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	lorenzo.pieralisi-5wv7dgnIgG8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linuxarm-hv44wF8Li93QT0dZR+AlfA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, minyard-HInyCGIudOg,
	liviu.dudau-5wv7dgnIgG8, zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
	john.garry-hv44wF8Li93QT0dZR+AlfA,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w, kantyzc-9Onoh4P/yGk,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q, marc.zyngier-5wv7dgnIgG8

On Thu, 2016-11-10 at 11:22 +0000, Mark Rutland wrote:
> On POWER8, our PCIe doesn't do IO at all, but we have an LPC bus behind
> > firmware calls ;-) We use that infrastructure to plumb in the LPC bus.
> 
> Just to check, do you hook that in your inb/outb/etc?

Yes.

> Generally, it would seem nicer if we could have higher-level
> isa_{inb,outb,whatever} accessors that we could hook separately from
> other IO.

Maybe but generally speaking, we don't discriminate accessors per bus,
ie, readl etc... work on all memory mapped busses, inb... works on all
busses with an "IO space", at least that's been the idea. It probably
all comes from the fact that PCI IO and ISA are the same space on
x86 and most other platforms (not all).

> We don't necessarily have to move all ISA drivers over to that if we had
> a separate symbol for that interface.

What I do on ppc today is that I have a chunk of virtual address space
that is reserved for "IO space". The first 64k are "reserved" in that
they route to "the primary" ISA bus (for legacy crap that uses hard
coded addresses, though I use that for my LPC bus too). I "allocate"
space for the PCI IO spaces higher in that space. Was I to support more
LPC busses I could allocate them up there too.

The IO resource of a given device thus becomes the actual IO port plus
the offset of the base of the segment it's in.

For memory mapped IO, inb/outb will just add the virtual address of
the base of all IO space to that. The hooking mechanism will pickup
the stuff that isn't memory mapped.

It's a bit messy but then IO space performance has never been a huge
worry since IO cycles tend to be very slow to begin with.

Note: We also have the ISA memory and ISA FW spaces that we don't have
good accessors for. They somewhat exist (I think the fbdev layer uses
some for vga) but it's messy.

Cheers,
Ben.

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-10 19:32           ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 286+ messages in thread
From: Benjamin Herrenschmidt @ 2016-11-10 19:32 UTC (permalink / raw)
  To: Mark Rutland
  Cc: gabriele.paoloni, catalin.marinas, will.deacon, linuxarm,
	lorenzo.pieralisi, arnd, xuwei5, linux-serial, linux-pci,
	devicetree, minyard, marc.zyngier, liviu.dudau, john.garry,
	zourongrong, robh+dt, bhelgaas, kantyzc, zhichang.yuan02,
	linux-arm-kernel, linux-kernel, zhichang.yuan, olof

On Thu, 2016-11-10 at 11:22 +0000, Mark Rutland wrote:
> On POWER8, our PCIe doesn't do IO at all, but we have an LPC bus behind
> > firmware calls ;-) We use that infrastructure to plumb in the LPC bus.
> 
> Just to check, do you hook that in your inb/outb/etc?

Yes.

> Generally, it would seem nicer if we could have higher-level
> isa_{inb,outb,whatever} accessors that we could hook separately from
> other IO.

Maybe but generally speaking, we don't discriminate accessors per bus,
ie, readl etc... work on all memory mapped busses, inb... works on all
busses with an "IO space", at least that's been the idea. It probably
all comes from the fact that PCI IO and ISA are the same space on
x86 and most other platforms (not all).

> We don't necessarily have to move all ISA drivers over to that if we had
> a separate symbol for that interface.

What I do on ppc today is that I have a chunk of virtual address space
that is reserved for "IO space". The first 64k are "reserved" in that
they route to "the primary" ISA bus (for legacy crap that uses hard
coded addresses, though I use that for my LPC bus too). I "allocate"
space for the PCI IO spaces higher in that space. Was I to support more
LPC busses I could allocate them up there too.

The IO resource of a given device thus becomes the actual IO port plus
the offset of the base of the segment it's in.

For memory mapped IO, inb/outb will just add the virtual address of
the base of all IO space to that. The hooking mechanism will pickup
the stuff that isn't memory mapped.

It's a bit messy but then IO space performance has never been a huge
worry since IO cycles tend to be very slow to begin with.

Note: We also have the ISA memory and ISA FW spaces that we don't have
good accessors for. They somewhat exist (I think the fbdev layer uses
some for vga) but it's messy.

Cheers,
Ben.


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-10 19:32           ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 286+ messages in thread
From: Benjamin Herrenschmidt @ 2016-11-10 19:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2016-11-10 at 11:22 +0000, Mark Rutland wrote:
> On POWER8, our PCIe doesn't do IO at all, but we have an LPC bus behind
> > firmware calls ;-) We use that infrastructure to plumb in the LPC bus.
> 
> Just to check, do you hook that in your inb/outb/etc?

Yes.

> Generally, it would seem nicer if we could have higher-level
> isa_{inb,outb,whatever} accessors that we could hook separately from
> other IO.

Maybe but generally speaking, we don't discriminate accessors per bus,
ie, readl etc... work on all memory mapped busses, inb... works on all
busses with an "IO space", at least that's been the idea. It probably
all comes from the fact that PCI IO and ISA are the same space on
x86 and most other platforms (not all).

> We don't necessarily have to move all ISA drivers over to that if we had
> a separate symbol for that interface.

What I do on ppc today is that I have a chunk of virtual address space
that is reserved for "IO space". The first 64k are "reserved" in that
they route to "the primary" ISA bus (for legacy crap that uses hard
coded addresses, though I use that for my LPC bus too). I "allocate"
space for the PCI IO spaces higher in that space. Was I to support more
LPC busses I could allocate them up there too.

The IO resource of a given device thus becomes the actual IO port plus
the offset of the base of the segment it's in.

For memory mapped IO, inb/outb will just add the virtual address of
the base of all IO space to that. The hooking mechanism will pickup
the stuff that isn't memory mapped.

It's a bit messy but then IO space performance has never been a huge
worry since IO cycles tend to be very slow to begin with.

Note: We also have the ISA memory and ISA FW spaces that we don't have
good accessors for. They somewhat exist (I think the fbdev layer uses
some for vga) but it's messy.

Cheers,
Ben.

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-11-10 19:32           ` Benjamin Herrenschmidt
  (?)
@ 2016-11-11 10:07             ` zhichang.yuan
  -1 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-11 10:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Mark Rutland
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, olof, arnd,
	linux-arm-kernel, lorenzo.pieralisi, linux-kernel, linuxarm,
	devicetree, linux-pci, linux-serial, minyard, liviu.dudau,
	zourongrong, john.garry, gabriele.paoloni, zhichang.yuan02,
	kantyzc, xuwei5, marc.zyngier

Hi, Ben, Mark,

Thanks for your comments! These are helpful!


On 2016/11/11 3:32, Benjamin Herrenschmidt wrote:
> On Thu, 2016-11-10 at 11:22 +0000, Mark Rutland wrote:
>> On POWER8, our PCIe doesn't do IO at all, but we have an LPC bus behind
>>> firmware calls ;-) We use that infrastructure to plumb in the LPC bus.
>>
>> Just to check, do you hook that in your inb/outb/etc?
> 
> Yes.
> 
>> Generally, it would seem nicer if we could have higher-level
>> isa_{inb,outb,whatever} accessors that we could hook separately from
>> other IO.
> 
> Maybe but generally speaking, we don't discriminate accessors per bus,
> ie, readl etc... work on all memory mapped busses, inb... works on all
> busses with an "IO space", at least that's been the idea. It probably
> all comes from the fact that PCI IO and ISA are the same space on
> x86 and most other platforms (not all).
> 
>> We don't necessarily have to move all ISA drivers over to that if we had
>> a separate symbol for that interface.
> 
> What I do on ppc today is that I have a chunk of virtual address space
> that is reserved for "IO space". The first 64k are "reserved" in that
> they route to "the primary" ISA bus (for legacy crap that uses hard
> coded addresses, though I use that for my LPC bus too). I "allocate"
> space for the PCI IO spaces higher in that space. Was I to support more
> LPC busses I could allocate them up there too.
>

I have similar idea as your PPC MMIO.

We notice the prototype of {in/out()} is something like that:

static inline u8 inb(unsigned long addr)
static inline void outb(u8 value, unsigned long addr)

The type of parameter 'addr' is unsigned long. For I/O space, it is big enough.
So, could you divide this 'addr' into several bit segments? The top 8 bits is
defined as bus index. For normal direct IO, the bus index is 0. For those bus
device which need indirectIO or some special I/O accessors, when these devices
are initializing, can request to allocate an unique ID to them, and register
their own accessors to the entry which is corresponding to the ID.

In this way, we can support multiple domains, I think.
But I am not sure whether it is feasible, for example, are there some
architectures/platforms had populated the top 8 bits? Do we need to request IO
region from ioport_resource for those devices?  etc...


Thanks,
Zhichang


> The IO resource of a given device thus becomes the actual IO port plus
> the offset of the base of the segment it's in.
> 
> For memory mapped IO, inb/outb will just add the virtual address of
> the base of all IO space to that. The hooking mechanism will pickup
> the stuff that isn't memory mapped.
> 
> It's a bit messy but then IO space performance has never been a huge
> worry since IO cycles tend to be very slow to begin with.
> 
> Note: We also have the ISA memory and ISA FW spaces that we don't have
> good accessors for. They somewhat exist (I think the fbdev layer uses
> some for vga) but it's messy.
> 
> Cheers,
> Ben.
> 
> 
> .
> 

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-11 10:07             ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-11 10:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Mark Rutland
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, olof, arnd,
	linux-arm-kernel, lorenzo.pieralisi, linux-kernel, linuxarm,
	devicetree, linux-pci, linux-serial, minyard, liviu.dudau,
	zourongrong, john.garry, gabriele.paoloni, zhichang.yuan02,
	kantyzc, xuwei5, marc.zyngier

Hi, Ben, Mark,

Thanks for your comments! These are helpful!


On 2016/11/11 3:32, Benjamin Herrenschmidt wrote:
> On Thu, 2016-11-10 at 11:22 +0000, Mark Rutland wrote:
>> On POWER8, our PCIe doesn't do IO at all, but we have an LPC bus behind
>>> firmware calls ;-) We use that infrastructure to plumb in the LPC bus.
>>
>> Just to check, do you hook that in your inb/outb/etc?
> 
> Yes.
> 
>> Generally, it would seem nicer if we could have higher-level
>> isa_{inb,outb,whatever} accessors that we could hook separately from
>> other IO.
> 
> Maybe but generally speaking, we don't discriminate accessors per bus,
> ie, readl etc... work on all memory mapped busses, inb... works on all
> busses with an "IO space", at least that's been the idea. It probably
> all comes from the fact that PCI IO and ISA are the same space on
> x86 and most other platforms (not all).
> 
>> We don't necessarily have to move all ISA drivers over to that if we had
>> a separate symbol for that interface.
> 
> What I do on ppc today is that I have a chunk of virtual address space
> that is reserved for "IO space". The first 64k are "reserved" in that
> they route to "the primary" ISA bus (for legacy crap that uses hard
> coded addresses, though I use that for my LPC bus too). I "allocate"
> space for the PCI IO spaces higher in that space. Was I to support more
> LPC busses I could allocate them up there too.
>

I have similar idea as your PPC MMIO.

We notice the prototype of {in/out()} is something like that:

static inline u8 inb(unsigned long addr)
static inline void outb(u8 value, unsigned long addr)

The type of parameter 'addr' is unsigned long. For I/O space, it is big enough.
So, could you divide this 'addr' into several bit segments? The top 8 bits is
defined as bus index. For normal direct IO, the bus index is 0. For those bus
device which need indirectIO or some special I/O accessors, when these devices
are initializing, can request to allocate an unique ID to them, and register
their own accessors to the entry which is corresponding to the ID.

In this way, we can support multiple domains, I think.
But I am not sure whether it is feasible, for example, are there some
architectures/platforms had populated the top 8 bits? Do we need to request IO
region from ioport_resource for those devices?  etc...


Thanks,
Zhichang


> The IO resource of a given device thus becomes the actual IO port plus
> the offset of the base of the segment it's in.
> 
> For memory mapped IO, inb/outb will just add the virtual address of
> the base of all IO space to that. The hooking mechanism will pickup
> the stuff that isn't memory mapped.
> 
> It's a bit messy but then IO space performance has never been a huge
> worry since IO cycles tend to be very slow to begin with.
> 
> Note: We also have the ISA memory and ISA FW spaces that we don't have
> good accessors for. They somewhat exist (I think the fbdev layer uses
> some for vga) but it's messy.
> 
> Cheers,
> Ben.
> 
> 
> .
> 

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-11 10:07             ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-11 10:07 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, Ben, Mark,

Thanks for your comments! These are helpful!


On 2016/11/11 3:32, Benjamin Herrenschmidt wrote:
> On Thu, 2016-11-10 at 11:22 +0000, Mark Rutland wrote:
>> On POWER8, our PCIe doesn't do IO at all, but we have an LPC bus behind
>>> firmware calls ;-) We use that infrastructure to plumb in the LPC bus.
>>
>> Just to check, do you hook that in your inb/outb/etc?
> 
> Yes.
> 
>> Generally, it would seem nicer if we could have higher-level
>> isa_{inb,outb,whatever} accessors that we could hook separately from
>> other IO.
> 
> Maybe but generally speaking, we don't discriminate accessors per bus,
> ie, readl etc... work on all memory mapped busses, inb... works on all
> busses with an "IO space", at least that's been the idea. It probably
> all comes from the fact that PCI IO and ISA are the same space on
> x86 and most other platforms (not all).
> 
>> We don't necessarily have to move all ISA drivers over to that if we had
>> a separate symbol for that interface.
> 
> What I do on ppc today is that I have a chunk of virtual address space
> that is reserved for "IO space". The first 64k are "reserved" in that
> they route to "the primary" ISA bus (for legacy crap that uses hard
> coded addresses, though I use that for my LPC bus too). I "allocate"
> space for the PCI IO spaces higher in that space. Was I to support more
> LPC busses I could allocate them up there too.
>

I have similar idea as your PPC MMIO.

We notice the prototype of {in/out()} is something like that:

static inline u8 inb(unsigned long addr)
static inline void outb(u8 value, unsigned long addr)

The type of parameter 'addr' is unsigned long. For I/O space, it is big enough.
So, could you divide this 'addr' into several bit segments? The top 8 bits is
defined as bus index. For normal direct IO, the bus index is 0. For those bus
device which need indirectIO or some special I/O accessors, when these devices
are initializing, can request to allocate an unique ID to them, and register
their own accessors to the entry which is corresponding to the ID.

In this way, we can support multiple domains, I think.
But I am not sure whether it is feasible, for example, are there some
architectures/platforms had populated the top 8 bits? Do we need to request IO
region from ioport_resource for those devices?  etc...


Thanks,
Zhichang


> The IO resource of a given device thus becomes the actual IO port plus
> the offset of the base of the segment it's in.
> 
> For memory mapped IO, inb/outb will just add the virtual address of
> the base of all IO space to that. The hooking mechanism will pickup
> the stuff that isn't memory mapped.
> 
> It's a bit messy but then IO space performance has never been a huge
> worry since IO cycles tend to be very slow to begin with.
> 
> Note: We also have the ISA memory and ISA FW spaces that we don't have
> good accessors for. They somewhat exist (I think the fbdev layer uses
> some for vga) but it's messy.
> 
> Cheers,
> Ben.
> 
> 
> .
> 

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-10 16:07                 ` Arnd Bergmann
  (?)
  (?)
@ 2016-11-11 10:09                   ` zhichang.yuan
  -1 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-11 10:09 UTC (permalink / raw)
  To: Arnd Bergmann, Gabriele Paoloni
  Cc: linux-arm-kernel, mark.rutland, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, benh, John Garry, will.deacon, linux-kernel,
	xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, liviu.dudau, bhelgaas@googl e.com,
	zhichang.yuan02

Hi, Arnd,

On 2016/11/11 0:07, Arnd Bergmann wrote:
> On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
>>
>> Where should we get the range from? For LPC we know that it is going
>> Work on anything that is not used by PCI I/O space, and this is 
>> why we use [0, PCIBIOS_MIN_IO]
> 
> It should be allocated the same way we allocate PCI config space
> segments. This is currently done with the io_range list in
> drivers/pci/pci.c, which isn't perfect but could be extended
> if necessary. Based on what others commented here, I'd rather
> make the differences between ISA/LPC and PCI I/O ranges smaller
> than larger.
> 
>>> Your current version has
>>>
>>>         if (arm64_extio_ops->pfout)                             \
>>>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>>>                        addr, value, sizeof(type));             \
>>>
>>> Instead, just subtract the start of the range from the logical
>>> port number to transform it back into a bus-local port number:
>>
>> These accessors do not operate on IO tokens:
>>
>> If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
>> addr is not going to be an I/O token; in fact patch 2/3 imposes that
>> the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to PCIBIOS_MIN_IO
>> we have free physical addresses that the accessors can operate on.
> 
> Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
> the logical I/O tokens, the purpose of that macro is really meant
> for allocating PCI I/O port numbers within the address space of
> one bus.
> 
> Note that it's equally likely that whichever next platform needs
> non-mapped I/O access like this actually needs them for PCI I/O space,
> and that will use it on addresses registered to a PCI host bridge.
> 
> If we separate the two steps:
> 
> a) assign a range of logical I/O port numbers to a bus
> b) register a set of helpers for redirecting logical I/O
>    port to a helper function
>
It seems that we need to add a new bus and the corresponding resource management
which can also cover current PCI pio mapping, is it right?

Thanks,
Zhichang

> then I think the code will get cleaner and more flexible.
> It should actually then be able to replace the powerpc
> specific implementation.
> 
> 	Arnd
> 
> .
> 

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 10:09                   ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-11 10:09 UTC (permalink / raw)
  To: Arnd Bergmann, Gabriele Paoloni
  Cc: linux-arm-kernel, mark.rutland, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, benh, John Garry, will.deacon, linux-kernel,
	xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc,
	linux-serial@vger.kernel.org

Hi, Arnd,

On 2016/11/11 0:07, Arnd Bergmann wrote:
> On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
>>
>> Where should we get the range from? For LPC we know that it is going
>> Work on anything that is not used by PCI I/O space, and this is 
>> why we use [0, PCIBIOS_MIN_IO]
> 
> It should be allocated the same way we allocate PCI config space
> segments. This is currently done with the io_range list in
> drivers/pci/pci.c, which isn't perfect but could be extended
> if necessary. Based on what others commented here, I'd rather
> make the differences between ISA/LPC and PCI I/O ranges smaller
> than larger.
> 
>>> Your current version has
>>>
>>>         if (arm64_extio_ops->pfout)                             \
>>>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>>>                        addr, value, sizeof(type));             \
>>>
>>> Instead, just subtract the start of the range from the logical
>>> port number to transform it back into a bus-local port number:
>>
>> These accessors do not operate on IO tokens:
>>
>> If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
>> addr is not going to be an I/O token; in fact patch 2/3 imposes that
>> the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to PCIBIOS_MIN_IO
>> we have free physical addresses that the accessors can operate on.
> 
> Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
> the logical I/O tokens, the purpose of that macro is really meant
> for allocating PCI I/O port numbers within the address space of
> one bus.
> 
> Note that it's equally likely that whichever next platform needs
> non-mapped I/O access like this actually needs them for PCI I/O space,
> and that will use it on addresses registered to a PCI host bridge.
> 
> If we separate the two steps:
> 
> a) assign a range of logical I/O port numbers to a bus
> b) register a set of helpers for redirecting logical I/O
>    port to a helper function
>
It seems that we need to add a new bus and the corresponding resource management
which can also cover current PCI pio mapping, is it right?

Thanks,
Zhichang

> then I think the code will get cleaner and more flexible.
> It should actually then be able to replace the powerpc
> specific implementation.
> 
> 	Arnd
> 
> .
> 

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 10:09                   ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-11 10:09 UTC (permalink / raw)
  To: Arnd Bergmann, Gabriele Paoloni
  Cc: linux-arm-kernel, mark.rutland, devicetree, lorenzo.pieralisi,
	minyard, linux-pci, benh, John Garry, will.deacon, linux-kernel,
	xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, liviu.dudau, bhelgaas@googl e.com,
	zhichang.yuan02

Hi, Arnd,

On 2016/11/11 0:07, Arnd Bergmann wrote:
> On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
>>
>> Where should we get the range from? For LPC we know that it is going
>> Work on anything that is not used by PCI I/O space, and this is 
>> why we use [0, PCIBIOS_MIN_IO]
> 
> It should be allocated the same way we allocate PCI config space
> segments. This is currently done with the io_range list in
> drivers/pci/pci.c, which isn't perfect but could be extended
> if necessary. Based on what others commented here, I'd rather
> make the differences between ISA/LPC and PCI I/O ranges smaller
> than larger.
> 
>>> Your current version has
>>>
>>>         if (arm64_extio_ops->pfout)                             \
>>>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>>>                        addr, value, sizeof(type));             \
>>>
>>> Instead, just subtract the start of the range from the logical
>>> port number to transform it back into a bus-local port number:
>>
>> These accessors do not operate on IO tokens:
>>
>> If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
>> addr is not going to be an I/O token; in fact patch 2/3 imposes that
>> the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to PCIBIOS_MIN_IO
>> we have free physical addresses that the accessors can operate on.
> 
> Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
> the logical I/O tokens, the purpose of that macro is really meant
> for allocating PCI I/O port numbers within the address space of
> one bus.
> 
> Note that it's equally likely that whichever next platform needs
> non-mapped I/O access like this actually needs them for PCI I/O space,
> and that will use it on addresses registered to a PCI host bridge.
> 
> If we separate the two steps:
> 
> a) assign a range of logical I/O port numbers to a bus
> b) register a set of helpers for redirecting logical I/O
>    port to a helper function
>
It seems that we need to add a new bus and the corresponding resource management
which can also cover current PCI pio mapping, is it right?

Thanks,
Zhichang

> then I think the code will get cleaner and more flexible.
> It should actually then be able to replace the powerpc
> specific implementation.
> 
> 	Arnd
> 
> .
> 

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 10:09                   ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-11 10:09 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, Arnd,

On 2016/11/11 0:07, Arnd Bergmann wrote:
> On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
>>
>> Where should we get the range from? For LPC we know that it is going
>> Work on anything that is not used by PCI I/O space, and this is 
>> why we use [0, PCIBIOS_MIN_IO]
> 
> It should be allocated the same way we allocate PCI config space
> segments. This is currently done with the io_range list in
> drivers/pci/pci.c, which isn't perfect but could be extended
> if necessary. Based on what others commented here, I'd rather
> make the differences between ISA/LPC and PCI I/O ranges smaller
> than larger.
> 
>>> Your current version has
>>>
>>>         if (arm64_extio_ops->pfout)                             \
>>>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>>>                        addr, value, sizeof(type));             \
>>>
>>> Instead, just subtract the start of the range from the logical
>>> port number to transform it back into a bus-local port number:
>>
>> These accessors do not operate on IO tokens:
>>
>> If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
>> addr is not going to be an I/O token; in fact patch 2/3 imposes that
>> the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to PCIBIOS_MIN_IO
>> we have free physical addresses that the accessors can operate on.
> 
> Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
> the logical I/O tokens, the purpose of that macro is really meant
> for allocating PCI I/O port numbers within the address space of
> one bus.
> 
> Note that it's equally likely that whichever next platform needs
> non-mapped I/O access like this actually needs them for PCI I/O space,
> and that will use it on addresses registered to a PCI host bridge.
> 
> If we separate the two steps:
> 
> a) assign a range of logical I/O port numbers to a bus
> b) register a set of helpers for redirecting logical I/O
>    port to a helper function
>
It seems that we need to add a new bus and the corresponding resource management
which can also cover current PCI pio mapping, is it right?

Thanks,
Zhichang

> then I think the code will get cleaner and more flexible.
> It should actually then be able to replace the powerpc
> specific implementation.
> 
> 	Arnd
> 
> .
> 

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
  2016-11-10 16:06           ` Gabriele Paoloni
  (?)
  (?)
@ 2016-11-11 10:37             ` liviu.dudau
  -1 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau @ 2016-11-11 10:37 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Yuanzhichang, catalin.marinas, will.deacon, robh+dt, bhelgaas,
	mark.rutland, olof, arnd, linux-arm-kernel, lorenzo.pieralisi,
	linux-kernel, Linuxarm, devicetree, linux-pci, linux-serial,
	minyard, benh, zourongrong, John Garry, zhichang.yuan02, kantyzc,
	xuwei (O)

On Thu, Nov 10, 2016 at 04:06:40PM +0000, Gabriele Paoloni wrote:
> Hi Liviu
> 
> > -----Original Message-----
> > From: liviu.dudau@arm.com [mailto:liviu.dudau@arm.com]
> > Sent: 09 November 2016 16:51
> > To: Gabriele Paoloni
> > Cc: Yuanzhichang; catalin.marinas@arm.com; will.deacon@arm.com;
> > robh+dt@kernel.org; bhelgaas@google.com; mark.rutland@arm.com;
> > olof@lixom.net; arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> > lorenzo.pieralisi@arm.com; linux-kernel@vger.kernel.org; Linuxarm;
> > devicetree@vger.kernel.org; linux-pci@vger.kernel.org; linux-
> > serial@vger.kernel.org; minyard@acm.org; benh@kernel.crashing.org;
> > zourongrong@gmail.com; John Garry; zhichang.yuan02@gmail.com;
> > kantyzc@163.com; xuwei (O)
> > Subject: Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for
> > special ISA
> > 
> > On Wed, Nov 09, 2016 at 04:16:17PM +0000, Gabriele Paoloni wrote:
> > > Hi Liviu
> > >
> > > Thanks for reviewing
> > >
> > 
> > [removed some irrelevant part of discussion, avoid crazy formatting]
> > 
> > > > > +/**
> > > > > + * addr_is_indirect_io - check whether the input taddr is for
> > > > indirectIO.
> > > > > + * @taddr: the io address to be checked.
> > > > > + *
> > > > > + * Returns 1 when taddr is in the range; otherwise return 0.
> > > > > + */
> > > > > +int addr_is_indirect_io(u64 taddr)
> > > > > +{
> > > > > +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end
> > <
> > > > taddr)
> > > >
> > > > start >= taddr ?
> > >
> > > Nope... if  (taddr < arm64_extio_ops->start || taddr >
> > arm64_extio_ops->end)
> > > then taddr is outside the range [start; end] and will return 0;
> > otherwise
> > > it will return 1...
> > 
> > Oops, sorry, did not pay attention to the returned value. The check is
> > correct as it is, no need to change then.
> > 
> > >
> > > >
> > > > > +		return 0;
> > > > > +
> > > > > +	return 1;
> > > > > +}
> > > > >
> > > > >  BUILD_EXTIO(b, u8)
> > > > >
> > > > > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > > > > index 02b2903..cc2a05d 100644
> > > > > --- a/drivers/of/address.c
> > > > > +++ b/drivers/of/address.c
> > > > > @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
> > > > device_node *np)
> > > > >  	return false;
> > > > >  }
> > > > >
> > > > > +
> > > > > +/*
> > > > > + * of_isa_indirect_io - get the IO address from some isa reg
> > > > property value.
> > > > > + *	For some isa/lpc devices, no ranges property in ancestor
> > node.
> > > > > + *	The device addresses are described directly in their regs
> > > > property.
> > > > > + *	This fixup function will be called to get the IO address of
> > > > isa/lpc
> > > > > + *	devices when the normal of_translation failed.
> > > > > + *
> > > > > + * @parent:	points to the parent dts node;
> > > > > + * @bus:		points to the of_bus which can be used to parse
> > > > address;
> > > > > + * @addr:	the address from reg property;
> > > > > + * @na:		the address cell counter of @addr;
> > > > > + * @presult:	store the address paresed from @addr;
> > > > > + *
> > > > > + * return 1 when successfully get the I/O address;
> > > > > + * 0 will return for some failures.
> > > >
> > > > Bah, you are returning a signed int, why 0 for failure? Return a
> > > > negative value with
> > > > error codes. Otherwise change the return value into a bool.
> > >
> > > Yes we'll move to bool
> > >
> > > >
> > > > > + */
> > > > > +static int of_get_isa_indirect_io(struct device_node *parent,
> > > > > +				struct of_bus *bus, __be32 *addr,
> > > > > +				int na, u64 *presult)
> > > > > +{
> > > > > +	unsigned int flags;
> > > > > +	unsigned int rlen;
> > > > > +
> > > > > +	/* whether support indirectIO */
> > > > > +	if (!indirect_io_enabled())
> > > > > +		return 0;
> > > > > +
> > > > > +	if (!of_bus_isa_match(parent))
> > > > > +		return 0;
> > > > > +
> > > > > +	flags = bus->get_flags(addr);
> > > > > +	if (!(flags & IORESOURCE_IO))
> > > > > +		return 0;
> > > > > +
> > > > > +	/* there is ranges property, apply the normal translation
> > > > directly. */
> > > >
> > > > s/there is ranges/if we have a 'ranges'/
> > >
> > > Thanks for spotting this
> > >
> > > >
> > > > > +	if (of_get_property(parent, "ranges", &rlen))
> > > > > +		return 0;
> > > > > +
> > > > > +	*presult = of_read_number(addr + 1, na - 1);
> > > > > +	/* this fixup is only valid for specific I/O range. */
> > > > > +	return addr_is_indirect_io(*presult);
> > > > > +}
> > > > > +
> > > > >  static int of_translate_one(struct device_node *parent, struct
> > > > of_bus *bus,
> > > > >  			    struct of_bus *pbus, __be32 *addr,
> > > > >  			    int na, int ns, int pna, const char *rprop)
> > > > > @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
> > > > device_node *dev,
> > > > >  			result = of_read_number(addr, na);
> > > > >  			break;
> > > > >  		}
> > > > > +		/*
> > > > > +		 * For indirectIO device which has no ranges
> > property, get
> > > > > +		 * the address from reg directly.
> > > > > +		 */
> > > > > +		if (of_get_isa_indirect_io(dev, bus, addr, na,
> > &result)) {
> > > > > +			pr_debug("isa indirectIO matched(%s)..addr =
> > > > 0x%llx\n",
> > > > > +				of_node_full_name(dev), result);
> > > > > +			break;
> > > > > +		}
> > > > >
> > > > >  		/* Get new parent bus and counts */
> > > > >  		pbus = of_match_bus(parent);
> > > > > @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
> > > > device_node *dev,
> > > > >  	if (taddr == OF_BAD_ADDR)
> > > > >  		return -EINVAL;
> > > > >  	memset(r, 0, sizeof(struct resource));
> > > > > -	if (flags & IORESOURCE_IO) {
> > > > > +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
> > > > >  		unsigned long port;
> > > > > +
> > > > >  		port = pci_address_to_pio(taddr);
> > > > >  		if (port == (unsigned long)-1)
> > > > >  			return -EINVAL;
> > > > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > > > > index ba34907..1a08511 100644
> > > > > --- a/drivers/pci/pci.c
> > > > > +++ b/drivers/pci/pci.c
> > > > > @@ -3263,7 +3263,7 @@ 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;
> > > > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > > > >
> > > > >  	/* check if the range hasn't been previously recorded */
> > > > >  	spin_lock(&io_range_lock);
> > > > > @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned
> > long
> > > > pio)
> > > > >
> > > > >  #ifdef PCI_IOBASE
> > > > >  	struct io_range *range;
> > > > > -	resource_size_t allocated_size = 0;
> > > > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > > >
> > > > Have you checked that pci_pio_to_address still returns valid values
> > > > after this? I know that
> > > > you are trying to take into account PCIBIOS_MIN_IO limit when
> > > > allocating reserving the IO ranges,
> > > > but the values added in the io_range_list are still starting from
> > zero,
> > > > no from PCIBIOS_MIN_IO,
> > >
> > > I think you're wrong here as in pci_address_to_pio we have:
> > > +	resource_size_t offset = PCIBIOS_MIN_IO;
> > >
> > > This should be enough to guarantee that the PIOs start at
> > > PCIBIOS_MIN_IO...right?
> > 
> > I don't think you can guarantee that the pio value that gets passed
> > into
> > pci_pio_to_address() always comes from a previously returned value by
> > pci_address_to_pio(). Maybe you can add a check in pci_pio_to_address()
> 
> Maybe I am missing something...could you make an exampleof a case
> where an IO toke doesn’t come from pci_address_to_pio() ?

Don't know, maybe it is coming from some DT or platform data? I was just
asking for confirmation that no one has seen issues there, I'm not saying
I've seen it happening.

Best regards,
Liviu

> 
> Thanks
> 
> Gab
> 
> 
> > 
> > 	if (pio < PCIBIOS_MIN_IO)
> > 		return address;
> > 
> > to avoid adding more checks in the list_for_each_entry() loop.
> > 
> > Best regards,
> > Liviu
> > 
> > >
> > >
> > > > so the calculation of the address in this function could return
> > > > negative values casted to pci_addr_t.
> > > >
> > > > Maybe you want to adjust the range->start value in
> > > > pci_register_io_range() as well to have it
> > > > offset by PCIBIOS_MIN_IO as well.
> > > >
> > > > Best regards,
> > > > Liviu
> > > >
> > > > >
> > > > >  	if (pio > IO_SPACE_LIMIT)
> > > > >  		return address;
> > > > > @@ -3335,7 +3335,7 @@ unsigned long __weak
> > > > pci_address_to_pio(phys_addr_t address)
> > > > >  {
> > > > >  #ifdef PCI_IOBASE
> > > > >  	struct io_range *res;
> > > > > -	resource_size_t offset = 0;
> > > > > +	resource_size_t offset = PCIBIOS_MIN_IO;
> > > > >  	unsigned long addr = -1;
> > > > >
> > > > >  	spin_lock(&io_range_lock);
> > > > > diff --git a/include/linux/of_address.h
> > b/include/linux/of_address.h
> > > > > index 3786473..deec469 100644
> > > > > --- a/include/linux/of_address.h
> > > > > +++ b/include/linux/of_address.h
> > > > > @@ -24,6 +24,23 @@ struct of_pci_range {
> > > > >  #define for_each_of_pci_range(parser, range) \
> > > > >  	for (; of_pci_range_parser_one(parser, range);)
> > > > >
> > > > > +
> > > > > +#ifndef indirect_io_enabled
> > > > > +#define indirect_io_enabled indirect_io_enabled
> > > > > +static inline bool indirect_io_enabled(void)
> > > > > +{
> > > > > +	return false;
> > > > > +}
> > > > > +#endif
> > > > > +
> > > > > +#ifndef addr_is_indirect_io
> > > > > +#define addr_is_indirect_io addr_is_indirect_io
> > > > > +static inline int addr_is_indirect_io(u64 taddr)
> > > > > +{
> > > > > +	return 0;
> > > > > +}
> > > > > +#endif
> > > > > +
> > > > >  /* Translate a DMA address from device space to CPU space */
> > > > >  extern u64 of_translate_dma_address(struct device_node *dev,
> > > > >  				    const __be32 *in_addr);
> > > > > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > > > > index 0e49f70..7f6bbb6 100644
> > > > > --- a/include/linux/pci.h
> > > > > +++ b/include/linux/pci.h
> > > > > @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
> > > > pci_bus *bus)
> > > > >  /* provide the legacy pci_dma_* API */
> > > > >  #include <linux/pci-dma-compat.h>
> > > > >
> > > > > +/*
> > > > > + * define this macro here to refrain from compilation error for
> > some
> > > > > + * platforms. Please keep this macro at the end of this header
> > file.
> > > > > + */
> > > > > +#ifndef PCIBIOS_MIN_IO
> > > > > +#define PCIBIOS_MIN_IO		0
> > > > > +#endif
> > > > > +
> > > > >  #endif /* LINUX_PCI_H */
> > > > > --
> > > > > 1.9.1
> > > > >
> > > > > --
> > > > > To unsubscribe from this list: send the line "unsubscribe linux-
> > pci"
> > > > in
> > > > > the body of a message to majordomo@vger.kernel.org
> > > > > More majordomo info at  http://vger.kernel.org/majordomo-
> > info.html
> > 
> > --
> > ====================
> > | I would like to |
> > | fix the world,  |
> > | but they're not |
> > | giving me the   |
> >  \ source code!  /
> >   ---------------
> >     ¯\_(ツ)_/¯

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

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-11 10:37             ` liviu.dudau
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau @ 2016-11-11 10:37 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Yuanzhichang, catalin.marinas, will.deacon, robh+dt, bhelgaas,
	mark.rutland, olof, arnd, linux-arm-kernel, lorenzo.pieralisi,
	linux-kernel, Linuxarm, devicetree, linux-pci, linux-serial,
	minyard@acm.org

On Thu, Nov 10, 2016 at 04:06:40PM +0000, Gabriele Paoloni wrote:
> Hi Liviu
> 
> > -----Original Message-----
> > From: liviu.dudau@arm.com [mailto:liviu.dudau@arm.com]
> > Sent: 09 November 2016 16:51
> > To: Gabriele Paoloni
> > Cc: Yuanzhichang; catalin.marinas@arm.com; will.deacon@arm.com;
> > robh+dt@kernel.org; bhelgaas@google.com; mark.rutland@arm.com;
> > olof@lixom.net; arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> > lorenzo.pieralisi@arm.com; linux-kernel@vger.kernel.org; Linuxarm;
> > devicetree@vger.kernel.org; linux-pci@vger.kernel.org; linux-
> > serial@vger.kernel.org; minyard@acm.org; benh@kernel.crashing.org;
> > zourongrong@gmail.com; John Garry; zhichang.yuan02@gmail.com;
> > kantyzc@163.com; xuwei (O)
> > Subject: Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for
> > special ISA
> > 
> > On Wed, Nov 09, 2016 at 04:16:17PM +0000, Gabriele Paoloni wrote:
> > > Hi Liviu
> > >
> > > Thanks for reviewing
> > >
> > 
> > [removed some irrelevant part of discussion, avoid crazy formatting]
> > 
> > > > > +/**
> > > > > + * addr_is_indirect_io - check whether the input taddr is for
> > > > indirectIO.
> > > > > + * @taddr: the io address to be checked.
> > > > > + *
> > > > > + * Returns 1 when taddr is in the range; otherwise return 0.
> > > > > + */
> > > > > +int addr_is_indirect_io(u64 taddr)
> > > > > +{
> > > > > +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end
> > <
> > > > taddr)
> > > >
> > > > start >= taddr ?
> > >
> > > Nope... if  (taddr < arm64_extio_ops->start || taddr >
> > arm64_extio_ops->end)
> > > then taddr is outside the range [start; end] and will return 0;
> > otherwise
> > > it will return 1...
> > 
> > Oops, sorry, did not pay attention to the returned value. The check is
> > correct as it is, no need to change then.
> > 
> > >
> > > >
> > > > > +		return 0;
> > > > > +
> > > > > +	return 1;
> > > > > +}
> > > > >
> > > > >  BUILD_EXTIO(b, u8)
> > > > >
> > > > > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > > > > index 02b2903..cc2a05d 100644
> > > > > --- a/drivers/of/address.c
> > > > > +++ b/drivers/of/address.c
> > > > > @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
> > > > device_node *np)
> > > > >  	return false;
> > > > >  }
> > > > >
> > > > > +
> > > > > +/*
> > > > > + * of_isa_indirect_io - get the IO address from some isa reg
> > > > property value.
> > > > > + *	For some isa/lpc devices, no ranges property in ancestor
> > node.
> > > > > + *	The device addresses are described directly in their regs
> > > > property.
> > > > > + *	This fixup function will be called to get the IO address of
> > > > isa/lpc
> > > > > + *	devices when the normal of_translation failed.
> > > > > + *
> > > > > + * @parent:	points to the parent dts node;
> > > > > + * @bus:		points to the of_bus which can be used to parse
> > > > address;
> > > > > + * @addr:	the address from reg property;
> > > > > + * @na:		the address cell counter of @addr;
> > > > > + * @presult:	store the address paresed from @addr;
> > > > > + *
> > > > > + * return 1 when successfully get the I/O address;
> > > > > + * 0 will return for some failures.
> > > >
> > > > Bah, you are returning a signed int, why 0 for failure? Return a
> > > > negative value with
> > > > error codes. Otherwise change the return value into a bool.
> > >
> > > Yes we'll move to bool
> > >
> > > >
> > > > > + */
> > > > > +static int of_get_isa_indirect_io(struct device_node *parent,
> > > > > +				struct of_bus *bus, __be32 *addr,
> > > > > +				int na, u64 *presult)
> > > > > +{
> > > > > +	unsigned int flags;
> > > > > +	unsigned int rlen;
> > > > > +
> > > > > +	/* whether support indirectIO */
> > > > > +	if (!indirect_io_enabled())
> > > > > +		return 0;
> > > > > +
> > > > > +	if (!of_bus_isa_match(parent))
> > > > > +		return 0;
> > > > > +
> > > > > +	flags = bus->get_flags(addr);
> > > > > +	if (!(flags & IORESOURCE_IO))
> > > > > +		return 0;
> > > > > +
> > > > > +	/* there is ranges property, apply the normal translation
> > > > directly. */
> > > >
> > > > s/there is ranges/if we have a 'ranges'/
> > >
> > > Thanks for spotting this
> > >
> > > >
> > > > > +	if (of_get_property(parent, "ranges", &rlen))
> > > > > +		return 0;
> > > > > +
> > > > > +	*presult = of_read_number(addr + 1, na - 1);
> > > > > +	/* this fixup is only valid for specific I/O range. */
> > > > > +	return addr_is_indirect_io(*presult);
> > > > > +}
> > > > > +
> > > > >  static int of_translate_one(struct device_node *parent, struct
> > > > of_bus *bus,
> > > > >  			    struct of_bus *pbus, __be32 *addr,
> > > > >  			    int na, int ns, int pna, const char *rprop)
> > > > > @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
> > > > device_node *dev,
> > > > >  			result = of_read_number(addr, na);
> > > > >  			break;
> > > > >  		}
> > > > > +		/*
> > > > > +		 * For indirectIO device which has no ranges
> > property, get
> > > > > +		 * the address from reg directly.
> > > > > +		 */
> > > > > +		if (of_get_isa_indirect_io(dev, bus, addr, na,
> > &result)) {
> > > > > +			pr_debug("isa indirectIO matched(%s)..addr =
> > > > 0x%llx\n",
> > > > > +				of_node_full_name(dev), result);
> > > > > +			break;
> > > > > +		}
> > > > >
> > > > >  		/* Get new parent bus and counts */
> > > > >  		pbus = of_match_bus(parent);
> > > > > @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
> > > > device_node *dev,
> > > > >  	if (taddr == OF_BAD_ADDR)
> > > > >  		return -EINVAL;
> > > > >  	memset(r, 0, sizeof(struct resource));
> > > > > -	if (flags & IORESOURCE_IO) {
> > > > > +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
> > > > >  		unsigned long port;
> > > > > +
> > > > >  		port = pci_address_to_pio(taddr);
> > > > >  		if (port == (unsigned long)-1)
> > > > >  			return -EINVAL;
> > > > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > > > > index ba34907..1a08511 100644
> > > > > --- a/drivers/pci/pci.c
> > > > > +++ b/drivers/pci/pci.c
> > > > > @@ -3263,7 +3263,7 @@ 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;
> > > > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > > > >
> > > > >  	/* check if the range hasn't been previously recorded */
> > > > >  	spin_lock(&io_range_lock);
> > > > > @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned
> > long
> > > > pio)
> > > > >
> > > > >  #ifdef PCI_IOBASE
> > > > >  	struct io_range *range;
> > > > > -	resource_size_t allocated_size = 0;
> > > > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > > >
> > > > Have you checked that pci_pio_to_address still returns valid values
> > > > after this? I know that
> > > > you are trying to take into account PCIBIOS_MIN_IO limit when
> > > > allocating reserving the IO ranges,
> > > > but the values added in the io_range_list are still starting from
> > zero,
> > > > no from PCIBIOS_MIN_IO,
> > >
> > > I think you're wrong here as in pci_address_to_pio we have:
> > > +	resource_size_t offset = PCIBIOS_MIN_IO;
> > >
> > > This should be enough to guarantee that the PIOs start at
> > > PCIBIOS_MIN_IO...right?
> > 
> > I don't think you can guarantee that the pio value that gets passed
> > into
> > pci_pio_to_address() always comes from a previously returned value by
> > pci_address_to_pio(). Maybe you can add a check in pci_pio_to_address()
> 
> Maybe I am missing something...could you make an exampleof a case
> where an IO toke doesn’t come from pci_address_to_pio() ?

Don't know, maybe it is coming from some DT or platform data? I was just
asking for confirmation that no one has seen issues there, I'm not saying
I've seen it happening.

Best regards,
Liviu

> 
> Thanks
> 
> Gab
> 
> 
> > 
> > 	if (pio < PCIBIOS_MIN_IO)
> > 		return address;
> > 
> > to avoid adding more checks in the list_for_each_entry() loop.
> > 
> > Best regards,
> > Liviu
> > 
> > >
> > >
> > > > so the calculation of the address in this function could return
> > > > negative values casted to pci_addr_t.
> > > >
> > > > Maybe you want to adjust the range->start value in
> > > > pci_register_io_range() as well to have it
> > > > offset by PCIBIOS_MIN_IO as well.
> > > >
> > > > Best regards,
> > > > Liviu
> > > >
> > > > >
> > > > >  	if (pio > IO_SPACE_LIMIT)
> > > > >  		return address;
> > > > > @@ -3335,7 +3335,7 @@ unsigned long __weak
> > > > pci_address_to_pio(phys_addr_t address)
> > > > >  {
> > > > >  #ifdef PCI_IOBASE
> > > > >  	struct io_range *res;
> > > > > -	resource_size_t offset = 0;
> > > > > +	resource_size_t offset = PCIBIOS_MIN_IO;
> > > > >  	unsigned long addr = -1;
> > > > >
> > > > >  	spin_lock(&io_range_lock);
> > > > > diff --git a/include/linux/of_address.h
> > b/include/linux/of_address.h
> > > > > index 3786473..deec469 100644
> > > > > --- a/include/linux/of_address.h
> > > > > +++ b/include/linux/of_address.h
> > > > > @@ -24,6 +24,23 @@ struct of_pci_range {
> > > > >  #define for_each_of_pci_range(parser, range) \
> > > > >  	for (; of_pci_range_parser_one(parser, range);)
> > > > >
> > > > > +
> > > > > +#ifndef indirect_io_enabled
> > > > > +#define indirect_io_enabled indirect_io_enabled
> > > > > +static inline bool indirect_io_enabled(void)
> > > > > +{
> > > > > +	return false;
> > > > > +}
> > > > > +#endif
> > > > > +
> > > > > +#ifndef addr_is_indirect_io
> > > > > +#define addr_is_indirect_io addr_is_indirect_io
> > > > > +static inline int addr_is_indirect_io(u64 taddr)
> > > > > +{
> > > > > +	return 0;
> > > > > +}
> > > > > +#endif
> > > > > +
> > > > >  /* Translate a DMA address from device space to CPU space */
> > > > >  extern u64 of_translate_dma_address(struct device_node *dev,
> > > > >  				    const __be32 *in_addr);
> > > > > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > > > > index 0e49f70..7f6bbb6 100644
> > > > > --- a/include/linux/pci.h
> > > > > +++ b/include/linux/pci.h
> > > > > @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
> > > > pci_bus *bus)
> > > > >  /* provide the legacy pci_dma_* API */
> > > > >  #include <linux/pci-dma-compat.h>
> > > > >
> > > > > +/*
> > > > > + * define this macro here to refrain from compilation error for
> > some
> > > > > + * platforms. Please keep this macro at the end of this header
> > file.
> > > > > + */
> > > > > +#ifndef PCIBIOS_MIN_IO
> > > > > +#define PCIBIOS_MIN_IO		0
> > > > > +#endif
> > > > > +
> > > > >  #endif /* LINUX_PCI_H */
> > > > > --
> > > > > 1.9.1
> > > > >
> > > > > --
> > > > > To unsubscribe from this list: send the line "unsubscribe linux-
> > pci"
> > > > in
> > > > > the body of a message to majordomo@vger.kernel.org
> > > > > More majordomo info at  http://vger.kernel.org/majordomo-
> > info.html
> > 
> > --
> > ====================
> > | I would like to |
> > | fix the world,  |
> > | but they're not |
> > | giving me the   |
> >  \ source code!  /
> >   ---------------
> >     ¯\_(ツ)_/¯

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

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-11 10:37             ` liviu.dudau
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau @ 2016-11-11 10:37 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Yuanzhichang, catalin.marinas, will.deacon, robh+dt, bhelgaas,
	mark.rutland, olof, arnd, linux-arm-kernel, lorenzo.pieralisi,
	linux-kernel, Linuxarm, devicetree, linux-pci, linux-serial,
	minyard, benh, zourongrong, John Garry, zhichang.yuan02, kantyzc,
	xuwei (O)

On Thu, Nov 10, 2016 at 04:06:40PM +0000, Gabriele Paoloni wrote:
> Hi Liviu
> 
> > -----Original Message-----
> > From: liviu.dudau@arm.com [mailto:liviu.dudau@arm.com]
> > Sent: 09 November 2016 16:51
> > To: Gabriele Paoloni
> > Cc: Yuanzhichang; catalin.marinas@arm.com; will.deacon@arm.com;
> > robh+dt@kernel.org; bhelgaas@google.com; mark.rutland@arm.com;
> > olof@lixom.net; arnd@arndb.de; linux-arm-kernel@lists.infradead.org;
> > lorenzo.pieralisi@arm.com; linux-kernel@vger.kernel.org; Linuxarm;
> > devicetree@vger.kernel.org; linux-pci@vger.kernel.org; linux-
> > serial@vger.kernel.org; minyard@acm.org; benh@kernel.crashing.org;
> > zourongrong@gmail.com; John Garry; zhichang.yuan02@gmail.com;
> > kantyzc@163.com; xuwei (O)
> > Subject: Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for
> > special ISA
> > 
> > On Wed, Nov 09, 2016 at 04:16:17PM +0000, Gabriele Paoloni wrote:
> > > Hi Liviu
> > >
> > > Thanks for reviewing
> > >
> > 
> > [removed some irrelevant part of discussion, avoid crazy formatting]
> > 
> > > > > +/**
> > > > > + * addr_is_indirect_io - check whether the input taddr is for
> > > > indirectIO.
> > > > > + * @taddr: the io address to be checked.
> > > > > + *
> > > > > + * Returns 1 when taddr is in the range; otherwise return 0.
> > > > > + */
> > > > > +int addr_is_indirect_io(u64 taddr)
> > > > > +{
> > > > > +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end
> > <
> > > > taddr)
> > > >
> > > > start >= taddr ?
> > >
> > > Nope... if  (taddr < arm64_extio_ops->start || taddr >
> > arm64_extio_ops->end)
> > > then taddr is outside the range [start; end] and will return 0;
> > otherwise
> > > it will return 1...
> > 
> > Oops, sorry, did not pay attention to the returned value. The check is
> > correct as it is, no need to change then.
> > 
> > >
> > > >
> > > > > +		return 0;
> > > > > +
> > > > > +	return 1;
> > > > > +}
> > > > >
> > > > >  BUILD_EXTIO(b, u8)
> > > > >
> > > > > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > > > > index 02b2903..cc2a05d 100644
> > > > > --- a/drivers/of/address.c
> > > > > +++ b/drivers/of/address.c
> > > > > @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
> > > > device_node *np)
> > > > >  	return false;
> > > > >  }
> > > > >
> > > > > +
> > > > > +/*
> > > > > + * of_isa_indirect_io - get the IO address from some isa reg
> > > > property value.
> > > > > + *	For some isa/lpc devices, no ranges property in ancestor
> > node.
> > > > > + *	The device addresses are described directly in their regs
> > > > property.
> > > > > + *	This fixup function will be called to get the IO address of
> > > > isa/lpc
> > > > > + *	devices when the normal of_translation failed.
> > > > > + *
> > > > > + * @parent:	points to the parent dts node;
> > > > > + * @bus:		points to the of_bus which can be used to parse
> > > > address;
> > > > > + * @addr:	the address from reg property;
> > > > > + * @na:		the address cell counter of @addr;
> > > > > + * @presult:	store the address paresed from @addr;
> > > > > + *
> > > > > + * return 1 when successfully get the I/O address;
> > > > > + * 0 will return for some failures.
> > > >
> > > > Bah, you are returning a signed int, why 0 for failure? Return a
> > > > negative value with
> > > > error codes. Otherwise change the return value into a bool.
> > >
> > > Yes we'll move to bool
> > >
> > > >
> > > > > + */
> > > > > +static int of_get_isa_indirect_io(struct device_node *parent,
> > > > > +				struct of_bus *bus, __be32 *addr,
> > > > > +				int na, u64 *presult)
> > > > > +{
> > > > > +	unsigned int flags;
> > > > > +	unsigned int rlen;
> > > > > +
> > > > > +	/* whether support indirectIO */
> > > > > +	if (!indirect_io_enabled())
> > > > > +		return 0;
> > > > > +
> > > > > +	if (!of_bus_isa_match(parent))
> > > > > +		return 0;
> > > > > +
> > > > > +	flags = bus->get_flags(addr);
> > > > > +	if (!(flags & IORESOURCE_IO))
> > > > > +		return 0;
> > > > > +
> > > > > +	/* there is ranges property, apply the normal translation
> > > > directly. */
> > > >
> > > > s/there is ranges/if we have a 'ranges'/
> > >
> > > Thanks for spotting this
> > >
> > > >
> > > > > +	if (of_get_property(parent, "ranges", &rlen))
> > > > > +		return 0;
> > > > > +
> > > > > +	*presult = of_read_number(addr + 1, na - 1);
> > > > > +	/* this fixup is only valid for specific I/O range. */
> > > > > +	return addr_is_indirect_io(*presult);
> > > > > +}
> > > > > +
> > > > >  static int of_translate_one(struct device_node *parent, struct
> > > > of_bus *bus,
> > > > >  			    struct of_bus *pbus, __be32 *addr,
> > > > >  			    int na, int ns, int pna, const char *rprop)
> > > > > @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
> > > > device_node *dev,
> > > > >  			result = of_read_number(addr, na);
> > > > >  			break;
> > > > >  		}
> > > > > +		/*
> > > > > +		 * For indirectIO device which has no ranges
> > property, get
> > > > > +		 * the address from reg directly.
> > > > > +		 */
> > > > > +		if (of_get_isa_indirect_io(dev, bus, addr, na,
> > &result)) {
> > > > > +			pr_debug("isa indirectIO matched(%s)..addr =
> > > > 0x%llx\n",
> > > > > +				of_node_full_name(dev), result);
> > > > > +			break;
> > > > > +		}
> > > > >
> > > > >  		/* Get new parent bus and counts */
> > > > >  		pbus = of_match_bus(parent);
> > > > > @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
> > > > device_node *dev,
> > > > >  	if (taddr == OF_BAD_ADDR)
> > > > >  		return -EINVAL;
> > > > >  	memset(r, 0, sizeof(struct resource));
> > > > > -	if (flags & IORESOURCE_IO) {
> > > > > +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
> > > > >  		unsigned long port;
> > > > > +
> > > > >  		port = pci_address_to_pio(taddr);
> > > > >  		if (port == (unsigned long)-1)
> > > > >  			return -EINVAL;
> > > > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > > > > index ba34907..1a08511 100644
> > > > > --- a/drivers/pci/pci.c
> > > > > +++ b/drivers/pci/pci.c
> > > > > @@ -3263,7 +3263,7 @@ 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;
> > > > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > > > >
> > > > >  	/* check if the range hasn't been previously recorded */
> > > > >  	spin_lock(&io_range_lock);
> > > > > @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned
> > long
> > > > pio)
> > > > >
> > > > >  #ifdef PCI_IOBASE
> > > > >  	struct io_range *range;
> > > > > -	resource_size_t allocated_size = 0;
> > > > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > > >
> > > > Have you checked that pci_pio_to_address still returns valid values
> > > > after this? I know that
> > > > you are trying to take into account PCIBIOS_MIN_IO limit when
> > > > allocating reserving the IO ranges,
> > > > but the values added in the io_range_list are still starting from
> > zero,
> > > > no from PCIBIOS_MIN_IO,
> > >
> > > I think you're wrong here as in pci_address_to_pio we have:
> > > +	resource_size_t offset = PCIBIOS_MIN_IO;
> > >
> > > This should be enough to guarantee that the PIOs start at
> > > PCIBIOS_MIN_IO...right?
> > 
> > I don't think you can guarantee that the pio value that gets passed
> > into
> > pci_pio_to_address() always comes from a previously returned value by
> > pci_address_to_pio(). Maybe you can add a check in pci_pio_to_address()
> 
> Maybe I am missing something...could you make an exampleof a case
> where an IO toke doesn’t come from pci_address_to_pio() ?

Don't know, maybe it is coming from some DT or platform data? I was just
asking for confirmation that no one has seen issues there, I'm not saying
I've seen it happening.

Best regards,
Liviu

> 
> Thanks
> 
> Gab
> 
> 
> > 
> > 	if (pio < PCIBIOS_MIN_IO)
> > 		return address;
> > 
> > to avoid adding more checks in the list_for_each_entry() loop.
> > 
> > Best regards,
> > Liviu
> > 
> > >
> > >
> > > > so the calculation of the address in this function could return
> > > > negative values casted to pci_addr_t.
> > > >
> > > > Maybe you want to adjust the range->start value in
> > > > pci_register_io_range() as well to have it
> > > > offset by PCIBIOS_MIN_IO as well.
> > > >
> > > > Best regards,
> > > > Liviu
> > > >
> > > > >
> > > > >  	if (pio > IO_SPACE_LIMIT)
> > > > >  		return address;
> > > > > @@ -3335,7 +3335,7 @@ unsigned long __weak
> > > > pci_address_to_pio(phys_addr_t address)
> > > > >  {
> > > > >  #ifdef PCI_IOBASE
> > > > >  	struct io_range *res;
> > > > > -	resource_size_t offset = 0;
> > > > > +	resource_size_t offset = PCIBIOS_MIN_IO;
> > > > >  	unsigned long addr = -1;
> > > > >
> > > > >  	spin_lock(&io_range_lock);
> > > > > diff --git a/include/linux/of_address.h
> > b/include/linux/of_address.h
> > > > > index 3786473..deec469 100644
> > > > > --- a/include/linux/of_address.h
> > > > > +++ b/include/linux/of_address.h
> > > > > @@ -24,6 +24,23 @@ struct of_pci_range {
> > > > >  #define for_each_of_pci_range(parser, range) \
> > > > >  	for (; of_pci_range_parser_one(parser, range);)
> > > > >
> > > > > +
> > > > > +#ifndef indirect_io_enabled
> > > > > +#define indirect_io_enabled indirect_io_enabled
> > > > > +static inline bool indirect_io_enabled(void)
> > > > > +{
> > > > > +	return false;
> > > > > +}
> > > > > +#endif
> > > > > +
> > > > > +#ifndef addr_is_indirect_io
> > > > > +#define addr_is_indirect_io addr_is_indirect_io
> > > > > +static inline int addr_is_indirect_io(u64 taddr)
> > > > > +{
> > > > > +	return 0;
> > > > > +}
> > > > > +#endif
> > > > > +
> > > > >  /* Translate a DMA address from device space to CPU space */
> > > > >  extern u64 of_translate_dma_address(struct device_node *dev,
> > > > >  				    const __be32 *in_addr);
> > > > > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > > > > index 0e49f70..7f6bbb6 100644
> > > > > --- a/include/linux/pci.h
> > > > > +++ b/include/linux/pci.h
> > > > > @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
> > > > pci_bus *bus)
> > > > >  /* provide the legacy pci_dma_* API */
> > > > >  #include <linux/pci-dma-compat.h>
> > > > >
> > > > > +/*
> > > > > + * define this macro here to refrain from compilation error for
> > some
> > > > > + * platforms. Please keep this macro at the end of this header
> > file.
> > > > > + */
> > > > > +#ifndef PCIBIOS_MIN_IO
> > > > > +#define PCIBIOS_MIN_IO		0
> > > > > +#endif
> > > > > +
> > > > >  #endif /* LINUX_PCI_H */
> > > > > --
> > > > > 1.9.1
> > > > >
> > > > > --
> > > > > To unsubscribe from this list: send the line "unsubscribe linux-
> > pci"
> > > > in
> > > > > the body of a message to majordomo@vger.kernel.org
> > > > > More majordomo info at  http://vger.kernel.org/majordomo-
> > info.html
> > 
> > --
> > ====================
> > | I would like to |
> > | fix the world,  |
> > | but they're not |
> > | giving me the   |
> >  \ source code!  /
> >   ---------------
> >     ¯\_(ツ)_/¯

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

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

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-11 10:37             ` liviu.dudau
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau at arm.com @ 2016-11-11 10:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Nov 10, 2016 at 04:06:40PM +0000, Gabriele Paoloni wrote:
> Hi Liviu
> 
> > -----Original Message-----
> > From: liviu.dudau at arm.com [mailto:liviu.dudau at arm.com]
> > Sent: 09 November 2016 16:51
> > To: Gabriele Paoloni
> > Cc: Yuanzhichang; catalin.marinas at arm.com; will.deacon at arm.com;
> > robh+dt at kernel.org; bhelgaas at google.com; mark.rutland at arm.com;
> > olof at lixom.net; arnd at arndb.de; linux-arm-kernel at lists.infradead.org;
> > lorenzo.pieralisi at arm.com; linux-kernel at vger.kernel.org; Linuxarm;
> > devicetree at vger.kernel.org; linux-pci at vger.kernel.org; linux-
> > serial at vger.kernel.org; minyard at acm.org; benh at kernel.crashing.org;
> > zourongrong at gmail.com; John Garry; zhichang.yuan02 at gmail.com;
> > kantyzc at 163.com; xuwei (O)
> > Subject: Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for
> > special ISA
> > 
> > On Wed, Nov 09, 2016 at 04:16:17PM +0000, Gabriele Paoloni wrote:
> > > Hi Liviu
> > >
> > > Thanks for reviewing
> > >
> > 
> > [removed some irrelevant part of discussion, avoid crazy formatting]
> > 
> > > > > +/**
> > > > > + * addr_is_indirect_io - check whether the input taddr is for
> > > > indirectIO.
> > > > > + * @taddr: the io address to be checked.
> > > > > + *
> > > > > + * Returns 1 when taddr is in the range; otherwise return 0.
> > > > > + */
> > > > > +int addr_is_indirect_io(u64 taddr)
> > > > > +{
> > > > > +	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end
> > <
> > > > taddr)
> > > >
> > > > start >= taddr ?
> > >
> > > Nope... if  (taddr < arm64_extio_ops->start || taddr >
> > arm64_extio_ops->end)
> > > then taddr is outside the range [start; end] and will return 0;
> > otherwise
> > > it will return 1...
> > 
> > Oops, sorry, did not pay attention to the returned value. The check is
> > correct as it is, no need to change then.
> > 
> > >
> > > >
> > > > > +		return 0;
> > > > > +
> > > > > +	return 1;
> > > > > +}
> > > > >
> > > > >  BUILD_EXTIO(b, u8)
> > > > >
> > > > > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > > > > index 02b2903..cc2a05d 100644
> > > > > --- a/drivers/of/address.c
> > > > > +++ b/drivers/of/address.c
> > > > > @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct
> > > > device_node *np)
> > > > >  	return false;
> > > > >  }
> > > > >
> > > > > +
> > > > > +/*
> > > > > + * of_isa_indirect_io - get the IO address from some isa reg
> > > > property value.
> > > > > + *	For some isa/lpc devices, no ranges property in ancestor
> > node.
> > > > > + *	The device addresses are described directly in their regs
> > > > property.
> > > > > + *	This fixup function will be called to get the IO address of
> > > > isa/lpc
> > > > > + *	devices when the normal of_translation failed.
> > > > > + *
> > > > > + * @parent:	points to the parent dts node;
> > > > > + * @bus:		points to the of_bus which can be used to parse
> > > > address;
> > > > > + * @addr:	the address from reg property;
> > > > > + * @na:		the address cell counter of @addr;
> > > > > + * @presult:	store the address paresed from @addr;
> > > > > + *
> > > > > + * return 1 when successfully get the I/O address;
> > > > > + * 0 will return for some failures.
> > > >
> > > > Bah, you are returning a signed int, why 0 for failure? Return a
> > > > negative value with
> > > > error codes. Otherwise change the return value into a bool.
> > >
> > > Yes we'll move to bool
> > >
> > > >
> > > > > + */
> > > > > +static int of_get_isa_indirect_io(struct device_node *parent,
> > > > > +				struct of_bus *bus, __be32 *addr,
> > > > > +				int na, u64 *presult)
> > > > > +{
> > > > > +	unsigned int flags;
> > > > > +	unsigned int rlen;
> > > > > +
> > > > > +	/* whether support indirectIO */
> > > > > +	if (!indirect_io_enabled())
> > > > > +		return 0;
> > > > > +
> > > > > +	if (!of_bus_isa_match(parent))
> > > > > +		return 0;
> > > > > +
> > > > > +	flags = bus->get_flags(addr);
> > > > > +	if (!(flags & IORESOURCE_IO))
> > > > > +		return 0;
> > > > > +
> > > > > +	/* there is ranges property, apply the normal translation
> > > > directly. */
> > > >
> > > > s/there is ranges/if we have a 'ranges'/
> > >
> > > Thanks for spotting this
> > >
> > > >
> > > > > +	if (of_get_property(parent, "ranges", &rlen))
> > > > > +		return 0;
> > > > > +
> > > > > +	*presult = of_read_number(addr + 1, na - 1);
> > > > > +	/* this fixup is only valid for specific I/O range. */
> > > > > +	return addr_is_indirect_io(*presult);
> > > > > +}
> > > > > +
> > > > >  static int of_translate_one(struct device_node *parent, struct
> > > > of_bus *bus,
> > > > >  			    struct of_bus *pbus, __be32 *addr,
> > > > >  			    int na, int ns, int pna, const char *rprop)
> > > > > @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct
> > > > device_node *dev,
> > > > >  			result = of_read_number(addr, na);
> > > > >  			break;
> > > > >  		}
> > > > > +		/*
> > > > > +		 * For indirectIO device which has no ranges
> > property, get
> > > > > +		 * the address from reg directly.
> > > > > +		 */
> > > > > +		if (of_get_isa_indirect_io(dev, bus, addr, na,
> > &result)) {
> > > > > +			pr_debug("isa indirectIO matched(%s)..addr =
> > > > 0x%llx\n",
> > > > > +				of_node_full_name(dev), result);
> > > > > +			break;
> > > > > +		}
> > > > >
> > > > >  		/* Get new parent bus and counts */
> > > > >  		pbus = of_match_bus(parent);
> > > > > @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct
> > > > device_node *dev,
> > > > >  	if (taddr == OF_BAD_ADDR)
> > > > >  		return -EINVAL;
> > > > >  	memset(r, 0, sizeof(struct resource));
> > > > > -	if (flags & IORESOURCE_IO) {
> > > > > +	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
> > > > >  		unsigned long port;
> > > > > +
> > > > >  		port = pci_address_to_pio(taddr);
> > > > >  		if (port == (unsigned long)-1)
> > > > >  			return -EINVAL;
> > > > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > > > > index ba34907..1a08511 100644
> > > > > --- a/drivers/pci/pci.c
> > > > > +++ b/drivers/pci/pci.c
> > > > > @@ -3263,7 +3263,7 @@ 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;
> > > > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > > > >
> > > > >  	/* check if the range hasn't been previously recorded */
> > > > >  	spin_lock(&io_range_lock);
> > > > > @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned
> > long
> > > > pio)
> > > > >
> > > > >  #ifdef PCI_IOBASE
> > > > >  	struct io_range *range;
> > > > > -	resource_size_t allocated_size = 0;
> > > > > +	resource_size_t allocated_size = PCIBIOS_MIN_IO;
> > > >
> > > > Have you checked that pci_pio_to_address still returns valid values
> > > > after this? I know that
> > > > you are trying to take into account PCIBIOS_MIN_IO limit when
> > > > allocating reserving the IO ranges,
> > > > but the values added in the io_range_list are still starting from
> > zero,
> > > > no from PCIBIOS_MIN_IO,
> > >
> > > I think you're wrong here as in pci_address_to_pio we have:
> > > +	resource_size_t offset = PCIBIOS_MIN_IO;
> > >
> > > This should be enough to guarantee that the PIOs start at
> > > PCIBIOS_MIN_IO...right?
> > 
> > I don't think you can guarantee that the pio value that gets passed
> > into
> > pci_pio_to_address() always comes from a previously returned value by
> > pci_address_to_pio(). Maybe you can add a check in pci_pio_to_address()
> 
> Maybe I am missing something...could you make an exampleof a case
> where an IO toke doesn?t come from pci_address_to_pio() ?

Don't know, maybe it is coming from some DT or platform data? I was just
asking for confirmation that no one has seen issues there, I'm not saying
I've seen it happening.

Best regards,
Liviu

> 
> Thanks
> 
> Gab
> 
> 
> > 
> > 	if (pio < PCIBIOS_MIN_IO)
> > 		return address;
> > 
> > to avoid adding more checks in the list_for_each_entry() loop.
> > 
> > Best regards,
> > Liviu
> > 
> > >
> > >
> > > > so the calculation of the address in this function could return
> > > > negative values casted to pci_addr_t.
> > > >
> > > > Maybe you want to adjust the range->start value in
> > > > pci_register_io_range() as well to have it
> > > > offset by PCIBIOS_MIN_IO as well.
> > > >
> > > > Best regards,
> > > > Liviu
> > > >
> > > > >
> > > > >  	if (pio > IO_SPACE_LIMIT)
> > > > >  		return address;
> > > > > @@ -3335,7 +3335,7 @@ unsigned long __weak
> > > > pci_address_to_pio(phys_addr_t address)
> > > > >  {
> > > > >  #ifdef PCI_IOBASE
> > > > >  	struct io_range *res;
> > > > > -	resource_size_t offset = 0;
> > > > > +	resource_size_t offset = PCIBIOS_MIN_IO;
> > > > >  	unsigned long addr = -1;
> > > > >
> > > > >  	spin_lock(&io_range_lock);
> > > > > diff --git a/include/linux/of_address.h
> > b/include/linux/of_address.h
> > > > > index 3786473..deec469 100644
> > > > > --- a/include/linux/of_address.h
> > > > > +++ b/include/linux/of_address.h
> > > > > @@ -24,6 +24,23 @@ struct of_pci_range {
> > > > >  #define for_each_of_pci_range(parser, range) \
> > > > >  	for (; of_pci_range_parser_one(parser, range);)
> > > > >
> > > > > +
> > > > > +#ifndef indirect_io_enabled
> > > > > +#define indirect_io_enabled indirect_io_enabled
> > > > > +static inline bool indirect_io_enabled(void)
> > > > > +{
> > > > > +	return false;
> > > > > +}
> > > > > +#endif
> > > > > +
> > > > > +#ifndef addr_is_indirect_io
> > > > > +#define addr_is_indirect_io addr_is_indirect_io
> > > > > +static inline int addr_is_indirect_io(u64 taddr)
> > > > > +{
> > > > > +	return 0;
> > > > > +}
> > > > > +#endif
> > > > > +
> > > > >  /* Translate a DMA address from device space to CPU space */
> > > > >  extern u64 of_translate_dma_address(struct device_node *dev,
> > > > >  				    const __be32 *in_addr);
> > > > > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > > > > index 0e49f70..7f6bbb6 100644
> > > > > --- a/include/linux/pci.h
> > > > > +++ b/include/linux/pci.h
> > > > > @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct
> > > > pci_bus *bus)
> > > > >  /* provide the legacy pci_dma_* API */
> > > > >  #include <linux/pci-dma-compat.h>
> > > > >
> > > > > +/*
> > > > > + * define this macro here to refrain from compilation error for
> > some
> > > > > + * platforms. Please keep this macro at the end of this header
> > file.
> > > > > + */
> > > > > +#ifndef PCIBIOS_MIN_IO
> > > > > +#define PCIBIOS_MIN_IO		0
> > > > > +#endif
> > > > > +
> > > > >  #endif /* LINUX_PCI_H */
> > > > > --
> > > > > 1.9.1
> > > > >
> > > > > --
> > > > > 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!  /
> >   ---------------
> >     ?\_(?)_/?

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

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-10 16:07                 ` Arnd Bergmann
  (?)
  (?)
@ 2016-11-11 10:48                   ` liviu.dudau
  -1 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau @ 2016-11-11 10:48 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Gabriele Paoloni, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, bhelgaas, zhichang.yuan02

Hi Arnd,

On Thu, Nov 10, 2016 at 05:07:21PM +0100, Arnd Bergmann wrote:
> On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
> > 
> > Where should we get the range from? For LPC we know that it is going
> > Work on anything that is not used by PCI I/O space, and this is 
> > why we use [0, PCIBIOS_MIN_IO]
> 
> It should be allocated the same way we allocate PCI config space
> segments. This is currently done with the io_range list in
> drivers/pci/pci.c, which isn't perfect but could be extended
> if necessary. Based on what others commented here, I'd rather
> make the differences between ISA/LPC and PCI I/O ranges smaller
> than larger.
> 
> > > Your current version has
> > > 
> > >         if (arm64_extio_ops->pfout)                             \
> > >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > >                        addr, value, sizeof(type));             \
> > > 
> > > Instead, just subtract the start of the range from the logical
> > > port number to transform it back into a bus-local port number:
> > 
> > These accessors do not operate on IO tokens:
> > 
> > If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> > addr is not going to be an I/O token; in fact patch 2/3 imposes that
> > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to PCIBIOS_MIN_IO
> > we have free physical addresses that the accessors can operate on.
> 
> Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
> the logical I/O tokens, the purpose of that macro is really meant
> for allocating PCI I/O port numbers within the address space of
> one bus.
> 
> Note that it's equally likely that whichever next platform needs
> non-mapped I/O access like this actually needs them for PCI I/O space,
> and that will use it on addresses registered to a PCI host bridge.
> 
> If we separate the two steps:
> 
> a) assign a range of logical I/O port numbers to a bus

Except that currently when we add ranges to io_range_list we don't have
a bus number yet, because the parsing happens before the host bridge
has been created. Maybe register_io_range() can take a bus number as an
argument, but I'm not sure how we are going to use that in pci_pio_to_address()
or pci_address_to_pio().

Best regards,
Liviu

> b) register a set of helpers for redirecting logical I/O
>    port to a helper function
> 
> then I think the code will get cleaner and more flexible.
> It should actually then be able to replace the powerpc
> specific implementation.
> 
> 	Arnd

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

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 10:48                   ` liviu.dudau
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau @ 2016-11-11 10:48 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Gabriele Paoloni, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt@kernel.org

Hi Arnd,

On Thu, Nov 10, 2016 at 05:07:21PM +0100, Arnd Bergmann wrote:
> On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
> > 
> > Where should we get the range from? For LPC we know that it is going
> > Work on anything that is not used by PCI I/O space, and this is 
> > why we use [0, PCIBIOS_MIN_IO]
> 
> It should be allocated the same way we allocate PCI config space
> segments. This is currently done with the io_range list in
> drivers/pci/pci.c, which isn't perfect but could be extended
> if necessary. Based on what others commented here, I'd rather
> make the differences between ISA/LPC and PCI I/O ranges smaller
> than larger.
> 
> > > Your current version has
> > > 
> > >         if (arm64_extio_ops->pfout)                             \
> > >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > >                        addr, value, sizeof(type));             \
> > > 
> > > Instead, just subtract the start of the range from the logical
> > > port number to transform it back into a bus-local port number:
> > 
> > These accessors do not operate on IO tokens:
> > 
> > If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> > addr is not going to be an I/O token; in fact patch 2/3 imposes that
> > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to PCIBIOS_MIN_IO
> > we have free physical addresses that the accessors can operate on.
> 
> Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
> the logical I/O tokens, the purpose of that macro is really meant
> for allocating PCI I/O port numbers within the address space of
> one bus.
> 
> Note that it's equally likely that whichever next platform needs
> non-mapped I/O access like this actually needs them for PCI I/O space,
> and that will use it on addresses registered to a PCI host bridge.
> 
> If we separate the two steps:
> 
> a) assign a range of logical I/O port numbers to a bus

Except that currently when we add ranges to io_range_list we don't have
a bus number yet, because the parsing happens before the host bridge
has been created. Maybe register_io_range() can take a bus number as an
argument, but I'm not sure how we are going to use that in pci_pio_to_address()
or pci_address_to_pio().

Best regards,
Liviu

> b) register a set of helpers for redirecting logical I/O
>    port to a helper function
> 
> then I think the code will get cleaner and more flexible.
> It should actually then be able to replace the powerpc
> specific implementation.
> 
> 	Arnd

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

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 10:48                   ` liviu.dudau
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau @ 2016-11-11 10:48 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Gabriele Paoloni, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, bhelgaas, zhichang.yuan02

Hi Arnd,

On Thu, Nov 10, 2016 at 05:07:21PM +0100, Arnd Bergmann wrote:
> On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
> > 
> > Where should we get the range from? For LPC we know that it is going
> > Work on anything that is not used by PCI I/O space, and this is 
> > why we use [0, PCIBIOS_MIN_IO]
> 
> It should be allocated the same way we allocate PCI config space
> segments. This is currently done with the io_range list in
> drivers/pci/pci.c, which isn't perfect but could be extended
> if necessary. Based on what others commented here, I'd rather
> make the differences between ISA/LPC and PCI I/O ranges smaller
> than larger.
> 
> > > Your current version has
> > > 
> > >         if (arm64_extio_ops->pfout)                             \
> > >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > >                        addr, value, sizeof(type));             \
> > > 
> > > Instead, just subtract the start of the range from the logical
> > > port number to transform it back into a bus-local port number:
> > 
> > These accessors do not operate on IO tokens:
> > 
> > If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> > addr is not going to be an I/O token; in fact patch 2/3 imposes that
> > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to PCIBIOS_MIN_IO
> > we have free physical addresses that the accessors can operate on.
> 
> Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
> the logical I/O tokens, the purpose of that macro is really meant
> for allocating PCI I/O port numbers within the address space of
> one bus.
> 
> Note that it's equally likely that whichever next platform needs
> non-mapped I/O access like this actually needs them for PCI I/O space,
> and that will use it on addresses registered to a PCI host bridge.
> 
> If we separate the two steps:
> 
> a) assign a range of logical I/O port numbers to a bus

Except that currently when we add ranges to io_range_list we don't have
a bus number yet, because the parsing happens before the host bridge
has been created. Maybe register_io_range() can take a bus number as an
argument, but I'm not sure how we are going to use that in pci_pio_to_address()
or pci_address_to_pio().

Best regards,
Liviu

> b) register a set of helpers for redirecting logical I/O
>    port to a helper function
> 
> then I think the code will get cleaner and more flexible.
> It should actually then be able to replace the powerpc
> specific implementation.
> 
> 	Arnd

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

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 10:48                   ` liviu.dudau
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau at arm.com @ 2016-11-11 10:48 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd,

On Thu, Nov 10, 2016 at 05:07:21PM +0100, Arnd Bergmann wrote:
> On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
> > 
> > Where should we get the range from? For LPC we know that it is going
> > Work on anything that is not used by PCI I/O space, and this is 
> > why we use [0, PCIBIOS_MIN_IO]
> 
> It should be allocated the same way we allocate PCI config space
> segments. This is currently done with the io_range list in
> drivers/pci/pci.c, which isn't perfect but could be extended
> if necessary. Based on what others commented here, I'd rather
> make the differences between ISA/LPC and PCI I/O ranges smaller
> than larger.
> 
> > > Your current version has
> > > 
> > >         if (arm64_extio_ops->pfout)                             \
> > >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > >                        addr, value, sizeof(type));             \
> > > 
> > > Instead, just subtract the start of the range from the logical
> > > port number to transform it back into a bus-local port number:
> > 
> > These accessors do not operate on IO tokens:
> > 
> > If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> > addr is not going to be an I/O token; in fact patch 2/3 imposes that
> > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to PCIBIOS_MIN_IO
> > we have free physical addresses that the accessors can operate on.
> 
> Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
> the logical I/O tokens, the purpose of that macro is really meant
> for allocating PCI I/O port numbers within the address space of
> one bus.
> 
> Note that it's equally likely that whichever next platform needs
> non-mapped I/O access like this actually needs them for PCI I/O space,
> and that will use it on addresses registered to a PCI host bridge.
> 
> If we separate the two steps:
> 
> a) assign a range of logical I/O port numbers to a bus

Except that currently when we add ranges to io_range_list we don't have
a bus number yet, because the parsing happens before the host bridge
has been created. Maybe register_io_range() can take a bus number as an
argument, but I'm not sure how we are going to use that in pci_pio_to_address()
or pci_address_to_pio().

Best regards,
Liviu

> b) register a set of helpers for redirecting logical I/O
>    port to a helper function
> 
> then I think the code will get cleaner and more flexible.
> It should actually then be able to replace the powerpc
> specific implementation.
> 
> 	Arnd

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

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-10 16:07                 ` Arnd Bergmann
  (?)
  (?)
@ 2016-11-11 13:39                   ` Gabriele Paoloni
  -1 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-11 13:39 UTC (permalink / raw)
  To: Arnd Bergmann, Gabriele Paoloni
  Cc: linux-arm-kernel, Yuanzhichang, mark.rutland, devicetree,
	lorenzo.pieralisi, minyard, linux-pci, benh, John Garry,
	will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, liviu.dudau, bhelgaas@googl e.com,
	zhichang.yuan02

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 10 November 2016 16:07
> To: Gabriele Paoloni
> Cc: linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> mark.rutland@arm.com; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> catalin.marinas@arm.com; olof@lixom.net; liviu.dudau@arm.com;
> bhelgaas@googl e.com; zhichang.yuan02@gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
> >
> > Where should we get the range from? For LPC we know that it is going
> > Work on anything that is not used by PCI I/O space, and this is
> > why we use [0, PCIBIOS_MIN_IO]
> 
> It should be allocated the same way we allocate PCI config space
> segments. This is currently done with the io_range list in
> drivers/pci/pci.c, which isn't perfect but could be extended
> if necessary. Based on what others commented here, I'd rather
> make the differences between ISA/LPC and PCI I/O ranges smaller
> than larger.

I am not sure this would make sense...

IMHO all the mechanism around io_range_list is needed to provide the
"mapping" between I/O tokens and physical CPU addresses.

Currently the available tokens range from 0 to IO_SPACE_LIMIT.

As you know the I/O memory accessors operate on whatever
__of_address_to_resource sets into the resource (start, end).

With this special device in place we cannot know if a resource is
assigned with an I/O token or a physical address, unless we forbid
the I/O tokens to be in a specific range.

So this is why we are changing the offsets of all the functions
handling io_range_list (to make sure that a range is forbidden to
the tokens and is available to the physical addresses).

We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
because this is the maximum physical I/O range that a non PCI device
can operate on and because we believe this does not impose much
restriction on the available I/O token range; that now is 
[PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
So we believe that the chosen forbidden range can accommodate
any special ISA bus device with no much constraint on the rest
of I/O tokens...

> 
> > > Your current version has
> > >
> > >         if (arm64_extio_ops->pfout)                             \
> > >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > >                        addr, value, sizeof(type));             \
> > >
> > > Instead, just subtract the start of the range from the logical
> > > port number to transform it back into a bus-local port number:
> >
> > These accessors do not operate on IO tokens:
> >
> > If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> > addr is not going to be an I/O token; in fact patch 2/3 imposes that
> > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> PCIBIOS_MIN_IO
> > we have free physical addresses that the accessors can operate on.
> 
> Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
> the logical I/O tokens, the purpose of that macro is really meant
> for allocating PCI I/O port numbers within the address space of
> one bus.

As I mentioned above, special devices operate on CPU addresses directly,
not I/O tokens. For them there is no way to distinguish....

> 
> Note that it's equally likely that whichever next platform needs
> non-mapped I/O access like this actually needs them for PCI I/O space,
> and that will use it on addresses registered to a PCI host bridge.

Ok so here you are talking about a platform that has got an I/O range
under the PCI host controller, right?
And this I/O range cannot be directly memory mapped but needs special
redirections for the I/O tokens, right?

In this scenario registering the I/O ranges with the forbidden range
implemented by the current patch would still allow to redirect I/O
tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO

So effectively the special PCI host controller
1) knows the physical range that needs special redirection
2) register such range
3) uses pci_pio_to_address() to retrieve the IO tokens for the
   special accessors
4) sets arm64_extio_ops->start/end to the IO tokens retrieved in 3)

So to be honest I think this patch can fit well both with
special PCI controllers that need I/O tokens redirection and with
special non-PCI controllers that need non-PCI I/O physical
address redirection...

Thanks (and sorry for the long reply but I didn't know how
to make the explanation shorter :) )

Gab

> 
> If we separate the two steps:
> 
> a) assign a range of logical I/O port numbers to a bus
> b) register a set of helpers for redirecting logical I/O
>    port to a helper function
> 
> then I think the code will get cleaner and more flexible.
> It should actually then be able to replace the powerpc
> specific implementation.
> 
> 	Arnd

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 13:39                   ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-11 13:39 UTC (permalink / raw)
  To: Arnd Bergmann, Gabriele Paoloni
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Yuanzhichang,
	mark.rutland-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA,
	lorenzo.pieralisi-5wv7dgnIgG8, minyard-HInyCGIudOg,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, John Garry,
	will.deacon-5wv7dgnIgG8, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	xuwei (O),
	Linuxarm, zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, kantyzc-9Onoh4P/yGk

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd-r2nGTMty4D4@public.gmane.org]
> Sent: 10 November 2016 16:07
> To: Gabriele Paoloni
> Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org; Yuanzhichang;
> mark.rutland-5wv7dgnIgG8@public.gmane.org; devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org; minyard-HInyCGIudOg@public.gmane.org; linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org; John Garry; will.deacon-5wv7dgnIgG8@public.gmane.org; linux-
> kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; xuwei (O); Linuxarm; zourongrong-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org;
> robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org; kantyzc-9Onoh4P/yGk@public.gmane.org; linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> catalin.marinas-5wv7dgnIgG8@public.gmane.org; olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org; liviu.dudau-5wv7dgnIgG8@public.gmane.org;
> bhelgaas@googl e.com; zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
> >
> > Where should we get the range from? For LPC we know that it is going
> > Work on anything that is not used by PCI I/O space, and this is
> > why we use [0, PCIBIOS_MIN_IO]
> 
> It should be allocated the same way we allocate PCI config space
> segments. This is currently done with the io_range list in
> drivers/pci/pci.c, which isn't perfect but could be extended
> if necessary. Based on what others commented here, I'd rather
> make the differences between ISA/LPC and PCI I/O ranges smaller
> than larger.

I am not sure this would make sense...

IMHO all the mechanism around io_range_list is needed to provide the
"mapping" between I/O tokens and physical CPU addresses.

Currently the available tokens range from 0 to IO_SPACE_LIMIT.

As you know the I/O memory accessors operate on whatever
__of_address_to_resource sets into the resource (start, end).

With this special device in place we cannot know if a resource is
assigned with an I/O token or a physical address, unless we forbid
the I/O tokens to be in a specific range.

So this is why we are changing the offsets of all the functions
handling io_range_list (to make sure that a range is forbidden to
the tokens and is available to the physical addresses).

We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
because this is the maximum physical I/O range that a non PCI device
can operate on and because we believe this does not impose much
restriction on the available I/O token range; that now is 
[PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
So we believe that the chosen forbidden range can accommodate
any special ISA bus device with no much constraint on the rest
of I/O tokens...

> 
> > > Your current version has
> > >
> > >         if (arm64_extio_ops->pfout)                             \
> > >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > >                        addr, value, sizeof(type));             \
> > >
> > > Instead, just subtract the start of the range from the logical
> > > port number to transform it back into a bus-local port number:
> >
> > These accessors do not operate on IO tokens:
> >
> > If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> > addr is not going to be an I/O token; in fact patch 2/3 imposes that
> > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> PCIBIOS_MIN_IO
> > we have free physical addresses that the accessors can operate on.
> 
> Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
> the logical I/O tokens, the purpose of that macro is really meant
> for allocating PCI I/O port numbers within the address space of
> one bus.

As I mentioned above, special devices operate on CPU addresses directly,
not I/O tokens. For them there is no way to distinguish....

> 
> Note that it's equally likely that whichever next platform needs
> non-mapped I/O access like this actually needs them for PCI I/O space,
> and that will use it on addresses registered to a PCI host bridge.

Ok so here you are talking about a platform that has got an I/O range
under the PCI host controller, right?
And this I/O range cannot be directly memory mapped but needs special
redirections for the I/O tokens, right?

In this scenario registering the I/O ranges with the forbidden range
implemented by the current patch would still allow to redirect I/O
tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO

So effectively the special PCI host controller
1) knows the physical range that needs special redirection
2) register such range
3) uses pci_pio_to_address() to retrieve the IO tokens for the
   special accessors
4) sets arm64_extio_ops->start/end to the IO tokens retrieved in 3)

So to be honest I think this patch can fit well both with
special PCI controllers that need I/O tokens redirection and with
special non-PCI controllers that need non-PCI I/O physical
address redirection...

Thanks (and sorry for the long reply but I didn't know how
to make the explanation shorter :) )

Gab

> 
> If we separate the two steps:
> 
> a) assign a range of logical I/O port numbers to a bus
> b) register a set of helpers for redirecting logical I/O
>    port to a helper function
> 
> then I think the code will get cleaner and more flexible.
> It should actually then be able to replace the powerpc
> specific implementation.
> 
> 	Arnd
--
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] 286+ messages in thread

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 13:39                   ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-11 13:39 UTC (permalink / raw)
  To: Arnd Bergmann, Gabriele Paoloni
  Cc: linux-arm-kernel, Yuanzhichang, mark.rutland, devicetree,
	lorenzo.pieralisi, minyard, linux-pci, benh, John Garry,
	will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, liviu.dudau, bhelgaas@googl e.com,
	zhichang.yuan02

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 10 November 2016 16:07
> To: Gabriele Paoloni
> Cc: linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> mark.rutland@arm.com; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> catalin.marinas@arm.com; olof@lixom.net; liviu.dudau@arm.com;
> bhelgaas@googl e.com; zhichang.yuan02@gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
> >
> > Where should we get the range from? For LPC we know that it is going
> > Work on anything that is not used by PCI I/O space, and this is
> > why we use [0, PCIBIOS_MIN_IO]
> 
> It should be allocated the same way we allocate PCI config space
> segments. This is currently done with the io_range list in
> drivers/pci/pci.c, which isn't perfect but could be extended
> if necessary. Based on what others commented here, I'd rather
> make the differences between ISA/LPC and PCI I/O ranges smaller
> than larger.

I am not sure this would make sense...

IMHO all the mechanism around io_range_list is needed to provide the
"mapping" between I/O tokens and physical CPU addresses.

Currently the available tokens range from 0 to IO_SPACE_LIMIT.

As you know the I/O memory accessors operate on whatever
__of_address_to_resource sets into the resource (start, end).

With this special device in place we cannot know if a resource is
assigned with an I/O token or a physical address, unless we forbid
the I/O tokens to be in a specific range.

So this is why we are changing the offsets of all the functions
handling io_range_list (to make sure that a range is forbidden to
the tokens and is available to the physical addresses).

We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
because this is the maximum physical I/O range that a non PCI device
can operate on and because we believe this does not impose much
restriction on the available I/O token range; that now is 
[PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
So we believe that the chosen forbidden range can accommodate
any special ISA bus device with no much constraint on the rest
of I/O tokens...

> 
> > > Your current version has
> > >
> > >         if (arm64_extio_ops->pfout)                             \
> > >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > >                        addr, value, sizeof(type));             \
> > >
> > > Instead, just subtract the start of the range from the logical
> > > port number to transform it back into a bus-local port number:
> >
> > These accessors do not operate on IO tokens:
> >
> > If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> > addr is not going to be an I/O token; in fact patch 2/3 imposes that
> > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> PCIBIOS_MIN_IO
> > we have free physical addresses that the accessors can operate on.
> 
> Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
> the logical I/O tokens, the purpose of that macro is really meant
> for allocating PCI I/O port numbers within the address space of
> one bus.

As I mentioned above, special devices operate on CPU addresses directly,
not I/O tokens. For them there is no way to distinguish....

> 
> Note that it's equally likely that whichever next platform needs
> non-mapped I/O access like this actually needs them for PCI I/O space,
> and that will use it on addresses registered to a PCI host bridge.

Ok so here you are talking about a platform that has got an I/O range
under the PCI host controller, right?
And this I/O range cannot be directly memory mapped but needs special
redirections for the I/O tokens, right?

In this scenario registering the I/O ranges with the forbidden range
implemented by the current patch would still allow to redirect I/O
tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO

So effectively the special PCI host controller
1) knows the physical range that needs special redirection
2) register such range
3) uses pci_pio_to_address() to retrieve the IO tokens for the
   special accessors
4) sets arm64_extio_ops->start/end to the IO tokens retrieved in 3)

So to be honest I think this patch can fit well both with
special PCI controllers that need I/O tokens redirection and with
special non-PCI controllers that need non-PCI I/O physical
address redirection...

Thanks (and sorry for the long reply but I didn't know how
to make the explanation shorter :) )

Gab

> 
> If we separate the two steps:
> 
> a) assign a range of logical I/O port numbers to a bus
> b) register a set of helpers for redirecting logical I/O
>    port to a helper function
> 
> then I think the code will get cleaner and more flexible.
> It should actually then be able to replace the powerpc
> specific implementation.
> 
> 	Arnd

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 13:39                   ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-11 13:39 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 10 November 2016 16:07
> To: Gabriele Paoloni
> Cc: linux-arm-kernel at lists.infradead.org; Yuanzhichang;
> mark.rutland at arm.com; devicetree at vger.kernel.org;
> lorenzo.pieralisi at arm.com; minyard at acm.org; linux-pci at vger.kernel.org;
> benh at kernel.crashing.org; John Garry; will.deacon at arm.com; linux-
> kernel at vger.kernel.org; xuwei (O); Linuxarm; zourongrong at gmail.com;
> robh+dt at kernel.org; kantyzc at 163.com; linux-serial at vger.kernel.org;
> catalin.marinas at arm.com; olof at lixom.net; liviu.dudau at arm.com;
> bhelgaas at googl e.com; zhichang.yuan02 at gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
> >
> > Where should we get the range from? For LPC we know that it is going
> > Work on anything that is not used by PCI I/O space, and this is
> > why we use [0, PCIBIOS_MIN_IO]
> 
> It should be allocated the same way we allocate PCI config space
> segments. This is currently done with the io_range list in
> drivers/pci/pci.c, which isn't perfect but could be extended
> if necessary. Based on what others commented here, I'd rather
> make the differences between ISA/LPC and PCI I/O ranges smaller
> than larger.

I am not sure this would make sense...

IMHO all the mechanism around io_range_list is needed to provide the
"mapping" between I/O tokens and physical CPU addresses.

Currently the available tokens range from 0 to IO_SPACE_LIMIT.

As you know the I/O memory accessors operate on whatever
__of_address_to_resource sets into the resource (start, end).

With this special device in place we cannot know if a resource is
assigned with an I/O token or a physical address, unless we forbid
the I/O tokens to be in a specific range.

So this is why we are changing the offsets of all the functions
handling io_range_list (to make sure that a range is forbidden to
the tokens and is available to the physical addresses).

We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
because this is the maximum physical I/O range that a non PCI device
can operate on and because we believe this does not impose much
restriction on the available I/O token range; that now is 
[PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
So we believe that the chosen forbidden range can accommodate
any special ISA bus device with no much constraint on the rest
of I/O tokens...

> 
> > > Your current version has
> > >
> > >         if (arm64_extio_ops->pfout)                             \
> > >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > >                        addr, value, sizeof(type));             \
> > >
> > > Instead, just subtract the start of the range from the logical
> > > port number to transform it back into a bus-local port number:
> >
> > These accessors do not operate on IO tokens:
> >
> > If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> > addr is not going to be an I/O token; in fact patch 2/3 imposes that
> > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> PCIBIOS_MIN_IO
> > we have free physical addresses that the accessors can operate on.
> 
> Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
> the logical I/O tokens, the purpose of that macro is really meant
> for allocating PCI I/O port numbers within the address space of
> one bus.

As I mentioned above, special devices operate on CPU addresses directly,
not I/O tokens. For them there is no way to distinguish....

> 
> Note that it's equally likely that whichever next platform needs
> non-mapped I/O access like this actually needs them for PCI I/O space,
> and that will use it on addresses registered to a PCI host bridge.

Ok so here you are talking about a platform that has got an I/O range
under the PCI host controller, right?
And this I/O range cannot be directly memory mapped but needs special
redirections for the I/O tokens, right?

In this scenario registering the I/O ranges with the forbidden range
implemented by the current patch would still allow to redirect I/O
tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO

So effectively the special PCI host controller
1) knows the physical range that needs special redirection
2) register such range
3) uses pci_pio_to_address() to retrieve the IO tokens for the
   special accessors
4) sets arm64_extio_ops->start/end to the IO tokens retrieved in 3)

So to be honest I think this patch can fit well both with
special PCI controllers that need I/O tokens redirection and with
special non-PCI controllers that need non-PCI I/O physical
address redirection...

Thanks (and sorry for the long reply but I didn't know how
to make the explanation shorter :) )

Gab

> 
> If we separate the two steps:
> 
> a) assign a range of logical I/O port numbers to a bus
> b) register a set of helpers for redirecting logical I/O
>    port to a helper function
> 
> then I think the code will get cleaner and more flexible.
> It should actually then be able to replace the powerpc
> specific implementation.
> 
> 	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-11 13:39                   ` Gabriele Paoloni
  (?)
  (?)
@ 2016-11-11 14:45                     ` liviu.dudau-5wv7dgnIgG8
  -1 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau @ 2016-11-11 14:45 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Arnd Bergmann, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, bhelgaas@googl e.com, zhichang.yuan02

On Fri, Nov 11, 2016 at 01:39:35PM +0000, Gabriele Paoloni wrote:
> Hi Arnd
> 
> > -----Original Message-----
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > Sent: 10 November 2016 16:07
> > To: Gabriele Paoloni
> > Cc: linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> > mark.rutland@arm.com; devicetree@vger.kernel.org;
> > lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> > benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> > kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> > robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> > catalin.marinas@arm.com; olof@lixom.net; liviu.dudau@arm.com;
> > bhelgaas@googl e.com; zhichang.yuan02@gmail.com
> > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> > Hip06
> > 
> > On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
> > >
> > > Where should we get the range from? For LPC we know that it is going
> > > Work on anything that is not used by PCI I/O space, and this is
> > > why we use [0, PCIBIOS_MIN_IO]
> > 
> > It should be allocated the same way we allocate PCI config space
> > segments. This is currently done with the io_range list in
> > drivers/pci/pci.c, which isn't perfect but could be extended
> > if necessary. Based on what others commented here, I'd rather
> > make the differences between ISA/LPC and PCI I/O ranges smaller
> > than larger.

Gabriele,

> 
> I am not sure this would make sense...
> 
> IMHO all the mechanism around io_range_list is needed to provide the
> "mapping" between I/O tokens and physical CPU addresses.
> 
> Currently the available tokens range from 0 to IO_SPACE_LIMIT.
> 
> As you know the I/O memory accessors operate on whatever
> __of_address_to_resource sets into the resource (start, end).
> 
> With this special device in place we cannot know if a resource is
> assigned with an I/O token or a physical address, unless we forbid
> the I/O tokens to be in a specific range.
> 
> So this is why we are changing the offsets of all the functions
> handling io_range_list (to make sure that a range is forbidden to
> the tokens and is available to the physical addresses).
> 
> We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
> because this is the maximum physical I/O range that a non PCI device
> can operate on and because we believe this does not impose much
> restriction on the available I/O token range; that now is 
> [PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
> So we believe that the chosen forbidden range can accommodate
> any special ISA bus device with no much constraint on the rest
> of I/O tokens...

Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and you
actually need another variable for "reserving" an area in the I/O space
that can be used for physical addresses rather than I/O tokens.

The one good example for using PCIBIOS_MIN_IO is when your platform/architecture
does not support legacy ISA operations *at all*. In that case someone
sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O range
so that it doesn't get used. With Zhichang's patch you now start forcing
those platforms to have a valid address below PCIBIOS_MIN_IO.

For the general case you also have to bear in mind that PCIBIOS_MIN_IO could
be zero. In that case, what is your "forbidden" range? [0, 0) ? So it makes
sense to add a new #define that should only be defined by those architectures/
platforms that want to reserve on top of PCIBIOS_MIN_IO another region
where I/O tokens can't be generated for.

Best regards,
Liviu

> 
> > 
> > > > Your current version has
> > > >
> > > >         if (arm64_extio_ops->pfout)                             \
> > > >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > > >                        addr, value, sizeof(type));             \
> > > >
> > > > Instead, just subtract the start of the range from the logical
> > > > port number to transform it back into a bus-local port number:
> > >
> > > These accessors do not operate on IO tokens:
> > >
> > > If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> > > addr is not going to be an I/O token; in fact patch 2/3 imposes that
> > > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> > PCIBIOS_MIN_IO
> > > we have free physical addresses that the accessors can operate on.
> > 
> > Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
> > the logical I/O tokens, the purpose of that macro is really meant
> > for allocating PCI I/O port numbers within the address space of
> > one bus.
> 
> As I mentioned above, special devices operate on CPU addresses directly,
> not I/O tokens. For them there is no way to distinguish....
> 
> > 
> > Note that it's equally likely that whichever next platform needs
> > non-mapped I/O access like this actually needs them for PCI I/O space,
> > and that will use it on addresses registered to a PCI host bridge.
> 
> Ok so here you are talking about a platform that has got an I/O range
> under the PCI host controller, right?
> And this I/O range cannot be directly memory mapped but needs special
> redirections for the I/O tokens, right?
> 
> In this scenario registering the I/O ranges with the forbidden range
> implemented by the current patch would still allow to redirect I/O
> tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
> 
> So effectively the special PCI host controller
> 1) knows the physical range that needs special redirection
> 2) register such range
> 3) uses pci_pio_to_address() to retrieve the IO tokens for the
>    special accessors
> 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in 3)
> 
> So to be honest I think this patch can fit well both with
> special PCI controllers that need I/O tokens redirection and with
> special non-PCI controllers that need non-PCI I/O physical
> address redirection...
> 
> Thanks (and sorry for the long reply but I didn't know how
> to make the explanation shorter :) )
> 
> Gab
> 
> > 
> > If we separate the two steps:
> > 
> > a) assign a range of logical I/O port numbers to a bus
> > b) register a set of helpers for redirecting logical I/O
> >    port to a helper function
> > 
> > then I think the code will get cleaner and more flexible.
> > It should actually then be able to replace the powerpc
> > specific implementation.
> > 
> > 	Arnd

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

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 14:45                     ` liviu.dudau-5wv7dgnIgG8
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau-5wv7dgnIgG8 @ 2016-11-11 14:45 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Arnd Bergmann, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Yuanzhichang, mark.rutland-5wv7dgnIgG8,
	devicetree-u79uwXL29TY76Z2rM5mHXA, lorenzo.pieralisi-5wv7dgnIgG8,
	minyard-HInyCGIudOg, linux-pci-u79uwXL29TY76Z2rM5mHXA,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, John Garry,
	will.deacon-5wv7dgnIgG8, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	xuwei (O),
	Linuxarm, zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A

On Fri, Nov 11, 2016 at 01:39:35PM +0000, Gabriele Paoloni wrote:
> Hi Arnd
> 
> > -----Original Message-----
> > From: Arnd Bergmann [mailto:arnd-r2nGTMty4D4@public.gmane.org]
> > Sent: 10 November 2016 16:07
> > To: Gabriele Paoloni
> > Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org; Yuanzhichang;
> > mark.rutland-5wv7dgnIgG8@public.gmane.org; devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> > lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org; minyard-HInyCGIudOg@public.gmane.org; linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> > benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org; John Garry; will.deacon-5wv7dgnIgG8@public.gmane.org; linux-
> > kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; xuwei (O); Linuxarm; zourongrong-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org;
> > robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org; kantyzc-9Onoh4P/yGk@public.gmane.org; linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> > catalin.marinas-5wv7dgnIgG8@public.gmane.org; olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org; liviu.dudau-5wv7dgnIgG8@public.gmane.org;
> > bhelgaas@googl e.com; zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
> > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> > Hip06
> > 
> > On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
> > >
> > > Where should we get the range from? For LPC we know that it is going
> > > Work on anything that is not used by PCI I/O space, and this is
> > > why we use [0, PCIBIOS_MIN_IO]
> > 
> > It should be allocated the same way we allocate PCI config space
> > segments. This is currently done with the io_range list in
> > drivers/pci/pci.c, which isn't perfect but could be extended
> > if necessary. Based on what others commented here, I'd rather
> > make the differences between ISA/LPC and PCI I/O ranges smaller
> > than larger.

Gabriele,

> 
> I am not sure this would make sense...
> 
> IMHO all the mechanism around io_range_list is needed to provide the
> "mapping" between I/O tokens and physical CPU addresses.
> 
> Currently the available tokens range from 0 to IO_SPACE_LIMIT.
> 
> As you know the I/O memory accessors operate on whatever
> __of_address_to_resource sets into the resource (start, end).
> 
> With this special device in place we cannot know if a resource is
> assigned with an I/O token or a physical address, unless we forbid
> the I/O tokens to be in a specific range.
> 
> So this is why we are changing the offsets of all the functions
> handling io_range_list (to make sure that a range is forbidden to
> the tokens and is available to the physical addresses).
> 
> We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
> because this is the maximum physical I/O range that a non PCI device
> can operate on and because we believe this does not impose much
> restriction on the available I/O token range; that now is 
> [PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
> So we believe that the chosen forbidden range can accommodate
> any special ISA bus device with no much constraint on the rest
> of I/O tokens...

Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and you
actually need another variable for "reserving" an area in the I/O space
that can be used for physical addresses rather than I/O tokens.

The one good example for using PCIBIOS_MIN_IO is when your platform/architecture
does not support legacy ISA operations *at all*. In that case someone
sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O range
so that it doesn't get used. With Zhichang's patch you now start forcing
those platforms to have a valid address below PCIBIOS_MIN_IO.

For the general case you also have to bear in mind that PCIBIOS_MIN_IO could
be zero. In that case, what is your "forbidden" range? [0, 0) ? So it makes
sense to add a new #define that should only be defined by those architectures/
platforms that want to reserve on top of PCIBIOS_MIN_IO another region
where I/O tokens can't be generated for.

Best regards,
Liviu

> 
> > 
> > > > Your current version has
> > > >
> > > >         if (arm64_extio_ops->pfout)                             \
> > > >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > > >                        addr, value, sizeof(type));             \
> > > >
> > > > Instead, just subtract the start of the range from the logical
> > > > port number to transform it back into a bus-local port number:
> > >
> > > These accessors do not operate on IO tokens:
> > >
> > > If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> > > addr is not going to be an I/O token; in fact patch 2/3 imposes that
> > > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> > PCIBIOS_MIN_IO
> > > we have free physical addresses that the accessors can operate on.
> > 
> > Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
> > the logical I/O tokens, the purpose of that macro is really meant
> > for allocating PCI I/O port numbers within the address space of
> > one bus.
> 
> As I mentioned above, special devices operate on CPU addresses directly,
> not I/O tokens. For them there is no way to distinguish....
> 
> > 
> > Note that it's equally likely that whichever next platform needs
> > non-mapped I/O access like this actually needs them for PCI I/O space,
> > and that will use it on addresses registered to a PCI host bridge.
> 
> Ok so here you are talking about a platform that has got an I/O range
> under the PCI host controller, right?
> And this I/O range cannot be directly memory mapped but needs special
> redirections for the I/O tokens, right?
> 
> In this scenario registering the I/O ranges with the forbidden range
> implemented by the current patch would still allow to redirect I/O
> tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
> 
> So effectively the special PCI host controller
> 1) knows the physical range that needs special redirection
> 2) register such range
> 3) uses pci_pio_to_address() to retrieve the IO tokens for the
>    special accessors
> 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in 3)
> 
> So to be honest I think this patch can fit well both with
> special PCI controllers that need I/O tokens redirection and with
> special non-PCI controllers that need non-PCI I/O physical
> address redirection...
> 
> Thanks (and sorry for the long reply but I didn't know how
> to make the explanation shorter :) )
> 
> Gab
> 
> > 
> > If we separate the two steps:
> > 
> > a) assign a range of logical I/O port numbers to a bus
> > b) register a set of helpers for redirecting logical I/O
> >    port to a helper function
> > 
> > then I think the code will get cleaner and more flexible.
> > It should actually then be able to replace the powerpc
> > specific implementation.
> > 
> > 	Arnd

-- 
====================
| 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] 286+ messages in thread

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 14:45                     ` liviu.dudau-5wv7dgnIgG8
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau @ 2016-11-11 14:45 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Arnd Bergmann, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, bhelgaas@googl e.com, zhichang.yuan02

On Fri, Nov 11, 2016 at 01:39:35PM +0000, Gabriele Paoloni wrote:
> Hi Arnd
> 
> > -----Original Message-----
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > Sent: 10 November 2016 16:07
> > To: Gabriele Paoloni
> > Cc: linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> > mark.rutland@arm.com; devicetree@vger.kernel.org;
> > lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> > benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> > kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> > robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> > catalin.marinas@arm.com; olof@lixom.net; liviu.dudau@arm.com;
> > bhelgaas@googl e.com; zhichang.yuan02@gmail.com
> > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> > Hip06
> > 
> > On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
> > >
> > > Where should we get the range from? For LPC we know that it is going
> > > Work on anything that is not used by PCI I/O space, and this is
> > > why we use [0, PCIBIOS_MIN_IO]
> > 
> > It should be allocated the same way we allocate PCI config space
> > segments. This is currently done with the io_range list in
> > drivers/pci/pci.c, which isn't perfect but could be extended
> > if necessary. Based on what others commented here, I'd rather
> > make the differences between ISA/LPC and PCI I/O ranges smaller
> > than larger.

Gabriele,

> 
> I am not sure this would make sense...
> 
> IMHO all the mechanism around io_range_list is needed to provide the
> "mapping" between I/O tokens and physical CPU addresses.
> 
> Currently the available tokens range from 0 to IO_SPACE_LIMIT.
> 
> As you know the I/O memory accessors operate on whatever
> __of_address_to_resource sets into the resource (start, end).
> 
> With this special device in place we cannot know if a resource is
> assigned with an I/O token or a physical address, unless we forbid
> the I/O tokens to be in a specific range.
> 
> So this is why we are changing the offsets of all the functions
> handling io_range_list (to make sure that a range is forbidden to
> the tokens and is available to the physical addresses).
> 
> We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
> because this is the maximum physical I/O range that a non PCI device
> can operate on and because we believe this does not impose much
> restriction on the available I/O token range; that now is 
> [PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
> So we believe that the chosen forbidden range can accommodate
> any special ISA bus device with no much constraint on the rest
> of I/O tokens...

Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and you
actually need another variable for "reserving" an area in the I/O space
that can be used for physical addresses rather than I/O tokens.

The one good example for using PCIBIOS_MIN_IO is when your platform/architecture
does not support legacy ISA operations *at all*. In that case someone
sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O range
so that it doesn't get used. With Zhichang's patch you now start forcing
those platforms to have a valid address below PCIBIOS_MIN_IO.

For the general case you also have to bear in mind that PCIBIOS_MIN_IO could
be zero. In that case, what is your "forbidden" range? [0, 0) ? So it makes
sense to add a new #define that should only be defined by those architectures/
platforms that want to reserve on top of PCIBIOS_MIN_IO another region
where I/O tokens can't be generated for.

Best regards,
Liviu

> 
> > 
> > > > Your current version has
> > > >
> > > >         if (arm64_extio_ops->pfout)                             \
> > > >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > > >                        addr, value, sizeof(type));             \
> > > >
> > > > Instead, just subtract the start of the range from the logical
> > > > port number to transform it back into a bus-local port number:
> > >
> > > These accessors do not operate on IO tokens:
> > >
> > > If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> > > addr is not going to be an I/O token; in fact patch 2/3 imposes that
> > > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> > PCIBIOS_MIN_IO
> > > we have free physical addresses that the accessors can operate on.
> > 
> > Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
> > the logical I/O tokens, the purpose of that macro is really meant
> > for allocating PCI I/O port numbers within the address space of
> > one bus.
> 
> As I mentioned above, special devices operate on CPU addresses directly,
> not I/O tokens. For them there is no way to distinguish....
> 
> > 
> > Note that it's equally likely that whichever next platform needs
> > non-mapped I/O access like this actually needs them for PCI I/O space,
> > and that will use it on addresses registered to a PCI host bridge.
> 
> Ok so here you are talking about a platform that has got an I/O range
> under the PCI host controller, right?
> And this I/O range cannot be directly memory mapped but needs special
> redirections for the I/O tokens, right?
> 
> In this scenario registering the I/O ranges with the forbidden range
> implemented by the current patch would still allow to redirect I/O
> tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
> 
> So effectively the special PCI host controller
> 1) knows the physical range that needs special redirection
> 2) register such range
> 3) uses pci_pio_to_address() to retrieve the IO tokens for the
>    special accessors
> 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in 3)
> 
> So to be honest I think this patch can fit well both with
> special PCI controllers that need I/O tokens redirection and with
> special non-PCI controllers that need non-PCI I/O physical
> address redirection...
> 
> Thanks (and sorry for the long reply but I didn't know how
> to make the explanation shorter :) )
> 
> Gab
> 
> > 
> > If we separate the two steps:
> > 
> > a) assign a range of logical I/O port numbers to a bus
> > b) register a set of helpers for redirecting logical I/O
> >    port to a helper function
> > 
> > then I think the code will get cleaner and more flexible.
> > It should actually then be able to replace the powerpc
> > specific implementation.
> > 
> > 	Arnd

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

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 14:45                     ` liviu.dudau-5wv7dgnIgG8
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau at arm.com @ 2016-11-11 14:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Nov 11, 2016 at 01:39:35PM +0000, Gabriele Paoloni wrote:
> Hi Arnd
> 
> > -----Original Message-----
> > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > Sent: 10 November 2016 16:07
> > To: Gabriele Paoloni
> > Cc: linux-arm-kernel at lists.infradead.org; Yuanzhichang;
> > mark.rutland at arm.com; devicetree at vger.kernel.org;
> > lorenzo.pieralisi at arm.com; minyard at acm.org; linux-pci at vger.kernel.org;
> > benh at kernel.crashing.org; John Garry; will.deacon at arm.com; linux-
> > kernel at vger.kernel.org; xuwei (O); Linuxarm; zourongrong at gmail.com;
> > robh+dt at kernel.org; kantyzc at 163.com; linux-serial at vger.kernel.org;
> > catalin.marinas at arm.com; olof at lixom.net; liviu.dudau at arm.com;
> > bhelgaas at googl e.com; zhichang.yuan02 at gmail.com
> > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> > Hip06
> > 
> > On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
> > >
> > > Where should we get the range from? For LPC we know that it is going
> > > Work on anything that is not used by PCI I/O space, and this is
> > > why we use [0, PCIBIOS_MIN_IO]
> > 
> > It should be allocated the same way we allocate PCI config space
> > segments. This is currently done with the io_range list in
> > drivers/pci/pci.c, which isn't perfect but could be extended
> > if necessary. Based on what others commented here, I'd rather
> > make the differences between ISA/LPC and PCI I/O ranges smaller
> > than larger.

Gabriele,

> 
> I am not sure this would make sense...
> 
> IMHO all the mechanism around io_range_list is needed to provide the
> "mapping" between I/O tokens and physical CPU addresses.
> 
> Currently the available tokens range from 0 to IO_SPACE_LIMIT.
> 
> As you know the I/O memory accessors operate on whatever
> __of_address_to_resource sets into the resource (start, end).
> 
> With this special device in place we cannot know if a resource is
> assigned with an I/O token or a physical address, unless we forbid
> the I/O tokens to be in a specific range.
> 
> So this is why we are changing the offsets of all the functions
> handling io_range_list (to make sure that a range is forbidden to
> the tokens and is available to the physical addresses).
> 
> We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
> because this is the maximum physical I/O range that a non PCI device
> can operate on and because we believe this does not impose much
> restriction on the available I/O token range; that now is 
> [PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
> So we believe that the chosen forbidden range can accommodate
> any special ISA bus device with no much constraint on the rest
> of I/O tokens...

Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and you
actually need another variable for "reserving" an area in the I/O space
that can be used for physical addresses rather than I/O tokens.

The one good example for using PCIBIOS_MIN_IO is when your platform/architecture
does not support legacy ISA operations *at all*. In that case someone
sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O range
so that it doesn't get used. With Zhichang's patch you now start forcing
those platforms to have a valid address below PCIBIOS_MIN_IO.

For the general case you also have to bear in mind that PCIBIOS_MIN_IO could
be zero. In that case, what is your "forbidden" range? [0, 0) ? So it makes
sense to add a new #define that should only be defined by those architectures/
platforms that want to reserve on top of PCIBIOS_MIN_IO another region
where I/O tokens can't be generated for.

Best regards,
Liviu

> 
> > 
> > > > Your current version has
> > > >
> > > >         if (arm64_extio_ops->pfout)                             \
> > > >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> > > >                        addr, value, sizeof(type));             \
> > > >
> > > > Instead, just subtract the start of the range from the logical
> > > > port number to transform it back into a bus-local port number:
> > >
> > > These accessors do not operate on IO tokens:
> > >
> > > If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> > > addr is not going to be an I/O token; in fact patch 2/3 imposes that
> > > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> > PCIBIOS_MIN_IO
> > > we have free physical addresses that the accessors can operate on.
> > 
> > Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
> > the logical I/O tokens, the purpose of that macro is really meant
> > for allocating PCI I/O port numbers within the address space of
> > one bus.
> 
> As I mentioned above, special devices operate on CPU addresses directly,
> not I/O tokens. For them there is no way to distinguish....
> 
> > 
> > Note that it's equally likely that whichever next platform needs
> > non-mapped I/O access like this actually needs them for PCI I/O space,
> > and that will use it on addresses registered to a PCI host bridge.
> 
> Ok so here you are talking about a platform that has got an I/O range
> under the PCI host controller, right?
> And this I/O range cannot be directly memory mapped but needs special
> redirections for the I/O tokens, right?
> 
> In this scenario registering the I/O ranges with the forbidden range
> implemented by the current patch would still allow to redirect I/O
> tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
> 
> So effectively the special PCI host controller
> 1) knows the physical range that needs special redirection
> 2) register such range
> 3) uses pci_pio_to_address() to retrieve the IO tokens for the
>    special accessors
> 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in 3)
> 
> So to be honest I think this patch can fit well both with
> special PCI controllers that need I/O tokens redirection and with
> special non-PCI controllers that need non-PCI I/O physical
> address redirection...
> 
> Thanks (and sorry for the long reply but I didn't know how
> to make the explanation shorter :) )
> 
> Gab
> 
> > 
> > If we separate the two steps:
> > 
> > a) assign a range of logical I/O port numbers to a bus
> > b) register a set of helpers for redirecting logical I/O
> >    port to a helper function
> > 
> > then I think the code will get cleaner and more flexible.
> > It should actually then be able to replace the powerpc
> > specific implementation.
> > 
> > 	Arnd

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

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-11 14:45                     ` liviu.dudau-5wv7dgnIgG8
  (?)
  (?)
@ 2016-11-11 15:53                       ` Gabriele Paoloni
  -1 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-11 15:53 UTC (permalink / raw)
  To: liviu.dudau
  Cc: Arnd Bergmann, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, bhelgaas@googl e.com, zhichang.yuan02

Hi Liviu

> -----Original Message-----
> From: liviu.dudau@arm.com [mailto:liviu.dudau@arm.com]
> Sent: 11 November 2016 14:46
> To: Gabriele Paoloni
> Cc: Arnd Bergmann; linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> mark.rutland@arm.com; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> catalin.marinas@arm.com; olof@lixom.net; bhelgaas@googl e.com;
> zhichang.yuan02@gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Fri, Nov 11, 2016 at 01:39:35PM +0000, Gabriele Paoloni wrote:
> > Hi Arnd
> >
> > > -----Original Message-----
> > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > Sent: 10 November 2016 16:07
> > > To: Gabriele Paoloni
> > > Cc: linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> > > mark.rutland@arm.com; devicetree@vger.kernel.org;
> > > lorenzo.pieralisi@arm.com; minyard@acm.org; linux-
> pci@vger.kernel.org;
> > > benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> > > kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> > > robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> > > catalin.marinas@arm.com; olof@lixom.net; liviu.dudau@arm.com;
> > > bhelgaas@googl e.com; zhichang.yuan02@gmail.com
> > > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> > > Hip06
> > >
> > > On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni
> wrote:
> > > >
> > > > Where should we get the range from? For LPC we know that it is
> going
> > > > Work on anything that is not used by PCI I/O space, and this is
> > > > why we use [0, PCIBIOS_MIN_IO]
> > >
> > > It should be allocated the same way we allocate PCI config space
> > > segments. This is currently done with the io_range list in
> > > drivers/pci/pci.c, which isn't perfect but could be extended
> > > if necessary. Based on what others commented here, I'd rather
> > > make the differences between ISA/LPC and PCI I/O ranges smaller
> > > than larger.
> 
> Gabriele,
> 
> >
> > I am not sure this would make sense...
> >
> > IMHO all the mechanism around io_range_list is needed to provide the
> > "mapping" between I/O tokens and physical CPU addresses.
> >
> > Currently the available tokens range from 0 to IO_SPACE_LIMIT.
> >
> > As you know the I/O memory accessors operate on whatever
> > __of_address_to_resource sets into the resource (start, end).
> >
> > With this special device in place we cannot know if a resource is
> > assigned with an I/O token or a physical address, unless we forbid
> > the I/O tokens to be in a specific range.
> >
> > So this is why we are changing the offsets of all the functions
> > handling io_range_list (to make sure that a range is forbidden to
> > the tokens and is available to the physical addresses).
> >
> > We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
> > because this is the maximum physical I/O range that a non PCI device
> > can operate on and because we believe this does not impose much
> > restriction on the available I/O token range; that now is
> > [PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
> > So we believe that the chosen forbidden range can accommodate
> > any special ISA bus device with no much constraint on the rest
> > of I/O tokens...
> 
> Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and you
> actually need another variable for "reserving" an area in the I/O space
> that can be used for physical addresses rather than I/O tokens.
> 
> The one good example for using PCIBIOS_MIN_IO is when your
> platform/architecture
> does not support legacy ISA operations *at all*. In that case someone
> sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O range
> so that it doesn't get used. With Zhichang's patch you now start
> forcing
> those platforms to have a valid address below PCIBIOS_MIN_IO.

But if PCIBIOS_MIN_IO is 0 then it means that all I/O space is to be used
by PCI controllers only...so if you have a special bus device using
an I/O range in this case should be a PCI controller...i.e. I would
expect it to fall back into the case of I/O tokens redirection rather than
physical addresses redirection (as mentioned below from my previous reply).
What do you think?

Thanks

Gab


> 
> For the general case you also have to bear in mind that PCIBIOS_MIN_IO
> could
> be zero. In that case, what is your "forbidden" range? [0, 0) ? So it
> makes
> sense to add a new #define that should only be defined by those
> architectures/
> platforms that want to reserve on top of PCIBIOS_MIN_IO another region
> where I/O tokens can't be generated for.
> 
> Best regards,
> Liviu
> 
> >
> > >
> > > > > Your current version has
> > > > >
> > > > >         if (arm64_extio_ops->pfout)
> \
> > > > >                 arm64_extio_ops->pfout(arm64_extio_ops-
> >devpara,\
> > > > >                        addr, value, sizeof(type));
> \
> > > > >
> > > > > Instead, just subtract the start of the range from the logical
> > > > > port number to transform it back into a bus-local port number:
> > > >
> > > > These accessors do not operate on IO tokens:
> > > >
> > > > If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> > > > addr is not going to be an I/O token; in fact patch 2/3 imposes
> that
> > > > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> > > PCIBIOS_MIN_IO
> > > > we have free physical addresses that the accessors can operate
> on.
> > >
> > > Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer
> to
> > > the logical I/O tokens, the purpose of that macro is really meant
> > > for allocating PCI I/O port numbers within the address space of
> > > one bus.
> >
> > As I mentioned above, special devices operate on CPU addresses
> directly,
> > not I/O tokens. For them there is no way to distinguish....
> >
> > >
> > > Note that it's equally likely that whichever next platform needs
> > > non-mapped I/O access like this actually needs them for PCI I/O
> space,
> > > and that will use it on addresses registered to a PCI host bridge.
> >
> > Ok so here you are talking about a platform that has got an I/O range
> > under the PCI host controller, right?
> > And this I/O range cannot be directly memory mapped but needs special
> > redirections for the I/O tokens, right?
> >
> > In this scenario registering the I/O ranges with the forbidden range
> > implemented by the current patch would still allow to redirect I/O
> > tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
> >
> > So effectively the special PCI host controller
> > 1) knows the physical range that needs special redirection
> > 2) register such range
> > 3) uses pci_pio_to_address() to retrieve the IO tokens for the
> >    special accessors
> > 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in 3)
> >
> > So to be honest I think this patch can fit well both with
> > special PCI controllers that need I/O tokens redirection and with
> > special non-PCI controllers that need non-PCI I/O physical
> > address redirection...
> >
> > Thanks (and sorry for the long reply but I didn't know how
> > to make the explanation shorter :) )
> >
> > Gab
> >
> > >
> > > If we separate the two steps:
> > >
> > > a) assign a range of logical I/O port numbers to a bus
> > > b) register a set of helpers for redirecting logical I/O
> > >    port to a helper function
> > >
> > > then I think the code will get cleaner and more flexible.
> > > It should actually then be able to replace the powerpc
> > > specific implementation.
> > >
> > > 	Arnd
> 
> --
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ¯\_(ツ)_/¯

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 15:53                       ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-11 15:53 UTC (permalink / raw)
  To: liviu.dudau
  Cc: Arnd Bergmann, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt

Hi Liviu

> -----Original Message-----
> From: liviu.dudau@arm.com [mailto:liviu.dudau@arm.com]
> Sent: 11 November 2016 14:46
> To: Gabriele Paoloni
> Cc: Arnd Bergmann; linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> mark.rutland@arm.com; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> catalin.marinas@arm.com; olof@lixom.net; bhelgaas@googl e.com;
> zhichang.yuan02@gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Fri, Nov 11, 2016 at 01:39:35PM +0000, Gabriele Paoloni wrote:
> > Hi Arnd
> >
> > > -----Original Message-----
> > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > Sent: 10 November 2016 16:07
> > > To: Gabriele Paoloni
> > > Cc: linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> > > mark.rutland@arm.com; devicetree@vger.kernel.org;
> > > lorenzo.pieralisi@arm.com; minyard@acm.org; linux-
> pci@vger.kernel.org;
> > > benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> > > kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> > > robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> > > catalin.marinas@arm.com; olof@lixom.net; liviu.dudau@arm.com;
> > > bhelgaas@googl e.com; zhichang.yuan02@gmail.com
> > > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> > > Hip06
> > >
> > > On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni
> wrote:
> > > >
> > > > Where should we get the range from? For LPC we know that it is
> going
> > > > Work on anything that is not used by PCI I/O space, and this is
> > > > why we use [0, PCIBIOS_MIN_IO]
> > >
> > > It should be allocated the same way we allocate PCI config space
> > > segments. This is currently done with the io_range list in
> > > drivers/pci/pci.c, which isn't perfect but could be extended
> > > if necessary. Based on what others commented here, I'd rather
> > > make the differences between ISA/LPC and PCI I/O ranges smaller
> > > than larger.
> 
> Gabriele,
> 
> >
> > I am not sure this would make sense...
> >
> > IMHO all the mechanism around io_range_list is needed to provide the
> > "mapping" between I/O tokens and physical CPU addresses.
> >
> > Currently the available tokens range from 0 to IO_SPACE_LIMIT.
> >
> > As you know the I/O memory accessors operate on whatever
> > __of_address_to_resource sets into the resource (start, end).
> >
> > With this special device in place we cannot know if a resource is
> > assigned with an I/O token or a physical address, unless we forbid
> > the I/O tokens to be in a specific range.
> >
> > So this is why we are changing the offsets of all the functions
> > handling io_range_list (to make sure that a range is forbidden to
> > the tokens and is available to the physical addresses).
> >
> > We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
> > because this is the maximum physical I/O range that a non PCI device
> > can operate on and because we believe this does not impose much
> > restriction on the available I/O token range; that now is
> > [PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
> > So we believe that the chosen forbidden range can accommodate
> > any special ISA bus device with no much constraint on the rest
> > of I/O tokens...
> 
> Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and you
> actually need another variable for "reserving" an area in the I/O space
> that can be used for physical addresses rather than I/O tokens.
> 
> The one good example for using PCIBIOS_MIN_IO is when your
> platform/architecture
> does not support legacy ISA operations *at all*. In that case someone
> sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O range
> so that it doesn't get used. With Zhichang's patch you now start
> forcing
> those platforms to have a valid address below PCIBIOS_MIN_IO.

But if PCIBIOS_MIN_IO is 0 then it means that all I/O space is to be used
by PCI controllers only...so if you have a special bus device using
an I/O range in this case should be a PCI controller...i.e. I would
expect it to fall back into the case of I/O tokens redirection rather than
physical addresses redirection (as mentioned below from my previous reply).
What do you think?

Thanks

Gab


> 
> For the general case you also have to bear in mind that PCIBIOS_MIN_IO
> could
> be zero. In that case, what is your "forbidden" range? [0, 0) ? So it
> makes
> sense to add a new #define that should only be defined by those
> architectures/
> platforms that want to reserve on top of PCIBIOS_MIN_IO another region
> where I/O tokens can't be generated for.
> 
> Best regards,
> Liviu
> 
> >
> > >
> > > > > Your current version has
> > > > >
> > > > >         if (arm64_extio_ops->pfout)
> \
> > > > >                 arm64_extio_ops->pfout(arm64_extio_ops-
> >devpara,\
> > > > >                        addr, value, sizeof(type));
> \
> > > > >
> > > > > Instead, just subtract the start of the range from the logical
> > > > > port number to transform it back into a bus-local port number:
> > > >
> > > > These accessors do not operate on IO tokens:
> > > >
> > > > If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> > > > addr is not going to be an I/O token; in fact patch 2/3 imposes
> that
> > > > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> > > PCIBIOS_MIN_IO
> > > > we have free physical addresses that the accessors can operate
> on.
> > >
> > > Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer
> to
> > > the logical I/O tokens, the purpose of that macro is really meant
> > > for allocating PCI I/O port numbers within the address space of
> > > one bus.
> >
> > As I mentioned above, special devices operate on CPU addresses
> directly,
> > not I/O tokens. For them there is no way to distinguish....
> >
> > >
> > > Note that it's equally likely that whichever next platform needs
> > > non-mapped I/O access like this actually needs them for PCI I/O
> space,
> > > and that will use it on addresses registered to a PCI host bridge.
> >
> > Ok so here you are talking about a platform that has got an I/O range
> > under the PCI host controller, right?
> > And this I/O range cannot be directly memory mapped but needs special
> > redirections for the I/O tokens, right?
> >
> > In this scenario registering the I/O ranges with the forbidden range
> > implemented by the current patch would still allow to redirect I/O
> > tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
> >
> > So effectively the special PCI host controller
> > 1) knows the physical range that needs special redirection
> > 2) register such range
> > 3) uses pci_pio_to_address() to retrieve the IO tokens for the
> >    special accessors
> > 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in 3)
> >
> > So to be honest I think this patch can fit well both with
> > special PCI controllers that need I/O tokens redirection and with
> > special non-PCI controllers that need non-PCI I/O physical
> > address redirection...
> >
> > Thanks (and sorry for the long reply but I didn't know how
> > to make the explanation shorter :) )
> >
> > Gab
> >
> > >
> > > If we separate the two steps:
> > >
> > > a) assign a range of logical I/O port numbers to a bus
> > > b) register a set of helpers for redirecting logical I/O
> > >    port to a helper function
> > >
> > > then I think the code will get cleaner and more flexible.
> > > It should actually then be able to replace the powerpc
> > > specific implementation.
> > >
> > > 	Arnd
> 
> --
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ¯\_(ツ)_/¯

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 15:53                       ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-11 15:53 UTC (permalink / raw)
  To: liviu.dudau
  Cc: Arnd Bergmann, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, bhelgaas@googl e.com, zhichang.yuan02

SGkgTGl2aXUNCg0KPiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBsaXZpdS5k
dWRhdUBhcm0uY29tIFttYWlsdG86bGl2aXUuZHVkYXVAYXJtLmNvbV0NCj4gU2VudDogMTEgTm92
ZW1iZXIgMjAxNiAxNDo0Ng0KPiBUbzogR2FicmllbGUgUGFvbG9uaQ0KPiBDYzogQXJuZCBCZXJn
bWFubjsgbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnOyBZdWFuemhpY2hhbmc7
DQo+IG1hcmsucnV0bGFuZEBhcm0uY29tOyBkZXZpY2V0cmVlQHZnZXIua2VybmVsLm9yZzsNCj4g
bG9yZW56by5waWVyYWxpc2lAYXJtLmNvbTsgbWlueWFyZEBhY20ub3JnOyBsaW51eC1wY2lAdmdl
ci5rZXJuZWwub3JnOw0KPiBiZW5oQGtlcm5lbC5jcmFzaGluZy5vcmc7IEpvaG4gR2Fycnk7IHdp
bGwuZGVhY29uQGFybS5jb207IGxpbnV4LQ0KPiBrZXJuZWxAdmdlci5rZXJuZWwub3JnOyB4dXdl
aSAoTyk7IExpbnV4YXJtOyB6b3Vyb25ncm9uZ0BnbWFpbC5jb207DQo+IHJvYmgrZHRAa2VybmVs
Lm9yZzsga2FudHl6Y0AxNjMuY29tOyBsaW51eC1zZXJpYWxAdmdlci5rZXJuZWwub3JnOw0KPiBj
YXRhbGluLm1hcmluYXNAYXJtLmNvbTsgb2xvZkBsaXhvbS5uZXQ7IGJoZWxnYWFzQGdvb2dsIGUu
Y29tOw0KPiB6aGljaGFuZy55dWFuMDJAZ21haWwuY29tDQo+IFN1YmplY3Q6IFJlOiBbUEFUQ0gg
VjUgMy8zXSBBUk02NCBMUEM6IExQQyBkcml2ZXIgaW1wbGVtZW50YXRpb24gb24NCj4gSGlwMDYN
Cj4gDQo+IE9uIEZyaSwgTm92IDExLCAyMDE2IGF0IDAxOjM5OjM1UE0gKzAwMDAsIEdhYnJpZWxl
IFBhb2xvbmkgd3JvdGU6DQo+ID4gSGkgQXJuZA0KPiA+DQo+ID4gPiAtLS0tLU9yaWdpbmFsIE1l
c3NhZ2UtLS0tLQ0KPiA+ID4gRnJvbTogQXJuZCBCZXJnbWFubiBbbWFpbHRvOmFybmRAYXJuZGIu
ZGVdDQo+ID4gPiBTZW50OiAxMCBOb3ZlbWJlciAyMDE2IDE2OjA3DQo+ID4gPiBUbzogR2Ficmll
bGUgUGFvbG9uaQ0KPiA+ID4gQ2M6IGxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9y
ZzsgWXVhbnpoaWNoYW5nOw0KPiA+ID4gbWFyay5ydXRsYW5kQGFybS5jb207IGRldmljZXRyZWVA
dmdlci5rZXJuZWwub3JnOw0KPiA+ID4gbG9yZW56by5waWVyYWxpc2lAYXJtLmNvbTsgbWlueWFy
ZEBhY20ub3JnOyBsaW51eC0NCj4gcGNpQHZnZXIua2VybmVsLm9yZzsNCj4gPiA+IGJlbmhAa2Vy
bmVsLmNyYXNoaW5nLm9yZzsgSm9obiBHYXJyeTsgd2lsbC5kZWFjb25AYXJtLmNvbTsgbGludXgt
DQo+ID4gPiBrZXJuZWxAdmdlci5rZXJuZWwub3JnOyB4dXdlaSAoTyk7IExpbnV4YXJtOyB6b3Vy
b25ncm9uZ0BnbWFpbC5jb207DQo+ID4gPiByb2JoK2R0QGtlcm5lbC5vcmc7IGthbnR5emNAMTYz
LmNvbTsgbGludXgtc2VyaWFsQHZnZXIua2VybmVsLm9yZzsNCj4gPiA+IGNhdGFsaW4ubWFyaW5h
c0Bhcm0uY29tOyBvbG9mQGxpeG9tLm5ldDsgbGl2aXUuZHVkYXVAYXJtLmNvbTsNCj4gPiA+IGJo
ZWxnYWFzQGdvb2dsIGUuY29tOyB6aGljaGFuZy55dWFuMDJAZ21haWwuY29tDQo+ID4gPiBTdWJq
ZWN0OiBSZTogW1BBVENIIFY1IDMvM10gQVJNNjQgTFBDOiBMUEMgZHJpdmVyIGltcGxlbWVudGF0
aW9uIG9uDQo+ID4gPiBIaXAwNg0KPiA+ID4NCj4gPiA+IE9uIFRodXJzZGF5LCBOb3ZlbWJlciAx
MCwgMjAxNiAzOjM2OjQ5IFBNIENFVCBHYWJyaWVsZSBQYW9sb25pDQo+IHdyb3RlOg0KPiA+ID4g
Pg0KPiA+ID4gPiBXaGVyZSBzaG91bGQgd2UgZ2V0IHRoZSByYW5nZSBmcm9tPyBGb3IgTFBDIHdl
IGtub3cgdGhhdCBpdCBpcw0KPiBnb2luZw0KPiA+ID4gPiBXb3JrIG9uIGFueXRoaW5nIHRoYXQg
aXMgbm90IHVzZWQgYnkgUENJIEkvTyBzcGFjZSwgYW5kIHRoaXMgaXMNCj4gPiA+ID4gd2h5IHdl
IHVzZSBbMCwgUENJQklPU19NSU5fSU9dDQo+ID4gPg0KPiA+ID4gSXQgc2hvdWxkIGJlIGFsbG9j
YXRlZCB0aGUgc2FtZSB3YXkgd2UgYWxsb2NhdGUgUENJIGNvbmZpZyBzcGFjZQ0KPiA+ID4gc2Vn
bWVudHMuIFRoaXMgaXMgY3VycmVudGx5IGRvbmUgd2l0aCB0aGUgaW9fcmFuZ2UgbGlzdCBpbg0K
PiA+ID4gZHJpdmVycy9wY2kvcGNpLmMsIHdoaWNoIGlzbid0IHBlcmZlY3QgYnV0IGNvdWxkIGJl
IGV4dGVuZGVkDQo+ID4gPiBpZiBuZWNlc3NhcnkuIEJhc2VkIG9uIHdoYXQgb3RoZXJzIGNvbW1l
bnRlZCBoZXJlLCBJJ2QgcmF0aGVyDQo+ID4gPiBtYWtlIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVu
IElTQS9MUEMgYW5kIFBDSSBJL08gcmFuZ2VzIHNtYWxsZXINCj4gPiA+IHRoYW4gbGFyZ2VyLg0K
PiANCj4gR2FicmllbGUsDQo+IA0KPiA+DQo+ID4gSSBhbSBub3Qgc3VyZSB0aGlzIHdvdWxkIG1h
a2Ugc2Vuc2UuLi4NCj4gPg0KPiA+IElNSE8gYWxsIHRoZSBtZWNoYW5pc20gYXJvdW5kIGlvX3Jh
bmdlX2xpc3QgaXMgbmVlZGVkIHRvIHByb3ZpZGUgdGhlDQo+ID4gIm1hcHBpbmciIGJldHdlZW4g
SS9PIHRva2VucyBhbmQgcGh5c2ljYWwgQ1BVIGFkZHJlc3Nlcy4NCj4gPg0KPiA+IEN1cnJlbnRs
eSB0aGUgYXZhaWxhYmxlIHRva2VucyByYW5nZSBmcm9tIDAgdG8gSU9fU1BBQ0VfTElNSVQuDQo+
ID4NCj4gPiBBcyB5b3Uga25vdyB0aGUgSS9PIG1lbW9yeSBhY2Nlc3NvcnMgb3BlcmF0ZSBvbiB3
aGF0ZXZlcg0KPiA+IF9fb2ZfYWRkcmVzc190b19yZXNvdXJjZSBzZXRzIGludG8gdGhlIHJlc291
cmNlIChzdGFydCwgZW5kKS4NCj4gPg0KPiA+IFdpdGggdGhpcyBzcGVjaWFsIGRldmljZSBpbiBw
bGFjZSB3ZSBjYW5ub3Qga25vdyBpZiBhIHJlc291cmNlIGlzDQo+ID4gYXNzaWduZWQgd2l0aCBh
biBJL08gdG9rZW4gb3IgYSBwaHlzaWNhbCBhZGRyZXNzLCB1bmxlc3Mgd2UgZm9yYmlkDQo+ID4g
dGhlIEkvTyB0b2tlbnMgdG8gYmUgaW4gYSBzcGVjaWZpYyByYW5nZS4NCj4gPg0KPiA+IFNvIHRo
aXMgaXMgd2h5IHdlIGFyZSBjaGFuZ2luZyB0aGUgb2Zmc2V0cyBvZiBhbGwgdGhlIGZ1bmN0aW9u
cw0KPiA+IGhhbmRsaW5nIGlvX3JhbmdlX2xpc3QgKHRvIG1ha2Ugc3VyZSB0aGF0IGEgcmFuZ2Ug
aXMgZm9yYmlkZGVuIHRvDQo+ID4gdGhlIHRva2VucyBhbmQgaXMgYXZhaWxhYmxlIHRvIHRoZSBw
aHlzaWNhbCBhZGRyZXNzZXMpLg0KPiA+DQo+ID4gV2UgaGF2ZSBjaG9zZW4gdGhpcyBmb3JiaWRk
ZW4gcmFuZ2UgdG8gYmUgWzAsIFBDSUJJT1NfTUlOX0lPKQ0KPiA+IGJlY2F1c2UgdGhpcyBpcyB0
aGUgbWF4aW11bSBwaHlzaWNhbCBJL08gcmFuZ2UgdGhhdCBhIG5vbiBQQ0kgZGV2aWNlDQo+ID4g
Y2FuIG9wZXJhdGUgb24gYW5kIGJlY2F1c2Ugd2UgYmVsaWV2ZSB0aGlzIGRvZXMgbm90IGltcG9z
ZSBtdWNoDQo+ID4gcmVzdHJpY3Rpb24gb24gdGhlIGF2YWlsYWJsZSBJL08gdG9rZW4gcmFuZ2U7
IHRoYXQgbm93IGlzDQo+ID4gW1BDSUJJT1NfTUlOX0lPLCBJT19TUEFDRV9MSU1JVF0uDQo+ID4g
U28gd2UgYmVsaWV2ZSB0aGF0IHRoZSBjaG9zZW4gZm9yYmlkZGVuIHJhbmdlIGNhbiBhY2NvbW1v
ZGF0ZQ0KPiA+IGFueSBzcGVjaWFsIElTQSBidXMgZGV2aWNlIHdpdGggbm8gbXVjaCBjb25zdHJh
aW50IG9uIHRoZSByZXN0DQo+ID4gb2YgSS9PIHRva2Vucy4uLg0KPiANCj4gWW91ciBpZGVhIGlz
IGEgZ29vZCBvbmUsIGhvd2V2ZXIgeW91IGFyZSBhYnVzaW5nIFBDSUJJT1NfTUlOX0lPIGFuZCB5
b3UNCj4gYWN0dWFsbHkgbmVlZCBhbm90aGVyIHZhcmlhYmxlIGZvciAicmVzZXJ2aW5nIiBhbiBh
cmVhIGluIHRoZSBJL08gc3BhY2UNCj4gdGhhdCBjYW4gYmUgdXNlZCBmb3IgcGh5c2ljYWwgYWRk
cmVzc2VzIHJhdGhlciB0aGFuIEkvTyB0b2tlbnMuDQo+IA0KPiBUaGUgb25lIGdvb2QgZXhhbXBs
ZSBmb3IgdXNpbmcgUENJQklPU19NSU5fSU8gaXMgd2hlbiB5b3VyDQo+IHBsYXRmb3JtL2FyY2hp
dGVjdHVyZQ0KPiBkb2VzIG5vdCBzdXBwb3J0IGxlZ2FjeSBJU0Egb3BlcmF0aW9ucyAqYXQgYWxs
Ki4gSW4gdGhhdCBjYXNlIHNvbWVvbmUNCj4gc2V0cyB0aGUgUENJQklPU19NSU5fSU8gdG8gYSBu
b24temVybyB2YWx1ZSB0byByZXNlcnZlIHRoYXQgSS9PIHJhbmdlDQo+IHNvIHRoYXQgaXQgZG9l
c24ndCBnZXQgdXNlZC4gV2l0aCBaaGljaGFuZydzIHBhdGNoIHlvdSBub3cgc3RhcnQNCj4gZm9y
Y2luZw0KPiB0aG9zZSBwbGF0Zm9ybXMgdG8gaGF2ZSBhIHZhbGlkIGFkZHJlc3MgYmVsb3cgUENJ
QklPU19NSU5fSU8uDQoNCkJ1dCBpZiBQQ0lCSU9TX01JTl9JTyBpcyAwIHRoZW4gaXQgbWVhbnMg
dGhhdCBhbGwgSS9PIHNwYWNlIGlzIHRvIGJlIHVzZWQNCmJ5IFBDSSBjb250cm9sbGVycyBvbmx5
Li4uc28gaWYgeW91IGhhdmUgYSBzcGVjaWFsIGJ1cyBkZXZpY2UgdXNpbmcNCmFuIEkvTyByYW5n
ZSBpbiB0aGlzIGNhc2Ugc2hvdWxkIGJlIGEgUENJIGNvbnRyb2xsZXIuLi5pLmUuIEkgd291bGQN
CmV4cGVjdCBpdCB0byBmYWxsIGJhY2sgaW50byB0aGUgY2FzZSBvZiBJL08gdG9rZW5zIHJlZGly
ZWN0aW9uIHJhdGhlciB0aGFuDQpwaHlzaWNhbCBhZGRyZXNzZXMgcmVkaXJlY3Rpb24gKGFzIG1l
bnRpb25lZCBiZWxvdyBmcm9tIG15IHByZXZpb3VzIHJlcGx5KS4NCldoYXQgZG8geW91IHRoaW5r
Pw0KDQpUaGFua3MNCg0KR2FiDQoNCg0KPiANCj4gRm9yIHRoZSBnZW5lcmFsIGNhc2UgeW91IGFs
c28gaGF2ZSB0byBiZWFyIGluIG1pbmQgdGhhdCBQQ0lCSU9TX01JTl9JTw0KPiBjb3VsZA0KPiBi
ZSB6ZXJvLiBJbiB0aGF0IGNhc2UsIHdoYXQgaXMgeW91ciAiZm9yYmlkZGVuIiByYW5nZT8gWzAs
IDApID8gU28gaXQNCj4gbWFrZXMNCj4gc2Vuc2UgdG8gYWRkIGEgbmV3ICNkZWZpbmUgdGhhdCBz
aG91bGQgb25seSBiZSBkZWZpbmVkIGJ5IHRob3NlDQo+IGFyY2hpdGVjdHVyZXMvDQo+IHBsYXRm
b3JtcyB0aGF0IHdhbnQgdG8gcmVzZXJ2ZSBvbiB0b3Agb2YgUENJQklPU19NSU5fSU8gYW5vdGhl
ciByZWdpb24NCj4gd2hlcmUgSS9PIHRva2VucyBjYW4ndCBiZSBnZW5lcmF0ZWQgZm9yLg0KPiAN
Cj4gQmVzdCByZWdhcmRzLA0KPiBMaXZpdQ0KPiANCj4gPg0KPiA+ID4NCj4gPiA+ID4gPiBZb3Vy
IGN1cnJlbnQgdmVyc2lvbiBoYXMNCj4gPiA+ID4gPg0KPiA+ID4gPiA+ICAgICAgICAgaWYgKGFy
bTY0X2V4dGlvX29wcy0+cGZvdXQpDQo+IFwNCj4gPiA+ID4gPiAgICAgICAgICAgICAgICAgYXJt
NjRfZXh0aW9fb3BzLT5wZm91dChhcm02NF9leHRpb19vcHMtDQo+ID5kZXZwYXJhLFwNCj4gPiA+
ID4gPiAgICAgICAgICAgICAgICAgICAgICAgIGFkZHIsIHZhbHVlLCBzaXplb2YodHlwZSkpOw0K
PiBcDQo+ID4gPiA+ID4NCj4gPiA+ID4gPiBJbnN0ZWFkLCBqdXN0IHN1YnRyYWN0IHRoZSBzdGFy
dCBvZiB0aGUgcmFuZ2UgZnJvbSB0aGUgbG9naWNhbA0KPiA+ID4gPiA+IHBvcnQgbnVtYmVyIHRv
IHRyYW5zZm9ybSBpdCBiYWNrIGludG8gYSBidXMtbG9jYWwgcG9ydCBudW1iZXI6DQo+ID4gPiA+
DQo+ID4gPiA+IFRoZXNlIGFjY2Vzc29ycyBkbyBub3Qgb3BlcmF0ZSBvbiBJTyB0b2tlbnM6DQo+
ID4gPiA+DQo+ID4gPiA+IElmIChhcm02NF9leHRpb19vcHMtPnN0YXJ0ID4gYWRkciB8fCBhcm02
NF9leHRpb19vcHMtPmVuZCA8IGFkZHIpDQo+ID4gPiA+IGFkZHIgaXMgbm90IGdvaW5nIHRvIGJl
IGFuIEkvTyB0b2tlbjsgaW4gZmFjdCBwYXRjaCAyLzMgaW1wb3Nlcw0KPiB0aGF0DQo+ID4gPiA+
IHRoZSBJL08gdG9rZW5zIHdpbGwgc3RhcnQgYXQgUENJQklPU19NSU5fSU8uIFNvIGZyb20gMCB0
bw0KPiA+ID4gUENJQklPU19NSU5fSU8NCj4gPiA+ID4gd2UgaGF2ZSBmcmVlIHBoeXNpY2FsIGFk
ZHJlc3NlcyB0aGF0IHRoZSBhY2Nlc3NvcnMgY2FuIG9wZXJhdGUNCj4gb24uDQo+ID4gPg0KPiA+
ID4gQWgsIEkgbWlzc2VkIHRoYXQgcGFydC4gSSdkIHJhdGhlciBub3QgdXNlIFBDSUJJT1NfTUlO
X0lPIHRvIHJlZmVyDQo+IHRvDQo+ID4gPiB0aGUgbG9naWNhbCBJL08gdG9rZW5zLCB0aGUgcHVy
cG9zZSBvZiB0aGF0IG1hY3JvIGlzIHJlYWxseSBtZWFudA0KPiA+ID4gZm9yIGFsbG9jYXRpbmcg
UENJIEkvTyBwb3J0IG51bWJlcnMgd2l0aGluIHRoZSBhZGRyZXNzIHNwYWNlIG9mDQo+ID4gPiBv
bmUgYnVzLg0KPiA+DQo+ID4gQXMgSSBtZW50aW9uZWQgYWJvdmUsIHNwZWNpYWwgZGV2aWNlcyBv
cGVyYXRlIG9uIENQVSBhZGRyZXNzZXMNCj4gZGlyZWN0bHksDQo+ID4gbm90IEkvTyB0b2tlbnMu
IEZvciB0aGVtIHRoZXJlIGlzIG5vIHdheSB0byBkaXN0aW5ndWlzaC4uLi4NCj4gPg0KPiA+ID4N
Cj4gPiA+IE5vdGUgdGhhdCBpdCdzIGVxdWFsbHkgbGlrZWx5IHRoYXQgd2hpY2hldmVyIG5leHQg
cGxhdGZvcm0gbmVlZHMNCj4gPiA+IG5vbi1tYXBwZWQgSS9PIGFjY2VzcyBsaWtlIHRoaXMgYWN0
dWFsbHkgbmVlZHMgdGhlbSBmb3IgUENJIEkvTw0KPiBzcGFjZSwNCj4gPiA+IGFuZCB0aGF0IHdp
bGwgdXNlIGl0IG9uIGFkZHJlc3NlcyByZWdpc3RlcmVkIHRvIGEgUENJIGhvc3QgYnJpZGdlLg0K
PiA+DQo+ID4gT2sgc28gaGVyZSB5b3UgYXJlIHRhbGtpbmcgYWJvdXQgYSBwbGF0Zm9ybSB0aGF0
IGhhcyBnb3QgYW4gSS9PIHJhbmdlDQo+ID4gdW5kZXIgdGhlIFBDSSBob3N0IGNvbnRyb2xsZXIs
IHJpZ2h0Pw0KPiA+IEFuZCB0aGlzIEkvTyByYW5nZSBjYW5ub3QgYmUgZGlyZWN0bHkgbWVtb3J5
IG1hcHBlZCBidXQgbmVlZHMgc3BlY2lhbA0KPiA+IHJlZGlyZWN0aW9ucyBmb3IgdGhlIEkvTyB0
b2tlbnMsIHJpZ2h0Pw0KPiA+DQo+ID4gSW4gdGhpcyBzY2VuYXJpbyByZWdpc3RlcmluZyB0aGUg
SS9PIHJhbmdlcyB3aXRoIHRoZSBmb3JiaWRkZW4gcmFuZ2UNCj4gPiBpbXBsZW1lbnRlZCBieSB0
aGUgY3VycmVudCBwYXRjaCB3b3VsZCBzdGlsbCBhbGxvdyB0byByZWRpcmVjdCBJL08NCj4gPiB0
b2tlbnMgYXMgbG9uZyBhcyBhcm02NF9leHRpb19vcHMtPnN0YXJ0ID49IFBDSUJJT1NfTUlOX0lP
DQo+ID4NCj4gPiBTbyBlZmZlY3RpdmVseSB0aGUgc3BlY2lhbCBQQ0kgaG9zdCBjb250cm9sbGVy
DQo+ID4gMSkga25vd3MgdGhlIHBoeXNpY2FsIHJhbmdlIHRoYXQgbmVlZHMgc3BlY2lhbCByZWRp
cmVjdGlvbg0KPiA+IDIpIHJlZ2lzdGVyIHN1Y2ggcmFuZ2UNCj4gPiAzKSB1c2VzIHBjaV9waW9f
dG9fYWRkcmVzcygpIHRvIHJldHJpZXZlIHRoZSBJTyB0b2tlbnMgZm9yIHRoZQ0KPiA+ICAgIHNw
ZWNpYWwgYWNjZXNzb3JzDQo+ID4gNCkgc2V0cyBhcm02NF9leHRpb19vcHMtPnN0YXJ0L2VuZCB0
byB0aGUgSU8gdG9rZW5zIHJldHJpZXZlZCBpbiAzKQ0KPiA+DQo+ID4gU28gdG8gYmUgaG9uZXN0
IEkgdGhpbmsgdGhpcyBwYXRjaCBjYW4gZml0IHdlbGwgYm90aCB3aXRoDQo+ID4gc3BlY2lhbCBQ
Q0kgY29udHJvbGxlcnMgdGhhdCBuZWVkIEkvTyB0b2tlbnMgcmVkaXJlY3Rpb24gYW5kIHdpdGgN
Cj4gPiBzcGVjaWFsIG5vbi1QQ0kgY29udHJvbGxlcnMgdGhhdCBuZWVkIG5vbi1QQ0kgSS9PIHBo
eXNpY2FsDQo+ID4gYWRkcmVzcyByZWRpcmVjdGlvbi4uLg0KPiA+DQo+ID4gVGhhbmtzIChhbmQg
c29ycnkgZm9yIHRoZSBsb25nIHJlcGx5IGJ1dCBJIGRpZG4ndCBrbm93IGhvdw0KPiA+IHRvIG1h
a2UgdGhlIGV4cGxhbmF0aW9uIHNob3J0ZXIgOikgKQ0KPiA+DQo+ID4gR2FiDQo+ID4NCj4gPiA+
DQo+ID4gPiBJZiB3ZSBzZXBhcmF0ZSB0aGUgdHdvIHN0ZXBzOg0KPiA+ID4NCj4gPiA+IGEpIGFz
c2lnbiBhIHJhbmdlIG9mIGxvZ2ljYWwgSS9PIHBvcnQgbnVtYmVycyB0byBhIGJ1cw0KPiA+ID4g
YikgcmVnaXN0ZXIgYSBzZXQgb2YgaGVscGVycyBmb3IgcmVkaXJlY3RpbmcgbG9naWNhbCBJL08N
Cj4gPiA+ICAgIHBvcnQgdG8gYSBoZWxwZXIgZnVuY3Rpb24NCj4gPiA+DQo+ID4gPiB0aGVuIEkg
dGhpbmsgdGhlIGNvZGUgd2lsbCBnZXQgY2xlYW5lciBhbmQgbW9yZSBmbGV4aWJsZS4NCj4gPiA+
IEl0IHNob3VsZCBhY3R1YWxseSB0aGVuIGJlIGFibGUgdG8gcmVwbGFjZSB0aGUgcG93ZXJwYw0K
PiA+ID4gc3BlY2lmaWMgaW1wbGVtZW50YXRpb24uDQo+ID4gPg0KPiA+ID4gCUFybmQNCj4gDQo+
IC0tDQo+ID09PT09PT09PT09PT09PT09PT09DQo+IHwgSSB3b3VsZCBsaWtlIHRvIHwNCj4gfCBm
aXggdGhlIHdvcmxkLCAgfA0KPiB8IGJ1dCB0aGV5J3JlIG5vdCB8DQo+IHwgZ2l2aW5nIG1lIHRo
ZSAgIHwNCj4gIFwgc291cmNlIGNvZGUhICAvDQo+ICAgLS0tLS0tLS0tLS0tLS0tDQo+ICAgICDC
r1xfKOODhClfL8KvDQo=

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 15:53                       ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-11 15:53 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Liviu

> -----Original Message-----
> From: liviu.dudau at arm.com [mailto:liviu.dudau at arm.com]
> Sent: 11 November 2016 14:46
> To: Gabriele Paoloni
> Cc: Arnd Bergmann; linux-arm-kernel at lists.infradead.org; Yuanzhichang;
> mark.rutland at arm.com; devicetree at vger.kernel.org;
> lorenzo.pieralisi at arm.com; minyard at acm.org; linux-pci at vger.kernel.org;
> benh at kernel.crashing.org; John Garry; will.deacon at arm.com; linux-
> kernel at vger.kernel.org; xuwei (O); Linuxarm; zourongrong at gmail.com;
> robh+dt at kernel.org; kantyzc at 163.com; linux-serial at vger.kernel.org;
> catalin.marinas at arm.com; olof at lixom.net; bhelgaas at googl e.com;
> zhichang.yuan02 at gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Fri, Nov 11, 2016 at 01:39:35PM +0000, Gabriele Paoloni wrote:
> > Hi Arnd
> >
> > > -----Original Message-----
> > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > Sent: 10 November 2016 16:07
> > > To: Gabriele Paoloni
> > > Cc: linux-arm-kernel at lists.infradead.org; Yuanzhichang;
> > > mark.rutland at arm.com; devicetree at vger.kernel.org;
> > > lorenzo.pieralisi at arm.com; minyard at acm.org; linux-
> pci at vger.kernel.org;
> > > benh at kernel.crashing.org; John Garry; will.deacon at arm.com; linux-
> > > kernel at vger.kernel.org; xuwei (O); Linuxarm; zourongrong at gmail.com;
> > > robh+dt at kernel.org; kantyzc at 163.com; linux-serial at vger.kernel.org;
> > > catalin.marinas at arm.com; olof at lixom.net; liviu.dudau at arm.com;
> > > bhelgaas at googl e.com; zhichang.yuan02 at gmail.com
> > > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> > > Hip06
> > >
> > > On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni
> wrote:
> > > >
> > > > Where should we get the range from? For LPC we know that it is
> going
> > > > Work on anything that is not used by PCI I/O space, and this is
> > > > why we use [0, PCIBIOS_MIN_IO]
> > >
> > > It should be allocated the same way we allocate PCI config space
> > > segments. This is currently done with the io_range list in
> > > drivers/pci/pci.c, which isn't perfect but could be extended
> > > if necessary. Based on what others commented here, I'd rather
> > > make the differences between ISA/LPC and PCI I/O ranges smaller
> > > than larger.
> 
> Gabriele,
> 
> >
> > I am not sure this would make sense...
> >
> > IMHO all the mechanism around io_range_list is needed to provide the
> > "mapping" between I/O tokens and physical CPU addresses.
> >
> > Currently the available tokens range from 0 to IO_SPACE_LIMIT.
> >
> > As you know the I/O memory accessors operate on whatever
> > __of_address_to_resource sets into the resource (start, end).
> >
> > With this special device in place we cannot know if a resource is
> > assigned with an I/O token or a physical address, unless we forbid
> > the I/O tokens to be in a specific range.
> >
> > So this is why we are changing the offsets of all the functions
> > handling io_range_list (to make sure that a range is forbidden to
> > the tokens and is available to the physical addresses).
> >
> > We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
> > because this is the maximum physical I/O range that a non PCI device
> > can operate on and because we believe this does not impose much
> > restriction on the available I/O token range; that now is
> > [PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
> > So we believe that the chosen forbidden range can accommodate
> > any special ISA bus device with no much constraint on the rest
> > of I/O tokens...
> 
> Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and you
> actually need another variable for "reserving" an area in the I/O space
> that can be used for physical addresses rather than I/O tokens.
> 
> The one good example for using PCIBIOS_MIN_IO is when your
> platform/architecture
> does not support legacy ISA operations *at all*. In that case someone
> sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O range
> so that it doesn't get used. With Zhichang's patch you now start
> forcing
> those platforms to have a valid address below PCIBIOS_MIN_IO.

But if PCIBIOS_MIN_IO is 0 then it means that all I/O space is to be used
by PCI controllers only...so if you have a special bus device using
an I/O range in this case should be a PCI controller...i.e. I would
expect it to fall back into the case of I/O tokens redirection rather than
physical addresses redirection (as mentioned below from my previous reply).
What do you think?

Thanks

Gab


> 
> For the general case you also have to bear in mind that PCIBIOS_MIN_IO
> could
> be zero. In that case, what is your "forbidden" range? [0, 0) ? So it
> makes
> sense to add a new #define that should only be defined by those
> architectures/
> platforms that want to reserve on top of PCIBIOS_MIN_IO another region
> where I/O tokens can't be generated for.
> 
> Best regards,
> Liviu
> 
> >
> > >
> > > > > Your current version has
> > > > >
> > > > >         if (arm64_extio_ops->pfout)
> \
> > > > >                 arm64_extio_ops->pfout(arm64_extio_ops-
> >devpara,\
> > > > >                        addr, value, sizeof(type));
> \
> > > > >
> > > > > Instead, just subtract the start of the range from the logical
> > > > > port number to transform it back into a bus-local port number:
> > > >
> > > > These accessors do not operate on IO tokens:
> > > >
> > > > If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> > > > addr is not going to be an I/O token; in fact patch 2/3 imposes
> that
> > > > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> > > PCIBIOS_MIN_IO
> > > > we have free physical addresses that the accessors can operate
> on.
> > >
> > > Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer
> to
> > > the logical I/O tokens, the purpose of that macro is really meant
> > > for allocating PCI I/O port numbers within the address space of
> > > one bus.
> >
> > As I mentioned above, special devices operate on CPU addresses
> directly,
> > not I/O tokens. For them there is no way to distinguish....
> >
> > >
> > > Note that it's equally likely that whichever next platform needs
> > > non-mapped I/O access like this actually needs them for PCI I/O
> space,
> > > and that will use it on addresses registered to a PCI host bridge.
> >
> > Ok so here you are talking about a platform that has got an I/O range
> > under the PCI host controller, right?
> > And this I/O range cannot be directly memory mapped but needs special
> > redirections for the I/O tokens, right?
> >
> > In this scenario registering the I/O ranges with the forbidden range
> > implemented by the current patch would still allow to redirect I/O
> > tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
> >
> > So effectively the special PCI host controller
> > 1) knows the physical range that needs special redirection
> > 2) register such range
> > 3) uses pci_pio_to_address() to retrieve the IO tokens for the
> >    special accessors
> > 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in 3)
> >
> > So to be honest I think this patch can fit well both with
> > special PCI controllers that need I/O tokens redirection and with
> > special non-PCI controllers that need non-PCI I/O physical
> > address redirection...
> >
> > Thanks (and sorry for the long reply but I didn't know how
> > to make the explanation shorter :) )
> >
> > Gab
> >
> > >
> > > If we separate the two steps:
> > >
> > > a) assign a range of logical I/O port numbers to a bus
> > > b) register a set of helpers for redirecting logical I/O
> > >    port to a helper function
> > >
> > > then I think the code will get cleaner and more flexible.
> > > It should actually then be able to replace the powerpc
> > > specific implementation.
> > >
> > > 	Arnd
> 
> --
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ?\_(?)_/?

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-11 14:45                     ` liviu.dudau-5wv7dgnIgG8
  (?)
  (?)
@ 2016-11-11 16:54                       ` zhichang.yuan
  -1 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-11 16:54 UTC (permalink / raw)
  To: liviu.dudau, Gabriele Paoloni
  Cc: Arnd Bergmann, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, bhelgaas@googl e.com

Hi, Liviu,


On 11/11/2016 10:45 PM, liviu.dudau@arm.com wrote:
> On Fri, Nov 11, 2016 at 01:39:35PM +0000, Gabriele Paoloni wrote:
>> Hi Arnd
>>
>>> -----Original Message-----
>>> From: Arnd Bergmann [mailto:arnd@arndb.de]
>>> Sent: 10 November 2016 16:07
>>> To: Gabriele Paoloni
>>> Cc: linux-arm-kernel@lists.infradead.org; Yuanzhichang;
>>> mark.rutland@arm.com; devicetree@vger.kernel.org;
>>> lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
>>> benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
>>> kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
>>> robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
>>> catalin.marinas@arm.com; olof@lixom.net; liviu.dudau@arm.com;
>>> bhelgaas@googl e.com; zhichang.yuan02@gmail.com
>>> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
>>> Hip06
>>>
>>> On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
>>>>
>>>> Where should we get the range from? For LPC we know that it is going
>>>> Work on anything that is not used by PCI I/O space, and this is
>>>> why we use [0, PCIBIOS_MIN_IO]
>>>
>>> It should be allocated the same way we allocate PCI config space
>>> segments. This is currently done with the io_range list in
>>> drivers/pci/pci.c, which isn't perfect but could be extended
>>> if necessary. Based on what others commented here, I'd rather
>>> make the differences between ISA/LPC and PCI I/O ranges smaller
>>> than larger.
> 
> Gabriele,
> 
>>
>> I am not sure this would make sense...
>>
>> IMHO all the mechanism around io_range_list is needed to provide the
>> "mapping" between I/O tokens and physical CPU addresses.
>>
>> Currently the available tokens range from 0 to IO_SPACE_LIMIT.
>>
>> As you know the I/O memory accessors operate on whatever
>> __of_address_to_resource sets into the resource (start, end).
>>
>> With this special device in place we cannot know if a resource is
>> assigned with an I/O token or a physical address, unless we forbid
>> the I/O tokens to be in a specific range.
>>
>> So this is why we are changing the offsets of all the functions
>> handling io_range_list (to make sure that a range is forbidden to
>> the tokens and is available to the physical addresses).
>>
>> We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
>> because this is the maximum physical I/O range that a non PCI device
>> can operate on and because we believe this does not impose much
>> restriction on the available I/O token range; that now is 
>> [PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
>> So we believe that the chosen forbidden range can accommodate
>> any special ISA bus device with no much constraint on the rest
>> of I/O tokens...
> 
> Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and you
> actually need another variable for "reserving" an area in the I/O space
> that can be used for physical addresses rather than I/O tokens.
> 
I think selecting PCIBIOS_MIN_IO as the separator of mapped and non-mapped I/O
range probably is not so reasonable.
PCIBIOS_MIN_IN is specific to PCI devices, it seems as the recommended minimal
start I/O address when assigning the pci device I/O region. It is probably not
defined in some platforms/architectures when no PCI is needed there. That is why
my patch caused some compile error on some archs;

But more important thing is that the PCIBIOS_MIN_IO has different value on
different platforms/architectures. On Arm64, it is 4K currently, but in other
archs, it is not true. And the maximum LPC I/O address should be 64K
theoretically, although for compatible ISA, 2K is enough.
So, It means using PCIBIOS_MIN_IO on arm64 can match our I/O reservation
require. But we can not make this indirectIO work well on other architectures.

I am thinking Arnd's suggestion. But I worry about I haven't completely
understood his idea. What about create a new bus host for LPC/ISA whose I/O
range can be 64KB? This LPC/ISA I/O range works similar to PCI host bridge's I/O
window, all the downstream devices under LPC/ISA should request I/O from that
root resource. But it seems Arnd want this root resource registered dynamically,
I am not sure how to do...

Anyway, if we have this root I/O resource, we don't need any new macro or
variable for the LPC/ISA I/O reservation.

Hope my thought is right.

Best,
Zhichang


> The one good example for using PCIBIOS_MIN_IO is when your platform/architecture
> does not support legacy ISA operations *at all*. In that case someone
> sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O range
> so that it doesn't get used. With Zhichang's patch you now start forcing
> those platforms to have a valid address below PCIBIOS_MIN_IO.
> 
> For the general case you also have to bear in mind that PCIBIOS_MIN_IO could
> be zero. In that case, what is your "forbidden" range? [0, 0) ? So it makes
> sense to add a new #define that should only be defined by those architectures/
> platforms that want to reserve on top of PCIBIOS_MIN_IO another region
> where I/O tokens can't be generated for.
> 
> Best regards,
> Liviu
> 
>>
>>>
>>>>> Your current version has
>>>>>
>>>>>         if (arm64_extio_ops->pfout)                             \
>>>>>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>>>>>                        addr, value, sizeof(type));             \
>>>>>
>>>>> Instead, just subtract the start of the range from the logical
>>>>> port number to transform it back into a bus-local port number:
>>>>
>>>> These accessors do not operate on IO tokens:
>>>>
>>>> If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
>>>> addr is not going to be an I/O token; in fact patch 2/3 imposes that
>>>> the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
>>> PCIBIOS_MIN_IO
>>>> we have free physical addresses that the accessors can operate on.
>>>
>>> Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
>>> the logical I/O tokens, the purpose of that macro is really meant
>>> for allocating PCI I/O port numbers within the address space of
>>> one bus.
>>
>> As I mentioned above, special devices operate on CPU addresses directly,
>> not I/O tokens. For them there is no way to distinguish....
>>
>>>
>>> Note that it's equally likely that whichever next platform needs
>>> non-mapped I/O access like this actually needs them for PCI I/O space,
>>> and that will use it on addresses registered to a PCI host bridge.
>>
>> Ok so here you are talking about a platform that has got an I/O range
>> under the PCI host controller, right?
>> And this I/O range cannot be directly memory mapped but needs special
>> redirections for the I/O tokens, right?
>>
>> In this scenario registering the I/O ranges with the forbidden range
>> implemented by the current patch would still allow to redirect I/O
>> tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
>>
>> So effectively the special PCI host controller
>> 1) knows the physical range that needs special redirection
>> 2) register such range
>> 3) uses pci_pio_to_address() to retrieve the IO tokens for the
>>    special accessors
>> 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in 3)
>>
>> So to be honest I think this patch can fit well both with
>> special PCI controllers that need I/O tokens redirection and with
>> special non-PCI controllers that need non-PCI I/O physical
>> address redirection...
>>
>> Thanks (and sorry for the long reply but I didn't know how
>> to make the explanation shorter :) )
>>
>> Gab
>>
>>>
>>> If we separate the two steps:
>>>
>>> a) assign a range of logical I/O port numbers to a bus
>>> b) register a set of helpers for redirecting logical I/O
>>>    port to a helper function
>>>
>>> then I think the code will get cleaner and more flexible.
>>> It should actually then be able to replace the powerpc
>>> specific implementation.
>>>
>>> 	Arnd
> 

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 16:54                       ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-11 16:54 UTC (permalink / raw)
  To: liviu.dudau, Gabriele Paoloni
  Cc: mark.rutland, devicetree, bhelgaas@googl e.com,
	lorenzo.pieralisi, catalin.marinas, minyard, Arnd Bergmann,
	linux-pci, John Garry, will.deacon, linux-kernel, Yuanzhichang,
	Linuxarm, olof, robh+dt, xuwei (O),
	linux-serial, benh, zourongrong@gmail.com

Hi, Liviu,


On 11/11/2016 10:45 PM, liviu.dudau@arm.com wrote:
> On Fri, Nov 11, 2016 at 01:39:35PM +0000, Gabriele Paoloni wrote:
>> Hi Arnd
>>
>>> -----Original Message-----
>>> From: Arnd Bergmann [mailto:arnd@arndb.de]
>>> Sent: 10 November 2016 16:07
>>> To: Gabriele Paoloni
>>> Cc: linux-arm-kernel@lists.infradead.org; Yuanzhichang;
>>> mark.rutland@arm.com; devicetree@vger.kernel.org;
>>> lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
>>> benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
>>> kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
>>> robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
>>> catalin.marinas@arm.com; olof@lixom.net; liviu.dudau@arm.com;
>>> bhelgaas@googl e.com; zhichang.yuan02@gmail.com
>>> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
>>> Hip06
>>>
>>> On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
>>>>
>>>> Where should we get the range from? For LPC we know that it is going
>>>> Work on anything that is not used by PCI I/O space, and this is
>>>> why we use [0, PCIBIOS_MIN_IO]
>>>
>>> It should be allocated the same way we allocate PCI config space
>>> segments. This is currently done with the io_range list in
>>> drivers/pci/pci.c, which isn't perfect but could be extended
>>> if necessary. Based on what others commented here, I'd rather
>>> make the differences between ISA/LPC and PCI I/O ranges smaller
>>> than larger.
> 
> Gabriele,
> 
>>
>> I am not sure this would make sense...
>>
>> IMHO all the mechanism around io_range_list is needed to provide the
>> "mapping" between I/O tokens and physical CPU addresses.
>>
>> Currently the available tokens range from 0 to IO_SPACE_LIMIT.
>>
>> As you know the I/O memory accessors operate on whatever
>> __of_address_to_resource sets into the resource (start, end).
>>
>> With this special device in place we cannot know if a resource is
>> assigned with an I/O token or a physical address, unless we forbid
>> the I/O tokens to be in a specific range.
>>
>> So this is why we are changing the offsets of all the functions
>> handling io_range_list (to make sure that a range is forbidden to
>> the tokens and is available to the physical addresses).
>>
>> We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
>> because this is the maximum physical I/O range that a non PCI device
>> can operate on and because we believe this does not impose much
>> restriction on the available I/O token range; that now is 
>> [PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
>> So we believe that the chosen forbidden range can accommodate
>> any special ISA bus device with no much constraint on the rest
>> of I/O tokens...
> 
> Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and you
> actually need another variable for "reserving" an area in the I/O space
> that can be used for physical addresses rather than I/O tokens.
> 
I think selecting PCIBIOS_MIN_IO as the separator of mapped and non-mapped I/O
range probably is not so reasonable.
PCIBIOS_MIN_IN is specific to PCI devices, it seems as the recommended minimal
start I/O address when assigning the pci device I/O region. It is probably not
defined in some platforms/architectures when no PCI is needed there. That is why
my patch caused some compile error on some archs;

But more important thing is that the PCIBIOS_MIN_IO has different value on
different platforms/architectures. On Arm64, it is 4K currently, but in other
archs, it is not true. And the maximum LPC I/O address should be 64K
theoretically, although for compatible ISA, 2K is enough.
So, It means using PCIBIOS_MIN_IO on arm64 can match our I/O reservation
require. But we can not make this indirectIO work well on other architectures.

I am thinking Arnd's suggestion. But I worry about I haven't completely
understood his idea. What about create a new bus host for LPC/ISA whose I/O
range can be 64KB? This LPC/ISA I/O range works similar to PCI host bridge's I/O
window, all the downstream devices under LPC/ISA should request I/O from that
root resource. But it seems Arnd want this root resource registered dynamically,
I am not sure how to do...

Anyway, if we have this root I/O resource, we don't need any new macro or
variable for the LPC/ISA I/O reservation.

Hope my thought is right.

Best,
Zhichang


> The one good example for using PCIBIOS_MIN_IO is when your platform/architecture
> does not support legacy ISA operations *at all*. In that case someone
> sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O range
> so that it doesn't get used. With Zhichang's patch you now start forcing
> those platforms to have a valid address below PCIBIOS_MIN_IO.
> 
> For the general case you also have to bear in mind that PCIBIOS_MIN_IO could
> be zero. In that case, what is your "forbidden" range? [0, 0) ? So it makes
> sense to add a new #define that should only be defined by those architectures/
> platforms that want to reserve on top of PCIBIOS_MIN_IO another region
> where I/O tokens can't be generated for.
> 
> Best regards,
> Liviu
> 
>>
>>>
>>>>> Your current version has
>>>>>
>>>>>         if (arm64_extio_ops->pfout)                             \
>>>>>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>>>>>                        addr, value, sizeof(type));             \
>>>>>
>>>>> Instead, just subtract the start of the range from the logical
>>>>> port number to transform it back into a bus-local port number:
>>>>
>>>> These accessors do not operate on IO tokens:
>>>>
>>>> If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
>>>> addr is not going to be an I/O token; in fact patch 2/3 imposes that
>>>> the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
>>> PCIBIOS_MIN_IO
>>>> we have free physical addresses that the accessors can operate on.
>>>
>>> Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
>>> the logical I/O tokens, the purpose of that macro is really meant
>>> for allocating PCI I/O port numbers within the address space of
>>> one bus.
>>
>> As I mentioned above, special devices operate on CPU addresses directly,
>> not I/O tokens. For them there is no way to distinguish....
>>
>>>
>>> Note that it's equally likely that whichever next platform needs
>>> non-mapped I/O access like this actually needs them for PCI I/O space,
>>> and that will use it on addresses registered to a PCI host bridge.
>>
>> Ok so here you are talking about a platform that has got an I/O range
>> under the PCI host controller, right?
>> And this I/O range cannot be directly memory mapped but needs special
>> redirections for the I/O tokens, right?
>>
>> In this scenario registering the I/O ranges with the forbidden range
>> implemented by the current patch would still allow to redirect I/O
>> tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
>>
>> So effectively the special PCI host controller
>> 1) knows the physical range that needs special redirection
>> 2) register such range
>> 3) uses pci_pio_to_address() to retrieve the IO tokens for the
>>    special accessors
>> 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in 3)
>>
>> So to be honest I think this patch can fit well both with
>> special PCI controllers that need I/O tokens redirection and with
>> special non-PCI controllers that need non-PCI I/O physical
>> address redirection...
>>
>> Thanks (and sorry for the long reply but I didn't know how
>> to make the explanation shorter :) )
>>
>> Gab
>>
>>>
>>> If we separate the two steps:
>>>
>>> a) assign a range of logical I/O port numbers to a bus
>>> b) register a set of helpers for redirecting logical I/O
>>>    port to a helper function
>>>
>>> then I think the code will get cleaner and more flexible.
>>> It should actually then be able to replace the powerpc
>>> specific implementation.
>>>
>>> 	Arnd
> 

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 16:54                       ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-11 16:54 UTC (permalink / raw)
  To: liviu.dudau, Gabriele Paoloni
  Cc: mark.rutland, devicetree, bhelgaas@googl e.com,
	lorenzo.pieralisi, catalin.marinas, minyard, Arnd Bergmann,
	linux-pci, John Garry, will.deacon, linux-kernel, Yuanzhichang,
	Linuxarm, olof, robh+dt, xuwei (O),
	linux-serial, benh, zourongrong, kantyzc, linux-arm-kernel

Hi, Liviu,


On 11/11/2016 10:45 PM, liviu.dudau@arm.com wrote:
> On Fri, Nov 11, 2016 at 01:39:35PM +0000, Gabriele Paoloni wrote:
>> Hi Arnd
>>
>>> -----Original Message-----
>>> From: Arnd Bergmann [mailto:arnd@arndb.de]
>>> Sent: 10 November 2016 16:07
>>> To: Gabriele Paoloni
>>> Cc: linux-arm-kernel@lists.infradead.org; Yuanzhichang;
>>> mark.rutland@arm.com; devicetree@vger.kernel.org;
>>> lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
>>> benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
>>> kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
>>> robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
>>> catalin.marinas@arm.com; olof@lixom.net; liviu.dudau@arm.com;
>>> bhelgaas@googl e.com; zhichang.yuan02@gmail.com
>>> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
>>> Hip06
>>>
>>> On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
>>>>
>>>> Where should we get the range from? For LPC we know that it is going
>>>> Work on anything that is not used by PCI I/O space, and this is
>>>> why we use [0, PCIBIOS_MIN_IO]
>>>
>>> It should be allocated the same way we allocate PCI config space
>>> segments. This is currently done with the io_range list in
>>> drivers/pci/pci.c, which isn't perfect but could be extended
>>> if necessary. Based on what others commented here, I'd rather
>>> make the differences between ISA/LPC and PCI I/O ranges smaller
>>> than larger.
> 
> Gabriele,
> 
>>
>> I am not sure this would make sense...
>>
>> IMHO all the mechanism around io_range_list is needed to provide the
>> "mapping" between I/O tokens and physical CPU addresses.
>>
>> Currently the available tokens range from 0 to IO_SPACE_LIMIT.
>>
>> As you know the I/O memory accessors operate on whatever
>> __of_address_to_resource sets into the resource (start, end).
>>
>> With this special device in place we cannot know if a resource is
>> assigned with an I/O token or a physical address, unless we forbid
>> the I/O tokens to be in a specific range.
>>
>> So this is why we are changing the offsets of all the functions
>> handling io_range_list (to make sure that a range is forbidden to
>> the tokens and is available to the physical addresses).
>>
>> We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
>> because this is the maximum physical I/O range that a non PCI device
>> can operate on and because we believe this does not impose much
>> restriction on the available I/O token range; that now is 
>> [PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
>> So we believe that the chosen forbidden range can accommodate
>> any special ISA bus device with no much constraint on the rest
>> of I/O tokens...
> 
> Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and you
> actually need another variable for "reserving" an area in the I/O space
> that can be used for physical addresses rather than I/O tokens.
> 
I think selecting PCIBIOS_MIN_IO as the separator of mapped and non-mapped I/O
range probably is not so reasonable.
PCIBIOS_MIN_IN is specific to PCI devices, it seems as the recommended minimal
start I/O address when assigning the pci device I/O region. It is probably not
defined in some platforms/architectures when no PCI is needed there. That is why
my patch caused some compile error on some archs;

But more important thing is that the PCIBIOS_MIN_IO has different value on
different platforms/architectures. On Arm64, it is 4K currently, but in other
archs, it is not true. And the maximum LPC I/O address should be 64K
theoretically, although for compatible ISA, 2K is enough.
So, It means using PCIBIOS_MIN_IO on arm64 can match our I/O reservation
require. But we can not make this indirectIO work well on other architectures.

I am thinking Arnd's suggestion. But I worry about I haven't completely
understood his idea. What about create a new bus host for LPC/ISA whose I/O
range can be 64KB? This LPC/ISA I/O range works similar to PCI host bridge's I/O
window, all the downstream devices under LPC/ISA should request I/O from that
root resource. But it seems Arnd want this root resource registered dynamically,
I am not sure how to do...

Anyway, if we have this root I/O resource, we don't need any new macro or
variable for the LPC/ISA I/O reservation.

Hope my thought is right.

Best,
Zhichang


> The one good example for using PCIBIOS_MIN_IO is when your platform/architecture
> does not support legacy ISA operations *at all*. In that case someone
> sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O range
> so that it doesn't get used. With Zhichang's patch you now start forcing
> those platforms to have a valid address below PCIBIOS_MIN_IO.
> 
> For the general case you also have to bear in mind that PCIBIOS_MIN_IO could
> be zero. In that case, what is your "forbidden" range? [0, 0) ? So it makes
> sense to add a new #define that should only be defined by those architectures/
> platforms that want to reserve on top of PCIBIOS_MIN_IO another region
> where I/O tokens can't be generated for.
> 
> Best regards,
> Liviu
> 
>>
>>>
>>>>> Your current version has
>>>>>
>>>>>         if (arm64_extio_ops->pfout)                             \
>>>>>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>>>>>                        addr, value, sizeof(type));             \
>>>>>
>>>>> Instead, just subtract the start of the range from the logical
>>>>> port number to transform it back into a bus-local port number:
>>>>
>>>> These accessors do not operate on IO tokens:
>>>>
>>>> If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
>>>> addr is not going to be an I/O token; in fact patch 2/3 imposes that
>>>> the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
>>> PCIBIOS_MIN_IO
>>>> we have free physical addresses that the accessors can operate on.
>>>
>>> Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
>>> the logical I/O tokens, the purpose of that macro is really meant
>>> for allocating PCI I/O port numbers within the address space of
>>> one bus.
>>
>> As I mentioned above, special devices operate on CPU addresses directly,
>> not I/O tokens. For them there is no way to distinguish....
>>
>>>
>>> Note that it's equally likely that whichever next platform needs
>>> non-mapped I/O access like this actually needs them for PCI I/O space,
>>> and that will use it on addresses registered to a PCI host bridge.
>>
>> Ok so here you are talking about a platform that has got an I/O range
>> under the PCI host controller, right?
>> And this I/O range cannot be directly memory mapped but needs special
>> redirections for the I/O tokens, right?
>>
>> In this scenario registering the I/O ranges with the forbidden range
>> implemented by the current patch would still allow to redirect I/O
>> tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
>>
>> So effectively the special PCI host controller
>> 1) knows the physical range that needs special redirection
>> 2) register such range
>> 3) uses pci_pio_to_address() to retrieve the IO tokens for the
>>    special accessors
>> 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in 3)
>>
>> So to be honest I think this patch can fit well both with
>> special PCI controllers that need I/O tokens redirection and with
>> special non-PCI controllers that need non-PCI I/O physical
>> address redirection...
>>
>> Thanks (and sorry for the long reply but I didn't know how
>> to make the explanation shorter :) )
>>
>> Gab
>>
>>>
>>> If we separate the two steps:
>>>
>>> a) assign a range of logical I/O port numbers to a bus
>>> b) register a set of helpers for redirecting logical I/O
>>>    port to a helper function
>>>
>>> then I think the code will get cleaner and more flexible.
>>> It should actually then be able to replace the powerpc
>>> specific implementation.
>>>
>>> 	Arnd
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 16:54                       ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-11 16:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, Liviu,


On 11/11/2016 10:45 PM, liviu.dudau at arm.com wrote:
> On Fri, Nov 11, 2016 at 01:39:35PM +0000, Gabriele Paoloni wrote:
>> Hi Arnd
>>
>>> -----Original Message-----
>>> From: Arnd Bergmann [mailto:arnd at arndb.de]
>>> Sent: 10 November 2016 16:07
>>> To: Gabriele Paoloni
>>> Cc: linux-arm-kernel at lists.infradead.org; Yuanzhichang;
>>> mark.rutland at arm.com; devicetree at vger.kernel.org;
>>> lorenzo.pieralisi at arm.com; minyard at acm.org; linux-pci at vger.kernel.org;
>>> benh at kernel.crashing.org; John Garry; will.deacon at arm.com; linux-
>>> kernel at vger.kernel.org; xuwei (O); Linuxarm; zourongrong at gmail.com;
>>> robh+dt at kernel.org; kantyzc at 163.com; linux-serial at vger.kernel.org;
>>> catalin.marinas at arm.com; olof at lixom.net; liviu.dudau at arm.com;
>>> bhelgaas at googl e.com; zhichang.yuan02 at gmail.com
>>> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
>>> Hip06
>>>
>>> On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni wrote:
>>>>
>>>> Where should we get the range from? For LPC we know that it is going
>>>> Work on anything that is not used by PCI I/O space, and this is
>>>> why we use [0, PCIBIOS_MIN_IO]
>>>
>>> It should be allocated the same way we allocate PCI config space
>>> segments. This is currently done with the io_range list in
>>> drivers/pci/pci.c, which isn't perfect but could be extended
>>> if necessary. Based on what others commented here, I'd rather
>>> make the differences between ISA/LPC and PCI I/O ranges smaller
>>> than larger.
> 
> Gabriele,
> 
>>
>> I am not sure this would make sense...
>>
>> IMHO all the mechanism around io_range_list is needed to provide the
>> "mapping" between I/O tokens and physical CPU addresses.
>>
>> Currently the available tokens range from 0 to IO_SPACE_LIMIT.
>>
>> As you know the I/O memory accessors operate on whatever
>> __of_address_to_resource sets into the resource (start, end).
>>
>> With this special device in place we cannot know if a resource is
>> assigned with an I/O token or a physical address, unless we forbid
>> the I/O tokens to be in a specific range.
>>
>> So this is why we are changing the offsets of all the functions
>> handling io_range_list (to make sure that a range is forbidden to
>> the tokens and is available to the physical addresses).
>>
>> We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
>> because this is the maximum physical I/O range that a non PCI device
>> can operate on and because we believe this does not impose much
>> restriction on the available I/O token range; that now is 
>> [PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
>> So we believe that the chosen forbidden range can accommodate
>> any special ISA bus device with no much constraint on the rest
>> of I/O tokens...
> 
> Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and you
> actually need another variable for "reserving" an area in the I/O space
> that can be used for physical addresses rather than I/O tokens.
> 
I think selecting PCIBIOS_MIN_IO as the separator of mapped and non-mapped I/O
range probably is not so reasonable.
PCIBIOS_MIN_IN is specific to PCI devices, it seems as the recommended minimal
start I/O address when assigning the pci device I/O region. It is probably not
defined in some platforms/architectures when no PCI is needed there. That is why
my patch caused some compile error on some archs;

But more important thing is that the PCIBIOS_MIN_IO has different value on
different platforms/architectures. On Arm64, it is 4K currently, but in other
archs, it is not true. And the maximum LPC I/O address should be 64K
theoretically, although for compatible ISA, 2K is enough.
So, It means using PCIBIOS_MIN_IO on arm64 can match our I/O reservation
require. But we can not make this indirectIO work well on other architectures.

I am thinking Arnd's suggestion. But I worry about I haven't completely
understood his idea. What about create a new bus host for LPC/ISA whose I/O
range can be 64KB? This LPC/ISA I/O range works similar to PCI host bridge's I/O
window, all the downstream devices under LPC/ISA should request I/O from that
root resource. But it seems Arnd want this root resource registered dynamically,
I am not sure how to do...

Anyway, if we have this root I/O resource, we don't need any new macro or
variable for the LPC/ISA I/O reservation.

Hope my thought is right.

Best,
Zhichang


> The one good example for using PCIBIOS_MIN_IO is when your platform/architecture
> does not support legacy ISA operations *at all*. In that case someone
> sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O range
> so that it doesn't get used. With Zhichang's patch you now start forcing
> those platforms to have a valid address below PCIBIOS_MIN_IO.
> 
> For the general case you also have to bear in mind that PCIBIOS_MIN_IO could
> be zero. In that case, what is your "forbidden" range? [0, 0) ? So it makes
> sense to add a new #define that should only be defined by those architectures/
> platforms that want to reserve on top of PCIBIOS_MIN_IO another region
> where I/O tokens can't be generated for.
> 
> Best regards,
> Liviu
> 
>>
>>>
>>>>> Your current version has
>>>>>
>>>>>         if (arm64_extio_ops->pfout)                             \
>>>>>                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>>>>>                        addr, value, sizeof(type));             \
>>>>>
>>>>> Instead, just subtract the start of the range from the logical
>>>>> port number to transform it back into a bus-local port number:
>>>>
>>>> These accessors do not operate on IO tokens:
>>>>
>>>> If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
>>>> addr is not going to be an I/O token; in fact patch 2/3 imposes that
>>>> the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
>>> PCIBIOS_MIN_IO
>>>> we have free physical addresses that the accessors can operate on.
>>>
>>> Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer to
>>> the logical I/O tokens, the purpose of that macro is really meant
>>> for allocating PCI I/O port numbers within the address space of
>>> one bus.
>>
>> As I mentioned above, special devices operate on CPU addresses directly,
>> not I/O tokens. For them there is no way to distinguish....
>>
>>>
>>> Note that it's equally likely that whichever next platform needs
>>> non-mapped I/O access like this actually needs them for PCI I/O space,
>>> and that will use it on addresses registered to a PCI host bridge.
>>
>> Ok so here you are talking about a platform that has got an I/O range
>> under the PCI host controller, right?
>> And this I/O range cannot be directly memory mapped but needs special
>> redirections for the I/O tokens, right?
>>
>> In this scenario registering the I/O ranges with the forbidden range
>> implemented by the current patch would still allow to redirect I/O
>> tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
>>
>> So effectively the special PCI host controller
>> 1) knows the physical range that needs special redirection
>> 2) register such range
>> 3) uses pci_pio_to_address() to retrieve the IO tokens for the
>>    special accessors
>> 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in 3)
>>
>> So to be honest I think this patch can fit well both with
>> special PCI controllers that need I/O tokens redirection and with
>> special non-PCI controllers that need non-PCI I/O physical
>> address redirection...
>>
>> Thanks (and sorry for the long reply but I didn't know how
>> to make the explanation shorter :) )
>>
>> Gab
>>
>>>
>>> If we separate the two steps:
>>>
>>> a) assign a range of logical I/O port numbers to a bus
>>> b) register a set of helpers for redirecting logical I/O
>>>    port to a helper function
>>>
>>> then I think the code will get cleaner and more flexible.
>>> It should actually then be able to replace the powerpc
>>> specific implementation.
>>>
>>> 	Arnd
> 

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-11 15:53                       ` Gabriele Paoloni
  (?)
  (?)
@ 2016-11-11 18:16                         ` liviu.dudau
  -1 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau @ 2016-11-11 18:16 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Arnd Bergmann, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, bhelgaas@googl e.com, zhichang.yuan02

On Fri, Nov 11, 2016 at 03:53:53PM +0000, Gabriele Paoloni wrote:
> Hi Liviu

Hi Gabriele,

> 
> > -----Original Message-----
> > From: liviu.dudau@arm.com [mailto:liviu.dudau@arm.com]
> > Sent: 11 November 2016 14:46
> > To: Gabriele Paoloni
> > Cc: Arnd Bergmann; linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> > mark.rutland@arm.com; devicetree@vger.kernel.org;
> > lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> > benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> > kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> > robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> > catalin.marinas@arm.com; olof@lixom.net; bhelgaas@googl e.com;
> > zhichang.yuan02@gmail.com
> > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> > Hip06
> > 
> > On Fri, Nov 11, 2016 at 01:39:35PM +0000, Gabriele Paoloni wrote:
> > > Hi Arnd
> > >
> > > > -----Original Message-----
> > > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > Sent: 10 November 2016 16:07
> > > > To: Gabriele Paoloni
> > > > Cc: linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> > > > mark.rutland@arm.com; devicetree@vger.kernel.org;
> > > > lorenzo.pieralisi@arm.com; minyard@acm.org; linux-
> > pci@vger.kernel.org;
> > > > benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> > > > kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> > > > robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> > > > catalin.marinas@arm.com; olof@lixom.net; liviu.dudau@arm.com;
> > > > bhelgaas@googl e.com; zhichang.yuan02@gmail.com
> > > > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> > > > Hip06
> > > >
> > > > On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni
> > wrote:
> > > > >
> > > > > Where should we get the range from? For LPC we know that it is
> > going
> > > > > Work on anything that is not used by PCI I/O space, and this is
> > > > > why we use [0, PCIBIOS_MIN_IO]
> > > >
> > > > It should be allocated the same way we allocate PCI config space
> > > > segments. This is currently done with the io_range list in
> > > > drivers/pci/pci.c, which isn't perfect but could be extended
> > > > if necessary. Based on what others commented here, I'd rather
> > > > make the differences between ISA/LPC and PCI I/O ranges smaller
> > > > than larger.
> > 
> > Gabriele,
> > 
> > >
> > > I am not sure this would make sense...
> > >
> > > IMHO all the mechanism around io_range_list is needed to provide the
> > > "mapping" between I/O tokens and physical CPU addresses.
> > >
> > > Currently the available tokens range from 0 to IO_SPACE_LIMIT.
> > >
> > > As you know the I/O memory accessors operate on whatever
> > > __of_address_to_resource sets into the resource (start, end).
> > >
> > > With this special device in place we cannot know if a resource is
> > > assigned with an I/O token or a physical address, unless we forbid
> > > the I/O tokens to be in a specific range.
> > >
> > > So this is why we are changing the offsets of all the functions
> > > handling io_range_list (to make sure that a range is forbidden to
> > > the tokens and is available to the physical addresses).
> > >
> > > We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
> > > because this is the maximum physical I/O range that a non PCI device
> > > can operate on and because we believe this does not impose much
> > > restriction on the available I/O token range; that now is
> > > [PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
> > > So we believe that the chosen forbidden range can accommodate
> > > any special ISA bus device with no much constraint on the rest
> > > of I/O tokens...
> > 
> > Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and you
> > actually need another variable for "reserving" an area in the I/O space
> > that can be used for physical addresses rather than I/O tokens.
> > 
> > The one good example for using PCIBIOS_MIN_IO is when your
> > platform/architecture
> > does not support legacy ISA operations *at all*. In that case someone
> > sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O range
> > so that it doesn't get used. With Zhichang's patch you now start
> > forcing
> > those platforms to have a valid address below PCIBIOS_MIN_IO.
> 
> But if PCIBIOS_MIN_IO is 0 then it means that all I/O space is to be used
> by PCI controllers only...

Nope, that is not what it means. It means that PCI devices can see I/O addresses
on the bus that start from 0. There never was any usage for non-PCI controllers
when PCIBIOS_MIN_IO != 0. That is what Zhichang is trying to do now and what
I think is not the right thing (and not enough anyway).

> so if you have a special bus device using
> an I/O range in this case should be a PCI controller...

That has always been the case. It is this series that wants to introduce the
new meaning.

> i.e. I would
> expect it to fall back into the case of I/O tokens redirection rather than
> physical addresses redirection (as mentioned below from my previous reply).
> What do you think?

I think you have looked too much at the code *with* Zhichang's patches applied.
Take a step back and look at how PCIBIOS_MIN_IO is used now, before you apply
the patches. It is all about PCI addresses and there is no notion of non-PCI
busses using PCI framework. Only platforms and architectures that try to work
around some legacy standards (ISA) or HW restrictions.

Best regards,
Liviu

> 
> Thanks
> 
> Gab
> 
> 
> > 
> > For the general case you also have to bear in mind that PCIBIOS_MIN_IO
> > could
> > be zero. In that case, what is your "forbidden" range? [0, 0) ? So it
> > makes
> > sense to add a new #define that should only be defined by those
> > architectures/
> > platforms that want to reserve on top of PCIBIOS_MIN_IO another region
> > where I/O tokens can't be generated for.
> > 
> > Best regards,
> > Liviu
> > 
> > >
> > > >
> > > > > > Your current version has
> > > > > >
> > > > > >         if (arm64_extio_ops->pfout)
> > \
> > > > > >                 arm64_extio_ops->pfout(arm64_extio_ops-
> > >devpara,\
> > > > > >                        addr, value, sizeof(type));
> > \
> > > > > >
> > > > > > Instead, just subtract the start of the range from the logical
> > > > > > port number to transform it back into a bus-local port number:
> > > > >
> > > > > These accessors do not operate on IO tokens:
> > > > >
> > > > > If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> > > > > addr is not going to be an I/O token; in fact patch 2/3 imposes
> > that
> > > > > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> > > > PCIBIOS_MIN_IO
> > > > > we have free physical addresses that the accessors can operate
> > on.
> > > >
> > > > Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer
> > to
> > > > the logical I/O tokens, the purpose of that macro is really meant
> > > > for allocating PCI I/O port numbers within the address space of
> > > > one bus.
> > >
> > > As I mentioned above, special devices operate on CPU addresses
> > directly,
> > > not I/O tokens. For them there is no way to distinguish....
> > >
> > > >
> > > > Note that it's equally likely that whichever next platform needs
> > > > non-mapped I/O access like this actually needs them for PCI I/O
> > space,
> > > > and that will use it on addresses registered to a PCI host bridge.
> > >
> > > Ok so here you are talking about a platform that has got an I/O range
> > > under the PCI host controller, right?
> > > And this I/O range cannot be directly memory mapped but needs special
> > > redirections for the I/O tokens, right?
> > >
> > > In this scenario registering the I/O ranges with the forbidden range
> > > implemented by the current patch would still allow to redirect I/O
> > > tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
> > >
> > > So effectively the special PCI host controller
> > > 1) knows the physical range that needs special redirection
> > > 2) register such range
> > > 3) uses pci_pio_to_address() to retrieve the IO tokens for the
> > >    special accessors
> > > 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in 3)
> > >
> > > So to be honest I think this patch can fit well both with
> > > special PCI controllers that need I/O tokens redirection and with
> > > special non-PCI controllers that need non-PCI I/O physical
> > > address redirection...
> > >
> > > Thanks (and sorry for the long reply but I didn't know how
> > > to make the explanation shorter :) )
> > >
> > > Gab
> > >
> > > >
> > > > If we separate the two steps:
> > > >
> > > > a) assign a range of logical I/O port numbers to a bus
> > > > b) register a set of helpers for redirecting logical I/O
> > > >    port to a helper function
> > > >
> > > > then I think the code will get cleaner and more flexible.
> > > > It should actually then be able to replace the powerpc
> > > > specific implementation.
> > > >
> > > > 	Arnd
> > 
> > --
> > ====================
> > | I would like to |
> > | fix the world,  |
> > | but they're not |
> > | giving me the   |
> >  \ source code!  /
> >   ---------------
> >     ¯\_(ツ)_/¯

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

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 18:16                         ` liviu.dudau
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau @ 2016-11-11 18:16 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: mark.rutland, benh, catalin.marinas, will.deacon, Linuxarm,
	lorenzo.pieralisi, Arnd Bergmann, xuwei (O),
	linux-serial, linux-pci, devicetree, minyard, John Garry,
	zourongrong, robh+dt, bhelgaas@googl e.com, kantyzc,
	zhichang.yuan02, linux-arm-kernel

On Fri, Nov 11, 2016 at 03:53:53PM +0000, Gabriele Paoloni wrote:
> Hi Liviu

Hi Gabriele,

> 
> > -----Original Message-----
> > From: liviu.dudau@arm.com [mailto:liviu.dudau@arm.com]
> > Sent: 11 November 2016 14:46
> > To: Gabriele Paoloni
> > Cc: Arnd Bergmann; linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> > mark.rutland@arm.com; devicetree@vger.kernel.org;
> > lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> > benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> > kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> > robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> > catalin.marinas@arm.com; olof@lixom.net; bhelgaas@googl e.com;
> > zhichang.yuan02@gmail.com
> > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> > Hip06
> > 
> > On Fri, Nov 11, 2016 at 01:39:35PM +0000, Gabriele Paoloni wrote:
> > > Hi Arnd
> > >
> > > > -----Original Message-----
> > > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > Sent: 10 November 2016 16:07
> > > > To: Gabriele Paoloni
> > > > Cc: linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> > > > mark.rutland@arm.com; devicetree@vger.kernel.org;
> > > > lorenzo.pieralisi@arm.com; minyard@acm.org; linux-
> > pci@vger.kernel.org;
> > > > benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> > > > kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> > > > robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> > > > catalin.marinas@arm.com; olof@lixom.net; liviu.dudau@arm.com;
> > > > bhelgaas@googl e.com; zhichang.yuan02@gmail.com
> > > > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> > > > Hip06
> > > >
> > > > On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni
> > wrote:
> > > > >
> > > > > Where should we get the range from? For LPC we know that it is
> > going
> > > > > Work on anything that is not used by PCI I/O space, and this is
> > > > > why we use [0, PCIBIOS_MIN_IO]
> > > >
> > > > It should be allocated the same way we allocate PCI config space
> > > > segments. This is currently done with the io_range list in
> > > > drivers/pci/pci.c, which isn't perfect but could be extended
> > > > if necessary. Based on what others commented here, I'd rather
> > > > make the differences between ISA/LPC and PCI I/O ranges smaller
> > > > than larger.
> > 
> > Gabriele,
> > 
> > >
> > > I am not sure this would make sense...
> > >
> > > IMHO all the mechanism around io_range_list is needed to provide the
> > > "mapping" between I/O tokens and physical CPU addresses.
> > >
> > > Currently the available tokens range from 0 to IO_SPACE_LIMIT.
> > >
> > > As you know the I/O memory accessors operate on whatever
> > > __of_address_to_resource sets into the resource (start, end).
> > >
> > > With this special device in place we cannot know if a resource is
> > > assigned with an I/O token or a physical address, unless we forbid
> > > the I/O tokens to be in a specific range.
> > >
> > > So this is why we are changing the offsets of all the functions
> > > handling io_range_list (to make sure that a range is forbidden to
> > > the tokens and is available to the physical addresses).
> > >
> > > We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
> > > because this is the maximum physical I/O range that a non PCI device
> > > can operate on and because we believe this does not impose much
> > > restriction on the available I/O token range; that now is
> > > [PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
> > > So we believe that the chosen forbidden range can accommodate
> > > any special ISA bus device with no much constraint on the rest
> > > of I/O tokens...
> > 
> > Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and you
> > actually need another variable for "reserving" an area in the I/O space
> > that can be used for physical addresses rather than I/O tokens.
> > 
> > The one good example for using PCIBIOS_MIN_IO is when your
> > platform/architecture
> > does not support legacy ISA operations *at all*. In that case someone
> > sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O range
> > so that it doesn't get used. With Zhichang's patch you now start
> > forcing
> > those platforms to have a valid address below PCIBIOS_MIN_IO.
> 
> But if PCIBIOS_MIN_IO is 0 then it means that all I/O space is to be used
> by PCI controllers only...

Nope, that is not what it means. It means that PCI devices can see I/O addresses
on the bus that start from 0. There never was any usage for non-PCI controllers
when PCIBIOS_MIN_IO != 0. That is what Zhichang is trying to do now and what
I think is not the right thing (and not enough anyway).

> so if you have a special bus device using
> an I/O range in this case should be a PCI controller...

That has always been the case. It is this series that wants to introduce the
new meaning.

> i.e. I would
> expect it to fall back into the case of I/O tokens redirection rather than
> physical addresses redirection (as mentioned below from my previous reply).
> What do you think?

I think you have looked too much at the code *with* Zhichang's patches applied.
Take a step back and look at how PCIBIOS_MIN_IO is used now, before you apply
the patches. It is all about PCI addresses and there is no notion of non-PCI
busses using PCI framework. Only platforms and architectures that try to work
around some legacy standards (ISA) or HW restrictions.

Best regards,
Liviu

> 
> Thanks
> 
> Gab
> 
> 
> > 
> > For the general case you also have to bear in mind that PCIBIOS_MIN_IO
> > could
> > be zero. In that case, what is your "forbidden" range? [0, 0) ? So it
> > makes
> > sense to add a new #define that should only be defined by those
> > architectures/
> > platforms that want to reserve on top of PCIBIOS_MIN_IO another region
> > where I/O tokens can't be generated for.
> > 
> > Best regards,
> > Liviu
> > 
> > >
> > > >
> > > > > > Your current version has
> > > > > >
> > > > > >         if (arm64_extio_ops->pfout)
> > \
> > > > > >                 arm64_extio_ops->pfout(arm64_extio_ops-
> > >devpara,\
> > > > > >                        addr, value, sizeof(type));
> > \
> > > > > >
> > > > > > Instead, just subtract the start of the range from the logical
> > > > > > port number to transform it back into a bus-local port number:
> > > > >
> > > > > These accessors do not operate on IO tokens:
> > > > >
> > > > > If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> > > > > addr is not going to be an I/O token; in fact patch 2/3 imposes
> > that
> > > > > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> > > > PCIBIOS_MIN_IO
> > > > > we have free physical addresses that the accessors can operate
> > on.
> > > >
> > > > Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer
> > to
> > > > the logical I/O tokens, the purpose of that macro is really meant
> > > > for allocating PCI I/O port numbers within the address space of
> > > > one bus.
> > >
> > > As I mentioned above, special devices operate on CPU addresses
> > directly,
> > > not I/O tokens. For them there is no way to distinguish....
> > >
> > > >
> > > > Note that it's equally likely that whichever next platform needs
> > > > non-mapped I/O access like this actually needs them for PCI I/O
> > space,
> > > > and that will use it on addresses registered to a PCI host bridge.
> > >
> > > Ok so here you are talking about a platform that has got an I/O range
> > > under the PCI host controller, right?
> > > And this I/O range cannot be directly memory mapped but needs special
> > > redirections for the I/O tokens, right?
> > >
> > > In this scenario registering the I/O ranges with the forbidden range
> > > implemented by the current patch would still allow to redirect I/O
> > > tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
> > >
> > > So effectively the special PCI host controller
> > > 1) knows the physical range that needs special redirection
> > > 2) register such range
> > > 3) uses pci_pio_to_address() to retrieve the IO tokens for the
> > >    special accessors
> > > 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in 3)
> > >
> > > So to be honest I think this patch can fit well both with
> > > special PCI controllers that need I/O tokens redirection and with
> > > special non-PCI controllers that need non-PCI I/O physical
> > > address redirection...
> > >
> > > Thanks (and sorry for the long reply but I didn't know how
> > > to make the explanation shorter :) )
> > >
> > > Gab
> > >
> > > >
> > > > If we separate the two steps:
> > > >
> > > > a) assign a range of logical I/O port numbers to a bus
> > > > b) register a set of helpers for redirecting logical I/O
> > > >    port to a helper function
> > > >
> > > > then I think the code will get cleaner and more flexible.
> > > > It should actually then be able to replace the powerpc
> > > > specific implementation.
> > > >
> > > > 	Arnd
> > 
> > --
> > ====================
> > | I would like to |
> > | fix the world,  |
> > | but they're not |
> > | giving me the   |
> >  \ source code!  /
> >   ---------------
> >     ¯\_(ツ)_/¯

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

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 18:16                         ` liviu.dudau
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau @ 2016-11-11 18:16 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Arnd Bergmann, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, bhelgaas@googl e.com, zhichang.yuan02

On Fri, Nov 11, 2016 at 03:53:53PM +0000, Gabriele Paoloni wrote:
> Hi Liviu

Hi Gabriele,

> 
> > -----Original Message-----
> > From: liviu.dudau@arm.com [mailto:liviu.dudau@arm.com]
> > Sent: 11 November 2016 14:46
> > To: Gabriele Paoloni
> > Cc: Arnd Bergmann; linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> > mark.rutland@arm.com; devicetree@vger.kernel.org;
> > lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> > benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> > kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> > robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> > catalin.marinas@arm.com; olof@lixom.net; bhelgaas@googl e.com;
> > zhichang.yuan02@gmail.com
> > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> > Hip06
> > 
> > On Fri, Nov 11, 2016 at 01:39:35PM +0000, Gabriele Paoloni wrote:
> > > Hi Arnd
> > >
> > > > -----Original Message-----
> > > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > Sent: 10 November 2016 16:07
> > > > To: Gabriele Paoloni
> > > > Cc: linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> > > > mark.rutland@arm.com; devicetree@vger.kernel.org;
> > > > lorenzo.pieralisi@arm.com; minyard@acm.org; linux-
> > pci@vger.kernel.org;
> > > > benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> > > > kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> > > > robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> > > > catalin.marinas@arm.com; olof@lixom.net; liviu.dudau@arm.com;
> > > > bhelgaas@googl e.com; zhichang.yuan02@gmail.com
> > > > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> > > > Hip06
> > > >
> > > > On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni
> > wrote:
> > > > >
> > > > > Where should we get the range from? For LPC we know that it is
> > going
> > > > > Work on anything that is not used by PCI I/O space, and this is
> > > > > why we use [0, PCIBIOS_MIN_IO]
> > > >
> > > > It should be allocated the same way we allocate PCI config space
> > > > segments. This is currently done with the io_range list in
> > > > drivers/pci/pci.c, which isn't perfect but could be extended
> > > > if necessary. Based on what others commented here, I'd rather
> > > > make the differences between ISA/LPC and PCI I/O ranges smaller
> > > > than larger.
> > 
> > Gabriele,
> > 
> > >
> > > I am not sure this would make sense...
> > >
> > > IMHO all the mechanism around io_range_list is needed to provide the
> > > "mapping" between I/O tokens and physical CPU addresses.
> > >
> > > Currently the available tokens range from 0 to IO_SPACE_LIMIT.
> > >
> > > As you know the I/O memory accessors operate on whatever
> > > __of_address_to_resource sets into the resource (start, end).
> > >
> > > With this special device in place we cannot know if a resource is
> > > assigned with an I/O token or a physical address, unless we forbid
> > > the I/O tokens to be in a specific range.
> > >
> > > So this is why we are changing the offsets of all the functions
> > > handling io_range_list (to make sure that a range is forbidden to
> > > the tokens and is available to the physical addresses).
> > >
> > > We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
> > > because this is the maximum physical I/O range that a non PCI device
> > > can operate on and because we believe this does not impose much
> > > restriction on the available I/O token range; that now is
> > > [PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
> > > So we believe that the chosen forbidden range can accommodate
> > > any special ISA bus device with no much constraint on the rest
> > > of I/O tokens...
> > 
> > Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and you
> > actually need another variable for "reserving" an area in the I/O space
> > that can be used for physical addresses rather than I/O tokens.
> > 
> > The one good example for using PCIBIOS_MIN_IO is when your
> > platform/architecture
> > does not support legacy ISA operations *at all*. In that case someone
> > sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O range
> > so that it doesn't get used. With Zhichang's patch you now start
> > forcing
> > those platforms to have a valid address below PCIBIOS_MIN_IO.
> 
> But if PCIBIOS_MIN_IO is 0 then it means that all I/O space is to be used
> by PCI controllers only...

Nope, that is not what it means. It means that PCI devices can see I/O addresses
on the bus that start from 0. There never was any usage for non-PCI controllers
when PCIBIOS_MIN_IO != 0. That is what Zhichang is trying to do now and what
I think is not the right thing (and not enough anyway).

> so if you have a special bus device using
> an I/O range in this case should be a PCI controller...

That has always been the case. It is this series that wants to introduce the
new meaning.

> i.e. I would
> expect it to fall back into the case of I/O tokens redirection rather than
> physical addresses redirection (as mentioned below from my previous reply).
> What do you think?

I think you have looked too much at the code *with* Zhichang's patches applied.
Take a step back and look at how PCIBIOS_MIN_IO is used now, before you apply
the patches. It is all about PCI addresses and there is no notion of non-PCI
busses using PCI framework. Only platforms and architectures that try to work
around some legacy standards (ISA) or HW restrictions.

Best regards,
Liviu

> 
> Thanks
> 
> Gab
> 
> 
> > 
> > For the general case you also have to bear in mind that PCIBIOS_MIN_IO
> > could
> > be zero. In that case, what is your "forbidden" range? [0, 0) ? So it
> > makes
> > sense to add a new #define that should only be defined by those
> > architectures/
> > platforms that want to reserve on top of PCIBIOS_MIN_IO another region
> > where I/O tokens can't be generated for.
> > 
> > Best regards,
> > Liviu
> > 
> > >
> > > >
> > > > > > Your current version has
> > > > > >
> > > > > >         if (arm64_extio_ops->pfout)
> > \
> > > > > >                 arm64_extio_ops->pfout(arm64_extio_ops-
> > >devpara,\
> > > > > >                        addr, value, sizeof(type));
> > \
> > > > > >
> > > > > > Instead, just subtract the start of the range from the logical
> > > > > > port number to transform it back into a bus-local port number:
> > > > >
> > > > > These accessors do not operate on IO tokens:
> > > > >
> > > > > If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> > > > > addr is not going to be an I/O token; in fact patch 2/3 imposes
> > that
> > > > > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> > > > PCIBIOS_MIN_IO
> > > > > we have free physical addresses that the accessors can operate
> > on.
> > > >
> > > > Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer
> > to
> > > > the logical I/O tokens, the purpose of that macro is really meant
> > > > for allocating PCI I/O port numbers within the address space of
> > > > one bus.
> > >
> > > As I mentioned above, special devices operate on CPU addresses
> > directly,
> > > not I/O tokens. For them there is no way to distinguish....
> > >
> > > >
> > > > Note that it's equally likely that whichever next platform needs
> > > > non-mapped I/O access like this actually needs them for PCI I/O
> > space,
> > > > and that will use it on addresses registered to a PCI host bridge.
> > >
> > > Ok so here you are talking about a platform that has got an I/O range
> > > under the PCI host controller, right?
> > > And this I/O range cannot be directly memory mapped but needs special
> > > redirections for the I/O tokens, right?
> > >
> > > In this scenario registering the I/O ranges with the forbidden range
> > > implemented by the current patch would still allow to redirect I/O
> > > tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
> > >
> > > So effectively the special PCI host controller
> > > 1) knows the physical range that needs special redirection
> > > 2) register such range
> > > 3) uses pci_pio_to_address() to retrieve the IO tokens for the
> > >    special accessors
> > > 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in 3)
> > >
> > > So to be honest I think this patch can fit well both with
> > > special PCI controllers that need I/O tokens redirection and with
> > > special non-PCI controllers that need non-PCI I/O physical
> > > address redirection...
> > >
> > > Thanks (and sorry for the long reply but I didn't know how
> > > to make the explanation shorter :) )
> > >
> > > Gab
> > >
> > > >
> > > > If we separate the two steps:
> > > >
> > > > a) assign a range of logical I/O port numbers to a bus
> > > > b) register a set of helpers for redirecting logical I/O
> > > >    port to a helper function
> > > >
> > > > then I think the code will get cleaner and more flexible.
> > > > It should actually then be able to replace the powerpc
> > > > specific implementation.
> > > >
> > > > 	Arnd
> > 
> > --
> > ====================
> > | I would like to |
> > | fix the world,  |
> > | but they're not |
> > | giving me the   |
> >  \ source code!  /
> >   ---------------
> >     ¯\_(ツ)_/¯

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

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-11 18:16                         ` liviu.dudau
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau at arm.com @ 2016-11-11 18:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Nov 11, 2016 at 03:53:53PM +0000, Gabriele Paoloni wrote:
> Hi Liviu

Hi Gabriele,

> 
> > -----Original Message-----
> > From: liviu.dudau at arm.com [mailto:liviu.dudau at arm.com]
> > Sent: 11 November 2016 14:46
> > To: Gabriele Paoloni
> > Cc: Arnd Bergmann; linux-arm-kernel at lists.infradead.org; Yuanzhichang;
> > mark.rutland at arm.com; devicetree at vger.kernel.org;
> > lorenzo.pieralisi at arm.com; minyard at acm.org; linux-pci at vger.kernel.org;
> > benh at kernel.crashing.org; John Garry; will.deacon at arm.com; linux-
> > kernel at vger.kernel.org; xuwei (O); Linuxarm; zourongrong at gmail.com;
> > robh+dt at kernel.org; kantyzc at 163.com; linux-serial at vger.kernel.org;
> > catalin.marinas at arm.com; olof at lixom.net; bhelgaas at googl e.com;
> > zhichang.yuan02 at gmail.com
> > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> > Hip06
> > 
> > On Fri, Nov 11, 2016 at 01:39:35PM +0000, Gabriele Paoloni wrote:
> > > Hi Arnd
> > >
> > > > -----Original Message-----
> > > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > > Sent: 10 November 2016 16:07
> > > > To: Gabriele Paoloni
> > > > Cc: linux-arm-kernel at lists.infradead.org; Yuanzhichang;
> > > > mark.rutland at arm.com; devicetree at vger.kernel.org;
> > > > lorenzo.pieralisi at arm.com; minyard at acm.org; linux-
> > pci at vger.kernel.org;
> > > > benh at kernel.crashing.org; John Garry; will.deacon at arm.com; linux-
> > > > kernel at vger.kernel.org; xuwei (O); Linuxarm; zourongrong at gmail.com;
> > > > robh+dt at kernel.org; kantyzc at 163.com; linux-serial at vger.kernel.org;
> > > > catalin.marinas at arm.com; olof at lixom.net; liviu.dudau at arm.com;
> > > > bhelgaas at googl e.com; zhichang.yuan02 at gmail.com
> > > > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> > > > Hip06
> > > >
> > > > On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni
> > wrote:
> > > > >
> > > > > Where should we get the range from? For LPC we know that it is
> > going
> > > > > Work on anything that is not used by PCI I/O space, and this is
> > > > > why we use [0, PCIBIOS_MIN_IO]
> > > >
> > > > It should be allocated the same way we allocate PCI config space
> > > > segments. This is currently done with the io_range list in
> > > > drivers/pci/pci.c, which isn't perfect but could be extended
> > > > if necessary. Based on what others commented here, I'd rather
> > > > make the differences between ISA/LPC and PCI I/O ranges smaller
> > > > than larger.
> > 
> > Gabriele,
> > 
> > >
> > > I am not sure this would make sense...
> > >
> > > IMHO all the mechanism around io_range_list is needed to provide the
> > > "mapping" between I/O tokens and physical CPU addresses.
> > >
> > > Currently the available tokens range from 0 to IO_SPACE_LIMIT.
> > >
> > > As you know the I/O memory accessors operate on whatever
> > > __of_address_to_resource sets into the resource (start, end).
> > >
> > > With this special device in place we cannot know if a resource is
> > > assigned with an I/O token or a physical address, unless we forbid
> > > the I/O tokens to be in a specific range.
> > >
> > > So this is why we are changing the offsets of all the functions
> > > handling io_range_list (to make sure that a range is forbidden to
> > > the tokens and is available to the physical addresses).
> > >
> > > We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
> > > because this is the maximum physical I/O range that a non PCI device
> > > can operate on and because we believe this does not impose much
> > > restriction on the available I/O token range; that now is
> > > [PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
> > > So we believe that the chosen forbidden range can accommodate
> > > any special ISA bus device with no much constraint on the rest
> > > of I/O tokens...
> > 
> > Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and you
> > actually need another variable for "reserving" an area in the I/O space
> > that can be used for physical addresses rather than I/O tokens.
> > 
> > The one good example for using PCIBIOS_MIN_IO is when your
> > platform/architecture
> > does not support legacy ISA operations *at all*. In that case someone
> > sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O range
> > so that it doesn't get used. With Zhichang's patch you now start
> > forcing
> > those platforms to have a valid address below PCIBIOS_MIN_IO.
> 
> But if PCIBIOS_MIN_IO is 0 then it means that all I/O space is to be used
> by PCI controllers only...

Nope, that is not what it means. It means that PCI devices can see I/O addresses
on the bus that start from 0. There never was any usage for non-PCI controllers
when PCIBIOS_MIN_IO != 0. That is what Zhichang is trying to do now and what
I think is not the right thing (and not enough anyway).

> so if you have a special bus device using
> an I/O range in this case should be a PCI controller...

That has always been the case. It is this series that wants to introduce the
new meaning.

> i.e. I would
> expect it to fall back into the case of I/O tokens redirection rather than
> physical addresses redirection (as mentioned below from my previous reply).
> What do you think?

I think you have looked too much at the code *with* Zhichang's patches applied.
Take a step back and look at how PCIBIOS_MIN_IO is used now, before you apply
the patches. It is all about PCI addresses and there is no notion of non-PCI
busses using PCI framework. Only platforms and architectures that try to work
around some legacy standards (ISA) or HW restrictions.

Best regards,
Liviu

> 
> Thanks
> 
> Gab
> 
> 
> > 
> > For the general case you also have to bear in mind that PCIBIOS_MIN_IO
> > could
> > be zero. In that case, what is your "forbidden" range? [0, 0) ? So it
> > makes
> > sense to add a new #define that should only be defined by those
> > architectures/
> > platforms that want to reserve on top of PCIBIOS_MIN_IO another region
> > where I/O tokens can't be generated for.
> > 
> > Best regards,
> > Liviu
> > 
> > >
> > > >
> > > > > > Your current version has
> > > > > >
> > > > > >         if (arm64_extio_ops->pfout)
> > \
> > > > > >                 arm64_extio_ops->pfout(arm64_extio_ops-
> > >devpara,\
> > > > > >                        addr, value, sizeof(type));
> > \
> > > > > >
> > > > > > Instead, just subtract the start of the range from the logical
> > > > > > port number to transform it back into a bus-local port number:
> > > > >
> > > > > These accessors do not operate on IO tokens:
> > > > >
> > > > > If (arm64_extio_ops->start > addr || arm64_extio_ops->end < addr)
> > > > > addr is not going to be an I/O token; in fact patch 2/3 imposes
> > that
> > > > > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> > > > PCIBIOS_MIN_IO
> > > > > we have free physical addresses that the accessors can operate
> > on.
> > > >
> > > > Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to refer
> > to
> > > > the logical I/O tokens, the purpose of that macro is really meant
> > > > for allocating PCI I/O port numbers within the address space of
> > > > one bus.
> > >
> > > As I mentioned above, special devices operate on CPU addresses
> > directly,
> > > not I/O tokens. For them there is no way to distinguish....
> > >
> > > >
> > > > Note that it's equally likely that whichever next platform needs
> > > > non-mapped I/O access like this actually needs them for PCI I/O
> > space,
> > > > and that will use it on addresses registered to a PCI host bridge.
> > >
> > > Ok so here you are talking about a platform that has got an I/O range
> > > under the PCI host controller, right?
> > > And this I/O range cannot be directly memory mapped but needs special
> > > redirections for the I/O tokens, right?
> > >
> > > In this scenario registering the I/O ranges with the forbidden range
> > > implemented by the current patch would still allow to redirect I/O
> > > tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
> > >
> > > So effectively the special PCI host controller
> > > 1) knows the physical range that needs special redirection
> > > 2) register such range
> > > 3) uses pci_pio_to_address() to retrieve the IO tokens for the
> > >    special accessors
> > > 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in 3)
> > >
> > > So to be honest I think this patch can fit well both with
> > > special PCI controllers that need I/O tokens redirection and with
> > > special non-PCI controllers that need non-PCI I/O physical
> > > address redirection...
> > >
> > > Thanks (and sorry for the long reply but I didn't know how
> > > to make the explanation shorter :) )
> > >
> > > Gab
> > >
> > > >
> > > > If we separate the two steps:
> > > >
> > > > a) assign a range of logical I/O port numbers to a bus
> > > > b) register a set of helpers for redirecting logical I/O
> > > >    port to a helper function
> > > >
> > > > then I think the code will get cleaner and more flexible.
> > > > It should actually then be able to replace the powerpc
> > > > specific implementation.
> > > >
> > > > 	Arnd
> > 
> > --
> > ====================
> > | I would like to |
> > | fix the world,  |
> > | but they're not |
> > | giving me the   |
> >  \ source code!  /
> >   ---------------
> >     ?\_(?)_/?

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

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-11 18:16                         ` liviu.dudau
  (?)
  (?)
@ 2016-11-14  8:26                           ` Gabriele Paoloni
  -1 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-14  8:26 UTC (permalink / raw)
  To: liviu.dudau
  Cc: Arnd Bergmann, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, bhelgaas@googl e.com, zhichang.yuan02

Hi Liviu

> -----Original Message-----
> From: liviu.dudau@arm.com [mailto:liviu.dudau@arm.com]
> Sent: 11 November 2016 18:16
> To: Gabriele Paoloni
> Cc: Arnd Bergmann; linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> mark.rutland@arm.com; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> catalin.marinas@arm.com; olof@lixom.net; bhelgaas@googl e.com;
> zhichang.yuan02@gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Fri, Nov 11, 2016 at 03:53:53PM +0000, Gabriele Paoloni wrote:
> > Hi Liviu
> 
> Hi Gabriele,
> 
> >
> > > -----Original Message-----
> > > From: liviu.dudau@arm.com [mailto:liviu.dudau@arm.com]
> > > Sent: 11 November 2016 14:46
> > > To: Gabriele Paoloni
> > > Cc: Arnd Bergmann; linux-arm-kernel@lists.infradead.org;
> Yuanzhichang;
> > > mark.rutland@arm.com; devicetree@vger.kernel.org;
> > > lorenzo.pieralisi@arm.com; minyard@acm.org; linux-
> pci@vger.kernel.org;
> > > benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> > > kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> > > robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> > > catalin.marinas@arm.com; olof@lixom.net; bhelgaas@googl e.com;
> > > zhichang.yuan02@gmail.com
> > > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> > > Hip06
> > >
> > > On Fri, Nov 11, 2016 at 01:39:35PM +0000, Gabriele Paoloni wrote:
> > > > Hi Arnd
> > > >
> > > > > -----Original Message-----
> > > > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > > Sent: 10 November 2016 16:07
> > > > > To: Gabriele Paoloni
> > > > > Cc: linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> > > > > mark.rutland@arm.com; devicetree@vger.kernel.org;
> > > > > lorenzo.pieralisi@arm.com; minyard@acm.org; linux-
> > > pci@vger.kernel.org;
> > > > > benh@kernel.crashing.org; John Garry; will.deacon@arm.com;
> linux-
> > > > > kernel@vger.kernel.org; xuwei (O); Linuxarm;
> zourongrong@gmail.com;
> > > > > robh+dt@kernel.org; kantyzc@163.com; linux-
> serial@vger.kernel.org;
> > > > > catalin.marinas@arm.com; olof@lixom.net; liviu.dudau@arm.com;
> > > > > bhelgaas@googl e.com; zhichang.yuan02@gmail.com
> > > > > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver
> implementation on
> > > > > Hip06
> > > > >
> > > > > On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni
> > > wrote:
> > > > > >
> > > > > > Where should we get the range from? For LPC we know that it
> is
> > > going
> > > > > > Work on anything that is not used by PCI I/O space, and this
> is
> > > > > > why we use [0, PCIBIOS_MIN_IO]
> > > > >
> > > > > It should be allocated the same way we allocate PCI config
> space
> > > > > segments. This is currently done with the io_range list in
> > > > > drivers/pci/pci.c, which isn't perfect but could be extended
> > > > > if necessary. Based on what others commented here, I'd rather
> > > > > make the differences between ISA/LPC and PCI I/O ranges smaller
> > > > > than larger.
> > >
> > > Gabriele,
> > >
> > > >
> > > > I am not sure this would make sense...
> > > >
> > > > IMHO all the mechanism around io_range_list is needed to provide
> the
> > > > "mapping" between I/O tokens and physical CPU addresses.
> > > >
> > > > Currently the available tokens range from 0 to IO_SPACE_LIMIT.
> > > >
> > > > As you know the I/O memory accessors operate on whatever
> > > > __of_address_to_resource sets into the resource (start, end).
> > > >
> > > > With this special device in place we cannot know if a resource is
> > > > assigned with an I/O token or a physical address, unless we
> forbid
> > > > the I/O tokens to be in a specific range.
> > > >
> > > > So this is why we are changing the offsets of all the functions
> > > > handling io_range_list (to make sure that a range is forbidden to
> > > > the tokens and is available to the physical addresses).
> > > >
> > > > We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
> > > > because this is the maximum physical I/O range that a non PCI
> device
> > > > can operate on and because we believe this does not impose much
> > > > restriction on the available I/O token range; that now is
> > > > [PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
> > > > So we believe that the chosen forbidden range can accommodate
> > > > any special ISA bus device with no much constraint on the rest
> > > > of I/O tokens...
> > >
> > > Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and
> you
> > > actually need another variable for "reserving" an area in the I/O
> space
> > > that can be used for physical addresses rather than I/O tokens.
> > >
> > > The one good example for using PCIBIOS_MIN_IO is when your
> > > platform/architecture
> > > does not support legacy ISA operations *at all*. In that case
> someone
> > > sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O
> range
> > > so that it doesn't get used. With Zhichang's patch you now start
> > > forcing
> > > those platforms to have a valid address below PCIBIOS_MIN_IO.
> >
> > But if PCIBIOS_MIN_IO is 0 then it means that all I/O space is to be
> used
> > by PCI controllers only...
> 
> Nope, that is not what it means. It means that PCI devices can see I/O
> addresses
> on the bus that start from 0. There never was any usage for non-PCI
> controllers

So I am a bit confused...
>From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
It seems that ISA buses operate on cpu I/O address range [0, 0xFFF].
I thought that was the reason why for most architectures we have
PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA controllers
usually use [0, PCIBIOS_MIN_IO - 1] )

For those architectures whose PCIBIOS_MIN_IO != 0x1000 probably
they are not fully compliant or they cannot fully support an ISA
controller...?

As said before this series forbid IO tokens to be in [0, PCIBIOS_MIN_IO)
to allow special ISA controllers to use that range with special
accessors.
Having a variable threshold would make life much more difficult
as there would be a probe dependency between the PCI controller and
the special ISA one (PCI to wait for the special ISA device to be
probed and set the right threshold value from DT or ACPI table).

Instead using PCIBIOS_MIN_IO is easier and should not impose much
constraint as [PCIBIOS_MIN_IO, IO_SPACE_LIMIT] is available to
the PCI controller for I/O tokens...

Thanks

Gab

> when PCIBIOS_MIN_IO != 0. That is what Zhichang is trying to do now and
> what
> I think is not the right thing (and not enough anyway).
> 
> > so if you have a special bus device using
> > an I/O range in this case should be a PCI controller...
> 
> That has always been the case. It is this series that wants to
> introduce the
> new meaning.
> 
> > i.e. I would
> > expect it to fall back into the case of I/O tokens redirection rather
> than
> > physical addresses redirection (as mentioned below from my previous
> reply).
> > What do you think?
> 
> I think you have looked too much at the code *with* Zhichang's patches
> applied.
> Take a step back and look at how PCIBIOS_MIN_IO is used now, before you
> apply
> the patches. It is all about PCI addresses and there is no notion of
> non-PCI
> busses using PCI framework. Only platforms and architectures that try
> to work
> around some legacy standards (ISA) or HW restrictions.
> 
> Best regards,
> Liviu
> 
> >
> > Thanks
> >
> > Gab
> >
> >
> > >
> > > For the general case you also have to bear in mind that
> PCIBIOS_MIN_IO
> > > could
> > > be zero. In that case, what is your "forbidden" range? [0, 0) ? So
> it
> > > makes
> > > sense to add a new #define that should only be defined by those
> > > architectures/
> > > platforms that want to reserve on top of PCIBIOS_MIN_IO another
> region
> > > where I/O tokens can't be generated for.
> > >
> > > Best regards,
> > > Liviu
> > >
> > > >
> > > > >
> > > > > > > Your current version has
> > > > > > >
> > > > > > >         if (arm64_extio_ops->pfout)
> > > \
> > > > > > >                 arm64_extio_ops->pfout(arm64_extio_ops-
> > > >devpara,\
> > > > > > >                        addr, value, sizeof(type));
> > > \
> > > > > > >
> > > > > > > Instead, just subtract the start of the range from the
> logical
> > > > > > > port number to transform it back into a bus-local port
> number:
> > > > > >
> > > > > > These accessors do not operate on IO tokens:
> > > > > >
> > > > > > If (arm64_extio_ops->start > addr || arm64_extio_ops->end <
> addr)
> > > > > > addr is not going to be an I/O token; in fact patch 2/3
> imposes
> > > that
> > > > > > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> > > > > PCIBIOS_MIN_IO
> > > > > > we have free physical addresses that the accessors can
> operate
> > > on.
> > > > >
> > > > > Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to
> refer
> > > to
> > > > > the logical I/O tokens, the purpose of that macro is really
> meant
> > > > > for allocating PCI I/O port numbers within the address space of
> > > > > one bus.
> > > >
> > > > As I mentioned above, special devices operate on CPU addresses
> > > directly,
> > > > not I/O tokens. For them there is no way to distinguish....
> > > >
> > > > >
> > > > > Note that it's equally likely that whichever next platform
> needs
> > > > > non-mapped I/O access like this actually needs them for PCI I/O
> > > space,
> > > > > and that will use it on addresses registered to a PCI host
> bridge.
> > > >
> > > > Ok so here you are talking about a platform that has got an I/O
> range
> > > > under the PCI host controller, right?
> > > > And this I/O range cannot be directly memory mapped but needs
> special
> > > > redirections for the I/O tokens, right?
> > > >
> > > > In this scenario registering the I/O ranges with the forbidden
> range
> > > > implemented by the current patch would still allow to redirect
> I/O
> > > > tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
> > > >
> > > > So effectively the special PCI host controller
> > > > 1) knows the physical range that needs special redirection
> > > > 2) register such range
> > > > 3) uses pci_pio_to_address() to retrieve the IO tokens for the
> > > >    special accessors
> > > > 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in
> 3)
> > > >
> > > > So to be honest I think this patch can fit well both with
> > > > special PCI controllers that need I/O tokens redirection and with
> > > > special non-PCI controllers that need non-PCI I/O physical
> > > > address redirection...
> > > >
> > > > Thanks (and sorry for the long reply but I didn't know how
> > > > to make the explanation shorter :) )
> > > >
> > > > Gab
> > > >
> > > > >
> > > > > If we separate the two steps:
> > > > >
> > > > > a) assign a range of logical I/O port numbers to a bus
> > > > > b) register a set of helpers for redirecting logical I/O
> > > > >    port to a helper function
> > > > >
> > > > > then I think the code will get cleaner and more flexible.
> > > > > It should actually then be able to replace the powerpc
> > > > > specific implementation.
> > > > >
> > > > > 	Arnd
> > >
> > > --
> > > ====================
> > > | I would like to |
> > > | fix the world,  |
> > > | but they're not |
> > > | giving me the   |
> > >  \ source code!  /
> > >   ---------------
> > >     ¯\_(ツ)_/¯
> 
> --
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ¯\_(ツ)_/¯

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-14  8:26                           ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-14  8:26 UTC (permalink / raw)
  To: liviu.dudau
  Cc: Arnd Bergmann, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt

Hi Liviu

> -----Original Message-----
> From: liviu.dudau@arm.com [mailto:liviu.dudau@arm.com]
> Sent: 11 November 2016 18:16
> To: Gabriele Paoloni
> Cc: Arnd Bergmann; linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> mark.rutland@arm.com; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> catalin.marinas@arm.com; olof@lixom.net; bhelgaas@googl e.com;
> zhichang.yuan02@gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Fri, Nov 11, 2016 at 03:53:53PM +0000, Gabriele Paoloni wrote:
> > Hi Liviu
> 
> Hi Gabriele,
> 
> >
> > > -----Original Message-----
> > > From: liviu.dudau@arm.com [mailto:liviu.dudau@arm.com]
> > > Sent: 11 November 2016 14:46
> > > To: Gabriele Paoloni
> > > Cc: Arnd Bergmann; linux-arm-kernel@lists.infradead.org;
> Yuanzhichang;
> > > mark.rutland@arm.com; devicetree@vger.kernel.org;
> > > lorenzo.pieralisi@arm.com; minyard@acm.org; linux-
> pci@vger.kernel.org;
> > > benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> > > kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> > > robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> > > catalin.marinas@arm.com; olof@lixom.net; bhelgaas@googl e.com;
> > > zhichang.yuan02@gmail.com
> > > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> > > Hip06
> > >
> > > On Fri, Nov 11, 2016 at 01:39:35PM +0000, Gabriele Paoloni wrote:
> > > > Hi Arnd
> > > >
> > > > > -----Original Message-----
> > > > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > > Sent: 10 November 2016 16:07
> > > > > To: Gabriele Paoloni
> > > > > Cc: linux-arm-kernel@lists.infradead.org; Yuanzhichang;
> > > > > mark.rutland@arm.com; devicetree@vger.kernel.org;
> > > > > lorenzo.pieralisi@arm.com; minyard@acm.org; linux-
> > > pci@vger.kernel.org;
> > > > > benh@kernel.crashing.org; John Garry; will.deacon@arm.com;
> linux-
> > > > > kernel@vger.kernel.org; xuwei (O); Linuxarm;
> zourongrong@gmail.com;
> > > > > robh+dt@kernel.org; kantyzc@163.com; linux-
> serial@vger.kernel.org;
> > > > > catalin.marinas@arm.com; olof@lixom.net; liviu.dudau@arm.com;
> > > > > bhelgaas@googl e.com; zhichang.yuan02@gmail.com
> > > > > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver
> implementation on
> > > > > Hip06
> > > > >
> > > > > On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni
> > > wrote:
> > > > > >
> > > > > > Where should we get the range from? For LPC we know that it
> is
> > > going
> > > > > > Work on anything that is not used by PCI I/O space, and this
> is
> > > > > > why we use [0, PCIBIOS_MIN_IO]
> > > > >
> > > > > It should be allocated the same way we allocate PCI config
> space
> > > > > segments. This is currently done with the io_range list in
> > > > > drivers/pci/pci.c, which isn't perfect but could be extended
> > > > > if necessary. Based on what others commented here, I'd rather
> > > > > make the differences between ISA/LPC and PCI I/O ranges smaller
> > > > > than larger.
> > >
> > > Gabriele,
> > >
> > > >
> > > > I am not sure this would make sense...
> > > >
> > > > IMHO all the mechanism around io_range_list is needed to provide
> the
> > > > "mapping" between I/O tokens and physical CPU addresses.
> > > >
> > > > Currently the available tokens range from 0 to IO_SPACE_LIMIT.
> > > >
> > > > As you know the I/O memory accessors operate on whatever
> > > > __of_address_to_resource sets into the resource (start, end).
> > > >
> > > > With this special device in place we cannot know if a resource is
> > > > assigned with an I/O token or a physical address, unless we
> forbid
> > > > the I/O tokens to be in a specific range.
> > > >
> > > > So this is why we are changing the offsets of all the functions
> > > > handling io_range_list (to make sure that a range is forbidden to
> > > > the tokens and is available to the physical addresses).
> > > >
> > > > We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
> > > > because this is the maximum physical I/O range that a non PCI
> device
> > > > can operate on and because we believe this does not impose much
> > > > restriction on the available I/O token range; that now is
> > > > [PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
> > > > So we believe that the chosen forbidden range can accommodate
> > > > any special ISA bus device with no much constraint on the rest
> > > > of I/O tokens...
> > >
> > > Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and
> you
> > > actually need another variable for "reserving" an area in the I/O
> space
> > > that can be used for physical addresses rather than I/O tokens.
> > >
> > > The one good example for using PCIBIOS_MIN_IO is when your
> > > platform/architecture
> > > does not support legacy ISA operations *at all*. In that case
> someone
> > > sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O
> range
> > > so that it doesn't get used. With Zhichang's patch you now start
> > > forcing
> > > those platforms to have a valid address below PCIBIOS_MIN_IO.
> >
> > But if PCIBIOS_MIN_IO is 0 then it means that all I/O space is to be
> used
> > by PCI controllers only...
> 
> Nope, that is not what it means. It means that PCI devices can see I/O
> addresses
> on the bus that start from 0. There never was any usage for non-PCI
> controllers

So I am a bit confused...
From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
It seems that ISA buses operate on cpu I/O address range [0, 0xFFF].
I thought that was the reason why for most architectures we have
PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA controllers
usually use [0, PCIBIOS_MIN_IO - 1] )

For those architectures whose PCIBIOS_MIN_IO != 0x1000 probably
they are not fully compliant or they cannot fully support an ISA
controller...?

As said before this series forbid IO tokens to be in [0, PCIBIOS_MIN_IO)
to allow special ISA controllers to use that range with special
accessors.
Having a variable threshold would make life much more difficult
as there would be a probe dependency between the PCI controller and
the special ISA one (PCI to wait for the special ISA device to be
probed and set the right threshold value from DT or ACPI table).

Instead using PCIBIOS_MIN_IO is easier and should not impose much
constraint as [PCIBIOS_MIN_IO, IO_SPACE_LIMIT] is available to
the PCI controller for I/O tokens...

Thanks

Gab

> when PCIBIOS_MIN_IO != 0. That is what Zhichang is trying to do now and
> what
> I think is not the right thing (and not enough anyway).
> 
> > so if you have a special bus device using
> > an I/O range in this case should be a PCI controller...
> 
> That has always been the case. It is this series that wants to
> introduce the
> new meaning.
> 
> > i.e. I would
> > expect it to fall back into the case of I/O tokens redirection rather
> than
> > physical addresses redirection (as mentioned below from my previous
> reply).
> > What do you think?
> 
> I think you have looked too much at the code *with* Zhichang's patches
> applied.
> Take a step back and look at how PCIBIOS_MIN_IO is used now, before you
> apply
> the patches. It is all about PCI addresses and there is no notion of
> non-PCI
> busses using PCI framework. Only platforms and architectures that try
> to work
> around some legacy standards (ISA) or HW restrictions.
> 
> Best regards,
> Liviu
> 
> >
> > Thanks
> >
> > Gab
> >
> >
> > >
> > > For the general case you also have to bear in mind that
> PCIBIOS_MIN_IO
> > > could
> > > be zero. In that case, what is your "forbidden" range? [0, 0) ? So
> it
> > > makes
> > > sense to add a new #define that should only be defined by those
> > > architectures/
> > > platforms that want to reserve on top of PCIBIOS_MIN_IO another
> region
> > > where I/O tokens can't be generated for.
> > >
> > > Best regards,
> > > Liviu
> > >
> > > >
> > > > >
> > > > > > > Your current version has
> > > > > > >
> > > > > > >         if (arm64_extio_ops->pfout)
> > > \
> > > > > > >                 arm64_extio_ops->pfout(arm64_extio_ops-
> > > >devpara,\
> > > > > > >                        addr, value, sizeof(type));
> > > \
> > > > > > >
> > > > > > > Instead, just subtract the start of the range from the
> logical
> > > > > > > port number to transform it back into a bus-local port
> number:
> > > > > >
> > > > > > These accessors do not operate on IO tokens:
> > > > > >
> > > > > > If (arm64_extio_ops->start > addr || arm64_extio_ops->end <
> addr)
> > > > > > addr is not going to be an I/O token; in fact patch 2/3
> imposes
> > > that
> > > > > > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> > > > > PCIBIOS_MIN_IO
> > > > > > we have free physical addresses that the accessors can
> operate
> > > on.
> > > > >
> > > > > Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to
> refer
> > > to
> > > > > the logical I/O tokens, the purpose of that macro is really
> meant
> > > > > for allocating PCI I/O port numbers within the address space of
> > > > > one bus.
> > > >
> > > > As I mentioned above, special devices operate on CPU addresses
> > > directly,
> > > > not I/O tokens. For them there is no way to distinguish....
> > > >
> > > > >
> > > > > Note that it's equally likely that whichever next platform
> needs
> > > > > non-mapped I/O access like this actually needs them for PCI I/O
> > > space,
> > > > > and that will use it on addresses registered to a PCI host
> bridge.
> > > >
> > > > Ok so here you are talking about a platform that has got an I/O
> range
> > > > under the PCI host controller, right?
> > > > And this I/O range cannot be directly memory mapped but needs
> special
> > > > redirections for the I/O tokens, right?
> > > >
> > > > In this scenario registering the I/O ranges with the forbidden
> range
> > > > implemented by the current patch would still allow to redirect
> I/O
> > > > tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
> > > >
> > > > So effectively the special PCI host controller
> > > > 1) knows the physical range that needs special redirection
> > > > 2) register such range
> > > > 3) uses pci_pio_to_address() to retrieve the IO tokens for the
> > > >    special accessors
> > > > 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in
> 3)
> > > >
> > > > So to be honest I think this patch can fit well both with
> > > > special PCI controllers that need I/O tokens redirection and with
> > > > special non-PCI controllers that need non-PCI I/O physical
> > > > address redirection...
> > > >
> > > > Thanks (and sorry for the long reply but I didn't know how
> > > > to make the explanation shorter :) )
> > > >
> > > > Gab
> > > >
> > > > >
> > > > > If we separate the two steps:
> > > > >
> > > > > a) assign a range of logical I/O port numbers to a bus
> > > > > b) register a set of helpers for redirecting logical I/O
> > > > >    port to a helper function
> > > > >
> > > > > then I think the code will get cleaner and more flexible.
> > > > > It should actually then be able to replace the powerpc
> > > > > specific implementation.
> > > > >
> > > > > 	Arnd
> > >
> > > --
> > > ====================
> > > | I would like to |
> > > | fix the world,  |
> > > | but they're not |
> > > | giving me the   |
> > >  \ source code!  /
> > >   ---------------
> > >     ¯\_(ツ)_/¯
> 
> --
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ¯\_(ツ)_/¯

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-14  8:26                           ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-14  8:26 UTC (permalink / raw)
  To: liviu.dudau
  Cc: Arnd Bergmann, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, bhelgaas@googl e.com, zhichang.yuan02

SGkgTGl2aXUNCg0KPiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBsaXZpdS5k
dWRhdUBhcm0uY29tIFttYWlsdG86bGl2aXUuZHVkYXVAYXJtLmNvbV0NCj4gU2VudDogMTEgTm92
ZW1iZXIgMjAxNiAxODoxNg0KPiBUbzogR2FicmllbGUgUGFvbG9uaQ0KPiBDYzogQXJuZCBCZXJn
bWFubjsgbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnOyBZdWFuemhpY2hhbmc7
DQo+IG1hcmsucnV0bGFuZEBhcm0uY29tOyBkZXZpY2V0cmVlQHZnZXIua2VybmVsLm9yZzsNCj4g
bG9yZW56by5waWVyYWxpc2lAYXJtLmNvbTsgbWlueWFyZEBhY20ub3JnOyBsaW51eC1wY2lAdmdl
ci5rZXJuZWwub3JnOw0KPiBiZW5oQGtlcm5lbC5jcmFzaGluZy5vcmc7IEpvaG4gR2Fycnk7IHdp
bGwuZGVhY29uQGFybS5jb207IGxpbnV4LQ0KPiBrZXJuZWxAdmdlci5rZXJuZWwub3JnOyB4dXdl
aSAoTyk7IExpbnV4YXJtOyB6b3Vyb25ncm9uZ0BnbWFpbC5jb207DQo+IHJvYmgrZHRAa2VybmVs
Lm9yZzsga2FudHl6Y0AxNjMuY29tOyBsaW51eC1zZXJpYWxAdmdlci5rZXJuZWwub3JnOw0KPiBj
YXRhbGluLm1hcmluYXNAYXJtLmNvbTsgb2xvZkBsaXhvbS5uZXQ7IGJoZWxnYWFzQGdvb2dsIGUu
Y29tOw0KPiB6aGljaGFuZy55dWFuMDJAZ21haWwuY29tDQo+IFN1YmplY3Q6IFJlOiBbUEFUQ0gg
VjUgMy8zXSBBUk02NCBMUEM6IExQQyBkcml2ZXIgaW1wbGVtZW50YXRpb24gb24NCj4gSGlwMDYN
Cj4gDQo+IE9uIEZyaSwgTm92IDExLCAyMDE2IGF0IDAzOjUzOjUzUE0gKzAwMDAsIEdhYnJpZWxl
IFBhb2xvbmkgd3JvdGU6DQo+ID4gSGkgTGl2aXUNCj4gDQo+IEhpIEdhYnJpZWxlLA0KPiANCj4g
Pg0KPiA+ID4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gPiA+IEZyb206IGxpdml1LmR1
ZGF1QGFybS5jb20gW21haWx0bzpsaXZpdS5kdWRhdUBhcm0uY29tXQ0KPiA+ID4gU2VudDogMTEg
Tm92ZW1iZXIgMjAxNiAxNDo0Ng0KPiA+ID4gVG86IEdhYnJpZWxlIFBhb2xvbmkNCj4gPiA+IENj
OiBBcm5kIEJlcmdtYW5uOyBsaW51eC1hcm0ta2VybmVsQGxpc3RzLmluZnJhZGVhZC5vcmc7DQo+
IFl1YW56aGljaGFuZzsNCj4gPiA+IG1hcmsucnV0bGFuZEBhcm0uY29tOyBkZXZpY2V0cmVlQHZn
ZXIua2VybmVsLm9yZzsNCj4gPiA+IGxvcmVuem8ucGllcmFsaXNpQGFybS5jb207IG1pbnlhcmRA
YWNtLm9yZzsgbGludXgtDQo+IHBjaUB2Z2VyLmtlcm5lbC5vcmc7DQo+ID4gPiBiZW5oQGtlcm5l
bC5jcmFzaGluZy5vcmc7IEpvaG4gR2Fycnk7IHdpbGwuZGVhY29uQGFybS5jb207IGxpbnV4LQ0K
PiA+ID4ga2VybmVsQHZnZXIua2VybmVsLm9yZzsgeHV3ZWkgKE8pOyBMaW51eGFybTsgem91cm9u
Z3JvbmdAZ21haWwuY29tOw0KPiA+ID4gcm9iaCtkdEBrZXJuZWwub3JnOyBrYW50eXpjQDE2My5j
b207IGxpbnV4LXNlcmlhbEB2Z2VyLmtlcm5lbC5vcmc7DQo+ID4gPiBjYXRhbGluLm1hcmluYXNA
YXJtLmNvbTsgb2xvZkBsaXhvbS5uZXQ7IGJoZWxnYWFzQGdvb2dsIGUuY29tOw0KPiA+ID4gemhp
Y2hhbmcueXVhbjAyQGdtYWlsLmNvbQ0KPiA+ID4gU3ViamVjdDogUmU6IFtQQVRDSCBWNSAzLzNd
IEFSTTY0IExQQzogTFBDIGRyaXZlciBpbXBsZW1lbnRhdGlvbiBvbg0KPiA+ID4gSGlwMDYNCj4g
PiA+DQo+ID4gPiBPbiBGcmksIE5vdiAxMSwgMjAxNiBhdCAwMTozOTozNVBNICswMDAwLCBHYWJy
aWVsZSBQYW9sb25pIHdyb3RlOg0KPiA+ID4gPiBIaSBBcm5kDQo+ID4gPiA+DQo+ID4gPiA+ID4g
LS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gPiA+ID4gPiBGcm9tOiBBcm5kIEJlcmdtYW5u
IFttYWlsdG86YXJuZEBhcm5kYi5kZV0NCj4gPiA+ID4gPiBTZW50OiAxMCBOb3ZlbWJlciAyMDE2
IDE2OjA3DQo+ID4gPiA+ID4gVG86IEdhYnJpZWxlIFBhb2xvbmkNCj4gPiA+ID4gPiBDYzogbGlu
dXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnOyBZdWFuemhpY2hhbmc7DQo+ID4gPiA+
ID4gbWFyay5ydXRsYW5kQGFybS5jb207IGRldmljZXRyZWVAdmdlci5rZXJuZWwub3JnOw0KPiA+
ID4gPiA+IGxvcmVuem8ucGllcmFsaXNpQGFybS5jb207IG1pbnlhcmRAYWNtLm9yZzsgbGludXgt
DQo+ID4gPiBwY2lAdmdlci5rZXJuZWwub3JnOw0KPiA+ID4gPiA+IGJlbmhAa2VybmVsLmNyYXNo
aW5nLm9yZzsgSm9obiBHYXJyeTsgd2lsbC5kZWFjb25AYXJtLmNvbTsNCj4gbGludXgtDQo+ID4g
PiA+ID4ga2VybmVsQHZnZXIua2VybmVsLm9yZzsgeHV3ZWkgKE8pOyBMaW51eGFybTsNCj4gem91
cm9uZ3JvbmdAZ21haWwuY29tOw0KPiA+ID4gPiA+IHJvYmgrZHRAa2VybmVsLm9yZzsga2FudHl6
Y0AxNjMuY29tOyBsaW51eC0NCj4gc2VyaWFsQHZnZXIua2VybmVsLm9yZzsNCj4gPiA+ID4gPiBj
YXRhbGluLm1hcmluYXNAYXJtLmNvbTsgb2xvZkBsaXhvbS5uZXQ7IGxpdml1LmR1ZGF1QGFybS5j
b207DQo+ID4gPiA+ID4gYmhlbGdhYXNAZ29vZ2wgZS5jb207IHpoaWNoYW5nLnl1YW4wMkBnbWFp
bC5jb20NCj4gPiA+ID4gPiBTdWJqZWN0OiBSZTogW1BBVENIIFY1IDMvM10gQVJNNjQgTFBDOiBM
UEMgZHJpdmVyDQo+IGltcGxlbWVudGF0aW9uIG9uDQo+ID4gPiA+ID4gSGlwMDYNCj4gPiA+ID4g
Pg0KPiA+ID4gPiA+IE9uIFRodXJzZGF5LCBOb3ZlbWJlciAxMCwgMjAxNiAzOjM2OjQ5IFBNIENF
VCBHYWJyaWVsZSBQYW9sb25pDQo+ID4gPiB3cm90ZToNCj4gPiA+ID4gPiA+DQo+ID4gPiA+ID4g
PiBXaGVyZSBzaG91bGQgd2UgZ2V0IHRoZSByYW5nZSBmcm9tPyBGb3IgTFBDIHdlIGtub3cgdGhh
dCBpdA0KPiBpcw0KPiA+ID4gZ29pbmcNCj4gPiA+ID4gPiA+IFdvcmsgb24gYW55dGhpbmcgdGhh
dCBpcyBub3QgdXNlZCBieSBQQ0kgSS9PIHNwYWNlLCBhbmQgdGhpcw0KPiBpcw0KPiA+ID4gPiA+
ID4gd2h5IHdlIHVzZSBbMCwgUENJQklPU19NSU5fSU9dDQo+ID4gPiA+ID4NCj4gPiA+ID4gPiBJ
dCBzaG91bGQgYmUgYWxsb2NhdGVkIHRoZSBzYW1lIHdheSB3ZSBhbGxvY2F0ZSBQQ0kgY29uZmln
DQo+IHNwYWNlDQo+ID4gPiA+ID4gc2VnbWVudHMuIFRoaXMgaXMgY3VycmVudGx5IGRvbmUgd2l0
aCB0aGUgaW9fcmFuZ2UgbGlzdCBpbg0KPiA+ID4gPiA+IGRyaXZlcnMvcGNpL3BjaS5jLCB3aGlj
aCBpc24ndCBwZXJmZWN0IGJ1dCBjb3VsZCBiZSBleHRlbmRlZA0KPiA+ID4gPiA+IGlmIG5lY2Vz
c2FyeS4gQmFzZWQgb24gd2hhdCBvdGhlcnMgY29tbWVudGVkIGhlcmUsIEknZCByYXRoZXINCj4g
PiA+ID4gPiBtYWtlIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIElTQS9MUEMgYW5kIFBDSSBJL08g
cmFuZ2VzIHNtYWxsZXINCj4gPiA+ID4gPiB0aGFuIGxhcmdlci4NCj4gPiA+DQo+ID4gPiBHYWJy
aWVsZSwNCj4gPiA+DQo+ID4gPiA+DQo+ID4gPiA+IEkgYW0gbm90IHN1cmUgdGhpcyB3b3VsZCBt
YWtlIHNlbnNlLi4uDQo+ID4gPiA+DQo+ID4gPiA+IElNSE8gYWxsIHRoZSBtZWNoYW5pc20gYXJv
dW5kIGlvX3JhbmdlX2xpc3QgaXMgbmVlZGVkIHRvIHByb3ZpZGUNCj4gdGhlDQo+ID4gPiA+ICJt
YXBwaW5nIiBiZXR3ZWVuIEkvTyB0b2tlbnMgYW5kIHBoeXNpY2FsIENQVSBhZGRyZXNzZXMuDQo+
ID4gPiA+DQo+ID4gPiA+IEN1cnJlbnRseSB0aGUgYXZhaWxhYmxlIHRva2VucyByYW5nZSBmcm9t
IDAgdG8gSU9fU1BBQ0VfTElNSVQuDQo+ID4gPiA+DQo+ID4gPiA+IEFzIHlvdSBrbm93IHRoZSBJ
L08gbWVtb3J5IGFjY2Vzc29ycyBvcGVyYXRlIG9uIHdoYXRldmVyDQo+ID4gPiA+IF9fb2ZfYWRk
cmVzc190b19yZXNvdXJjZSBzZXRzIGludG8gdGhlIHJlc291cmNlIChzdGFydCwgZW5kKS4NCj4g
PiA+ID4NCj4gPiA+ID4gV2l0aCB0aGlzIHNwZWNpYWwgZGV2aWNlIGluIHBsYWNlIHdlIGNhbm5v
dCBrbm93IGlmIGEgcmVzb3VyY2UgaXMNCj4gPiA+ID4gYXNzaWduZWQgd2l0aCBhbiBJL08gdG9r
ZW4gb3IgYSBwaHlzaWNhbCBhZGRyZXNzLCB1bmxlc3Mgd2UNCj4gZm9yYmlkDQo+ID4gPiA+IHRo
ZSBJL08gdG9rZW5zIHRvIGJlIGluIGEgc3BlY2lmaWMgcmFuZ2UuDQo+ID4gPiA+DQo+ID4gPiA+
IFNvIHRoaXMgaXMgd2h5IHdlIGFyZSBjaGFuZ2luZyB0aGUgb2Zmc2V0cyBvZiBhbGwgdGhlIGZ1
bmN0aW9ucw0KPiA+ID4gPiBoYW5kbGluZyBpb19yYW5nZV9saXN0ICh0byBtYWtlIHN1cmUgdGhh
dCBhIHJhbmdlIGlzIGZvcmJpZGRlbiB0bw0KPiA+ID4gPiB0aGUgdG9rZW5zIGFuZCBpcyBhdmFp
bGFibGUgdG8gdGhlIHBoeXNpY2FsIGFkZHJlc3NlcykuDQo+ID4gPiA+DQo+ID4gPiA+IFdlIGhh
dmUgY2hvc2VuIHRoaXMgZm9yYmlkZGVuIHJhbmdlIHRvIGJlIFswLCBQQ0lCSU9TX01JTl9JTykN
Cj4gPiA+ID4gYmVjYXVzZSB0aGlzIGlzIHRoZSBtYXhpbXVtIHBoeXNpY2FsIEkvTyByYW5nZSB0
aGF0IGEgbm9uIFBDSQ0KPiBkZXZpY2UNCj4gPiA+ID4gY2FuIG9wZXJhdGUgb24gYW5kIGJlY2F1
c2Ugd2UgYmVsaWV2ZSB0aGlzIGRvZXMgbm90IGltcG9zZSBtdWNoDQo+ID4gPiA+IHJlc3RyaWN0
aW9uIG9uIHRoZSBhdmFpbGFibGUgSS9PIHRva2VuIHJhbmdlOyB0aGF0IG5vdyBpcw0KPiA+ID4g
PiBbUENJQklPU19NSU5fSU8sIElPX1NQQUNFX0xJTUlUXS4NCj4gPiA+ID4gU28gd2UgYmVsaWV2
ZSB0aGF0IHRoZSBjaG9zZW4gZm9yYmlkZGVuIHJhbmdlIGNhbiBhY2NvbW1vZGF0ZQ0KPiA+ID4g
PiBhbnkgc3BlY2lhbCBJU0EgYnVzIGRldmljZSB3aXRoIG5vIG11Y2ggY29uc3RyYWludCBvbiB0
aGUgcmVzdA0KPiA+ID4gPiBvZiBJL08gdG9rZW5zLi4uDQo+ID4gPg0KPiA+ID4gWW91ciBpZGVh
IGlzIGEgZ29vZCBvbmUsIGhvd2V2ZXIgeW91IGFyZSBhYnVzaW5nIFBDSUJJT1NfTUlOX0lPIGFu
ZA0KPiB5b3UNCj4gPiA+IGFjdHVhbGx5IG5lZWQgYW5vdGhlciB2YXJpYWJsZSBmb3IgInJlc2Vy
dmluZyIgYW4gYXJlYSBpbiB0aGUgSS9PDQo+IHNwYWNlDQo+ID4gPiB0aGF0IGNhbiBiZSB1c2Vk
IGZvciBwaHlzaWNhbCBhZGRyZXNzZXMgcmF0aGVyIHRoYW4gSS9PIHRva2Vucy4NCj4gPiA+DQo+
ID4gPiBUaGUgb25lIGdvb2QgZXhhbXBsZSBmb3IgdXNpbmcgUENJQklPU19NSU5fSU8gaXMgd2hl
biB5b3VyDQo+ID4gPiBwbGF0Zm9ybS9hcmNoaXRlY3R1cmUNCj4gPiA+IGRvZXMgbm90IHN1cHBv
cnQgbGVnYWN5IElTQSBvcGVyYXRpb25zICphdCBhbGwqLiBJbiB0aGF0IGNhc2UNCj4gc29tZW9u
ZQ0KPiA+ID4gc2V0cyB0aGUgUENJQklPU19NSU5fSU8gdG8gYSBub24temVybyB2YWx1ZSB0byBy
ZXNlcnZlIHRoYXQgSS9PDQo+IHJhbmdlDQo+ID4gPiBzbyB0aGF0IGl0IGRvZXNuJ3QgZ2V0IHVz
ZWQuIFdpdGggWmhpY2hhbmcncyBwYXRjaCB5b3Ugbm93IHN0YXJ0DQo+ID4gPiBmb3JjaW5nDQo+
ID4gPiB0aG9zZSBwbGF0Zm9ybXMgdG8gaGF2ZSBhIHZhbGlkIGFkZHJlc3MgYmVsb3cgUENJQklP
U19NSU5fSU8uDQo+ID4NCj4gPiBCdXQgaWYgUENJQklPU19NSU5fSU8gaXMgMCB0aGVuIGl0IG1l
YW5zIHRoYXQgYWxsIEkvTyBzcGFjZSBpcyB0byBiZQ0KPiB1c2VkDQo+ID4gYnkgUENJIGNvbnRy
b2xsZXJzIG9ubHkuLi4NCj4gDQo+IE5vcGUsIHRoYXQgaXMgbm90IHdoYXQgaXQgbWVhbnMuIEl0
IG1lYW5zIHRoYXQgUENJIGRldmljZXMgY2FuIHNlZSBJL08NCj4gYWRkcmVzc2VzDQo+IG9uIHRo
ZSBidXMgdGhhdCBzdGFydCBmcm9tIDAuIFRoZXJlIG5ldmVyIHdhcyBhbnkgdXNhZ2UgZm9yIG5v
bi1QQ0kNCj4gY29udHJvbGxlcnMNCg0KU28gSSBhbSBhIGJpdCBjb25mdXNlZC4uLg0KRnJvbSBo
dHRwOi8vd3d3LmZpcm13YXJlLm9yZy8xMjc1L2JpbmRpbmdzL2lzYS9pc2EwXzRkLnBzDQpJdCBz
ZWVtcyB0aGF0IElTQSBidXNlcyBvcGVyYXRlIG9uIGNwdSBJL08gYWRkcmVzcyByYW5nZSBbMCwg
MHhGRkZdLg0KSSB0aG91Z2h0IHRoYXQgd2FzIHRoZSByZWFzb24gd2h5IGZvciBtb3N0IGFyY2hp
dGVjdHVyZXMgd2UgaGF2ZQ0KUENJQklPU19NSU5fSU8gZXF1YWwgdG8gMHgxMDAwIChzbyBJIHRo
b3VnaHQgdGhhdCBJU0EgY29udHJvbGxlcnMNCnVzdWFsbHkgdXNlIFswLCBQQ0lCSU9TX01JTl9J
TyAtIDFdICkNCg0KRm9yIHRob3NlIGFyY2hpdGVjdHVyZXMgd2hvc2UgUENJQklPU19NSU5fSU8g
IT0gMHgxMDAwIHByb2JhYmx5DQp0aGV5IGFyZSBub3QgZnVsbHkgY29tcGxpYW50IG9yIHRoZXkg
Y2Fubm90IGZ1bGx5IHN1cHBvcnQgYW4gSVNBDQpjb250cm9sbGVyLi4uPw0KDQpBcyBzYWlkIGJl
Zm9yZSB0aGlzIHNlcmllcyBmb3JiaWQgSU8gdG9rZW5zIHRvIGJlIGluIFswLCBQQ0lCSU9TX01J
Tl9JTykNCnRvIGFsbG93IHNwZWNpYWwgSVNBIGNvbnRyb2xsZXJzIHRvIHVzZSB0aGF0IHJhbmdl
IHdpdGggc3BlY2lhbA0KYWNjZXNzb3JzLg0KSGF2aW5nIGEgdmFyaWFibGUgdGhyZXNob2xkIHdv
dWxkIG1ha2UgbGlmZSBtdWNoIG1vcmUgZGlmZmljdWx0DQphcyB0aGVyZSB3b3VsZCBiZSBhIHBy
b2JlIGRlcGVuZGVuY3kgYmV0d2VlbiB0aGUgUENJIGNvbnRyb2xsZXIgYW5kDQp0aGUgc3BlY2lh
bCBJU0Egb25lIChQQ0kgdG8gd2FpdCBmb3IgdGhlIHNwZWNpYWwgSVNBIGRldmljZSB0byBiZQ0K
cHJvYmVkIGFuZCBzZXQgdGhlIHJpZ2h0IHRocmVzaG9sZCB2YWx1ZSBmcm9tIERUIG9yIEFDUEkg
dGFibGUpLg0KDQpJbnN0ZWFkIHVzaW5nIFBDSUJJT1NfTUlOX0lPIGlzIGVhc2llciBhbmQgc2hv
dWxkIG5vdCBpbXBvc2UgbXVjaA0KY29uc3RyYWludCBhcyBbUENJQklPU19NSU5fSU8sIElPX1NQ
QUNFX0xJTUlUXSBpcyBhdmFpbGFibGUgdG8NCnRoZSBQQ0kgY29udHJvbGxlciBmb3IgSS9PIHRv
a2Vucy4uLg0KDQpUaGFua3MNCg0KR2FiDQoNCj4gd2hlbiBQQ0lCSU9TX01JTl9JTyAhPSAwLiBU
aGF0IGlzIHdoYXQgWmhpY2hhbmcgaXMgdHJ5aW5nIHRvIGRvIG5vdyBhbmQNCj4gd2hhdA0KPiBJ
IHRoaW5rIGlzIG5vdCB0aGUgcmlnaHQgdGhpbmcgKGFuZCBub3QgZW5vdWdoIGFueXdheSkuDQo+
IA0KPiA+IHNvIGlmIHlvdSBoYXZlIGEgc3BlY2lhbCBidXMgZGV2aWNlIHVzaW5nDQo+ID4gYW4g
SS9PIHJhbmdlIGluIHRoaXMgY2FzZSBzaG91bGQgYmUgYSBQQ0kgY29udHJvbGxlci4uLg0KPiAN
Cj4gVGhhdCBoYXMgYWx3YXlzIGJlZW4gdGhlIGNhc2UuIEl0IGlzIHRoaXMgc2VyaWVzIHRoYXQg
d2FudHMgdG8NCj4gaW50cm9kdWNlIHRoZQ0KPiBuZXcgbWVhbmluZy4NCj4gDQo+ID4gaS5lLiBJ
IHdvdWxkDQo+ID4gZXhwZWN0IGl0IHRvIGZhbGwgYmFjayBpbnRvIHRoZSBjYXNlIG9mIEkvTyB0
b2tlbnMgcmVkaXJlY3Rpb24gcmF0aGVyDQo+IHRoYW4NCj4gPiBwaHlzaWNhbCBhZGRyZXNzZXMg
cmVkaXJlY3Rpb24gKGFzIG1lbnRpb25lZCBiZWxvdyBmcm9tIG15IHByZXZpb3VzDQo+IHJlcGx5
KS4NCj4gPiBXaGF0IGRvIHlvdSB0aGluaz8NCj4gDQo+IEkgdGhpbmsgeW91IGhhdmUgbG9va2Vk
IHRvbyBtdWNoIGF0IHRoZSBjb2RlICp3aXRoKiBaaGljaGFuZydzIHBhdGNoZXMNCj4gYXBwbGll
ZC4NCj4gVGFrZSBhIHN0ZXAgYmFjayBhbmQgbG9vayBhdCBob3cgUENJQklPU19NSU5fSU8gaXMg
dXNlZCBub3csIGJlZm9yZSB5b3UNCj4gYXBwbHkNCj4gdGhlIHBhdGNoZXMuIEl0IGlzIGFsbCBh
Ym91dCBQQ0kgYWRkcmVzc2VzIGFuZCB0aGVyZSBpcyBubyBub3Rpb24gb2YNCj4gbm9uLVBDSQ0K
PiBidXNzZXMgdXNpbmcgUENJIGZyYW1ld29yay4gT25seSBwbGF0Zm9ybXMgYW5kIGFyY2hpdGVj
dHVyZXMgdGhhdCB0cnkNCj4gdG8gd29yaw0KPiBhcm91bmQgc29tZSBsZWdhY3kgc3RhbmRhcmRz
IChJU0EpIG9yIEhXIHJlc3RyaWN0aW9ucy4NCj4gDQo+IEJlc3QgcmVnYXJkcywNCj4gTGl2aXUN
Cj4gDQo+ID4NCj4gPiBUaGFua3MNCj4gPg0KPiA+IEdhYg0KPiA+DQo+ID4NCj4gPiA+DQo+ID4g
PiBGb3IgdGhlIGdlbmVyYWwgY2FzZSB5b3UgYWxzbyBoYXZlIHRvIGJlYXIgaW4gbWluZCB0aGF0
DQo+IFBDSUJJT1NfTUlOX0lPDQo+ID4gPiBjb3VsZA0KPiA+ID4gYmUgemVyby4gSW4gdGhhdCBj
YXNlLCB3aGF0IGlzIHlvdXIgImZvcmJpZGRlbiIgcmFuZ2U/IFswLCAwKSA/IFNvDQo+IGl0DQo+
ID4gPiBtYWtlcw0KPiA+ID4gc2Vuc2UgdG8gYWRkIGEgbmV3ICNkZWZpbmUgdGhhdCBzaG91bGQg
b25seSBiZSBkZWZpbmVkIGJ5IHRob3NlDQo+ID4gPiBhcmNoaXRlY3R1cmVzLw0KPiA+ID4gcGxh
dGZvcm1zIHRoYXQgd2FudCB0byByZXNlcnZlIG9uIHRvcCBvZiBQQ0lCSU9TX01JTl9JTyBhbm90
aGVyDQo+IHJlZ2lvbg0KPiA+ID4gd2hlcmUgSS9PIHRva2VucyBjYW4ndCBiZSBnZW5lcmF0ZWQg
Zm9yLg0KPiA+ID4NCj4gPiA+IEJlc3QgcmVnYXJkcywNCj4gPiA+IExpdml1DQo+ID4gPg0KPiA+
ID4gPg0KPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+IFlvdXIgY3VycmVudCB2ZXJzaW9uIGhhcw0K
PiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiAgICAgICAgIGlmIChhcm02NF9leHRpb19vcHMt
PnBmb3V0KQ0KPiA+ID4gXA0KPiA+ID4gPiA+ID4gPiAgICAgICAgICAgICAgICAgYXJtNjRfZXh0
aW9fb3BzLT5wZm91dChhcm02NF9leHRpb19vcHMtDQo+ID4gPiA+ZGV2cGFyYSxcDQo+ID4gPiA+
ID4gPiA+ICAgICAgICAgICAgICAgICAgICAgICAgYWRkciwgdmFsdWUsIHNpemVvZih0eXBlKSk7
DQo+ID4gPiBcDQo+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+IEluc3RlYWQsIGp1c3Qgc3Vi
dHJhY3QgdGhlIHN0YXJ0IG9mIHRoZSByYW5nZSBmcm9tIHRoZQ0KPiBsb2dpY2FsDQo+ID4gPiA+
ID4gPiA+IHBvcnQgbnVtYmVyIHRvIHRyYW5zZm9ybSBpdCBiYWNrIGludG8gYSBidXMtbG9jYWwg
cG9ydA0KPiBudW1iZXI6DQo+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gVGhlc2UgYWNjZXNzb3Jz
IGRvIG5vdCBvcGVyYXRlIG9uIElPIHRva2VuczoNCj4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiBJ
ZiAoYXJtNjRfZXh0aW9fb3BzLT5zdGFydCA+IGFkZHIgfHwgYXJtNjRfZXh0aW9fb3BzLT5lbmQg
PA0KPiBhZGRyKQ0KPiA+ID4gPiA+ID4gYWRkciBpcyBub3QgZ29pbmcgdG8gYmUgYW4gSS9PIHRv
a2VuOyBpbiBmYWN0IHBhdGNoIDIvMw0KPiBpbXBvc2VzDQo+ID4gPiB0aGF0DQo+ID4gPiA+ID4g
PiB0aGUgSS9PIHRva2VucyB3aWxsIHN0YXJ0IGF0IFBDSUJJT1NfTUlOX0lPLiBTbyBmcm9tIDAg
dG8NCj4gPiA+ID4gPiBQQ0lCSU9TX01JTl9JTw0KPiA+ID4gPiA+ID4gd2UgaGF2ZSBmcmVlIHBo
eXNpY2FsIGFkZHJlc3NlcyB0aGF0IHRoZSBhY2Nlc3NvcnMgY2FuDQo+IG9wZXJhdGUNCj4gPiA+
IG9uLg0KPiA+ID4gPiA+DQo+ID4gPiA+ID4gQWgsIEkgbWlzc2VkIHRoYXQgcGFydC4gSSdkIHJh
dGhlciBub3QgdXNlIFBDSUJJT1NfTUlOX0lPIHRvDQo+IHJlZmVyDQo+ID4gPiB0bw0KPiA+ID4g
PiA+IHRoZSBsb2dpY2FsIEkvTyB0b2tlbnMsIHRoZSBwdXJwb3NlIG9mIHRoYXQgbWFjcm8gaXMg
cmVhbGx5DQo+IG1lYW50DQo+ID4gPiA+ID4gZm9yIGFsbG9jYXRpbmcgUENJIEkvTyBwb3J0IG51
bWJlcnMgd2l0aGluIHRoZSBhZGRyZXNzIHNwYWNlIG9mDQo+ID4gPiA+ID4gb25lIGJ1cy4NCj4g
PiA+ID4NCj4gPiA+ID4gQXMgSSBtZW50aW9uZWQgYWJvdmUsIHNwZWNpYWwgZGV2aWNlcyBvcGVy
YXRlIG9uIENQVSBhZGRyZXNzZXMNCj4gPiA+IGRpcmVjdGx5LA0KPiA+ID4gPiBub3QgSS9PIHRv
a2Vucy4gRm9yIHRoZW0gdGhlcmUgaXMgbm8gd2F5IHRvIGRpc3Rpbmd1aXNoLi4uLg0KPiA+ID4g
Pg0KPiA+ID4gPiA+DQo+ID4gPiA+ID4gTm90ZSB0aGF0IGl0J3MgZXF1YWxseSBsaWtlbHkgdGhh
dCB3aGljaGV2ZXIgbmV4dCBwbGF0Zm9ybQ0KPiBuZWVkcw0KPiA+ID4gPiA+IG5vbi1tYXBwZWQg
SS9PIGFjY2VzcyBsaWtlIHRoaXMgYWN0dWFsbHkgbmVlZHMgdGhlbSBmb3IgUENJIEkvTw0KPiA+
ID4gc3BhY2UsDQo+ID4gPiA+ID4gYW5kIHRoYXQgd2lsbCB1c2UgaXQgb24gYWRkcmVzc2VzIHJl
Z2lzdGVyZWQgdG8gYSBQQ0kgaG9zdA0KPiBicmlkZ2UuDQo+ID4gPiA+DQo+ID4gPiA+IE9rIHNv
IGhlcmUgeW91IGFyZSB0YWxraW5nIGFib3V0IGEgcGxhdGZvcm0gdGhhdCBoYXMgZ290IGFuIEkv
Tw0KPiByYW5nZQ0KPiA+ID4gPiB1bmRlciB0aGUgUENJIGhvc3QgY29udHJvbGxlciwgcmlnaHQ/
DQo+ID4gPiA+IEFuZCB0aGlzIEkvTyByYW5nZSBjYW5ub3QgYmUgZGlyZWN0bHkgbWVtb3J5IG1h
cHBlZCBidXQgbmVlZHMNCj4gc3BlY2lhbA0KPiA+ID4gPiByZWRpcmVjdGlvbnMgZm9yIHRoZSBJ
L08gdG9rZW5zLCByaWdodD8NCj4gPiA+ID4NCj4gPiA+ID4gSW4gdGhpcyBzY2VuYXJpbyByZWdp
c3RlcmluZyB0aGUgSS9PIHJhbmdlcyB3aXRoIHRoZSBmb3JiaWRkZW4NCj4gcmFuZ2UNCj4gPiA+
ID4gaW1wbGVtZW50ZWQgYnkgdGhlIGN1cnJlbnQgcGF0Y2ggd291bGQgc3RpbGwgYWxsb3cgdG8g
cmVkaXJlY3QNCj4gSS9PDQo+ID4gPiA+IHRva2VucyBhcyBsb25nIGFzIGFybTY0X2V4dGlvX29w
cy0+c3RhcnQgPj0gUENJQklPU19NSU5fSU8NCj4gPiA+ID4NCj4gPiA+ID4gU28gZWZmZWN0aXZl
bHkgdGhlIHNwZWNpYWwgUENJIGhvc3QgY29udHJvbGxlcg0KPiA+ID4gPiAxKSBrbm93cyB0aGUg
cGh5c2ljYWwgcmFuZ2UgdGhhdCBuZWVkcyBzcGVjaWFsIHJlZGlyZWN0aW9uDQo+ID4gPiA+IDIp
IHJlZ2lzdGVyIHN1Y2ggcmFuZ2UNCj4gPiA+ID4gMykgdXNlcyBwY2lfcGlvX3RvX2FkZHJlc3Mo
KSB0byByZXRyaWV2ZSB0aGUgSU8gdG9rZW5zIGZvciB0aGUNCj4gPiA+ID4gICAgc3BlY2lhbCBh
Y2Nlc3NvcnMNCj4gPiA+ID4gNCkgc2V0cyBhcm02NF9leHRpb19vcHMtPnN0YXJ0L2VuZCB0byB0
aGUgSU8gdG9rZW5zIHJldHJpZXZlZCBpbg0KPiAzKQ0KPiA+ID4gPg0KPiA+ID4gPiBTbyB0byBi
ZSBob25lc3QgSSB0aGluayB0aGlzIHBhdGNoIGNhbiBmaXQgd2VsbCBib3RoIHdpdGgNCj4gPiA+
ID4gc3BlY2lhbCBQQ0kgY29udHJvbGxlcnMgdGhhdCBuZWVkIEkvTyB0b2tlbnMgcmVkaXJlY3Rp
b24gYW5kIHdpdGgNCj4gPiA+ID4gc3BlY2lhbCBub24tUENJIGNvbnRyb2xsZXJzIHRoYXQgbmVl
ZCBub24tUENJIEkvTyBwaHlzaWNhbA0KPiA+ID4gPiBhZGRyZXNzIHJlZGlyZWN0aW9uLi4uDQo+
ID4gPiA+DQo+ID4gPiA+IFRoYW5rcyAoYW5kIHNvcnJ5IGZvciB0aGUgbG9uZyByZXBseSBidXQg
SSBkaWRuJ3Qga25vdyBob3cNCj4gPiA+ID4gdG8gbWFrZSB0aGUgZXhwbGFuYXRpb24gc2hvcnRl
ciA6KSApDQo+ID4gPiA+DQo+ID4gPiA+IEdhYg0KPiA+ID4gPg0KPiA+ID4gPiA+DQo+ID4gPiA+
ID4gSWYgd2Ugc2VwYXJhdGUgdGhlIHR3byBzdGVwczoNCj4gPiA+ID4gPg0KPiA+ID4gPiA+IGEp
IGFzc2lnbiBhIHJhbmdlIG9mIGxvZ2ljYWwgSS9PIHBvcnQgbnVtYmVycyB0byBhIGJ1cw0KPiA+
ID4gPiA+IGIpIHJlZ2lzdGVyIGEgc2V0IG9mIGhlbHBlcnMgZm9yIHJlZGlyZWN0aW5nIGxvZ2lj
YWwgSS9PDQo+ID4gPiA+ID4gICAgcG9ydCB0byBhIGhlbHBlciBmdW5jdGlvbg0KPiA+ID4gPiA+
DQo+ID4gPiA+ID4gdGhlbiBJIHRoaW5rIHRoZSBjb2RlIHdpbGwgZ2V0IGNsZWFuZXIgYW5kIG1v
cmUgZmxleGlibGUuDQo+ID4gPiA+ID4gSXQgc2hvdWxkIGFjdHVhbGx5IHRoZW4gYmUgYWJsZSB0
byByZXBsYWNlIHRoZSBwb3dlcnBjDQo+ID4gPiA+ID4gc3BlY2lmaWMgaW1wbGVtZW50YXRpb24u
DQo+ID4gPiA+ID4NCj4gPiA+ID4gPiAJQXJuZA0KPiA+ID4NCj4gPiA+IC0tDQo+ID4gPiA9PT09
PT09PT09PT09PT09PT09PQ0KPiA+ID4gfCBJIHdvdWxkIGxpa2UgdG8gfA0KPiA+ID4gfCBmaXgg
dGhlIHdvcmxkLCAgfA0KPiA+ID4gfCBidXQgdGhleSdyZSBub3QgfA0KPiA+ID4gfCBnaXZpbmcg
bWUgdGhlICAgfA0KPiA+ID4gIFwgc291cmNlIGNvZGUhICAvDQo+ID4gPiAgIC0tLS0tLS0tLS0t
LS0tLQ0KPiA+ID4gICAgIMKvXF8o44OEKV8vwq8NCj4gDQo+IC0tDQo+ID09PT09PT09PT09PT09
PT09PT09DQo+IHwgSSB3b3VsZCBsaWtlIHRvIHwNCj4gfCBmaXggdGhlIHdvcmxkLCAgfA0KPiB8
IGJ1dCB0aGV5J3JlIG5vdCB8DQo+IHwgZ2l2aW5nIG1lIHRoZSAgIHwNCj4gIFwgc291cmNlIGNv
ZGUhICAvDQo+ICAgLS0tLS0tLS0tLS0tLS0tDQo+ICAgICDCr1xfKOODhClfL8KvDQo=

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-14  8:26                           ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-14  8:26 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Liviu

> -----Original Message-----
> From: liviu.dudau at arm.com [mailto:liviu.dudau at arm.com]
> Sent: 11 November 2016 18:16
> To: Gabriele Paoloni
> Cc: Arnd Bergmann; linux-arm-kernel at lists.infradead.org; Yuanzhichang;
> mark.rutland at arm.com; devicetree at vger.kernel.org;
> lorenzo.pieralisi at arm.com; minyard at acm.org; linux-pci at vger.kernel.org;
> benh at kernel.crashing.org; John Garry; will.deacon at arm.com; linux-
> kernel at vger.kernel.org; xuwei (O); Linuxarm; zourongrong at gmail.com;
> robh+dt at kernel.org; kantyzc at 163.com; linux-serial at vger.kernel.org;
> catalin.marinas at arm.com; olof at lixom.net; bhelgaas at googl e.com;
> zhichang.yuan02 at gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Fri, Nov 11, 2016 at 03:53:53PM +0000, Gabriele Paoloni wrote:
> > Hi Liviu
> 
> Hi Gabriele,
> 
> >
> > > -----Original Message-----
> > > From: liviu.dudau at arm.com [mailto:liviu.dudau at arm.com]
> > > Sent: 11 November 2016 14:46
> > > To: Gabriele Paoloni
> > > Cc: Arnd Bergmann; linux-arm-kernel at lists.infradead.org;
> Yuanzhichang;
> > > mark.rutland at arm.com; devicetree at vger.kernel.org;
> > > lorenzo.pieralisi at arm.com; minyard at acm.org; linux-
> pci at vger.kernel.org;
> > > benh at kernel.crashing.org; John Garry; will.deacon at arm.com; linux-
> > > kernel at vger.kernel.org; xuwei (O); Linuxarm; zourongrong at gmail.com;
> > > robh+dt at kernel.org; kantyzc at 163.com; linux-serial at vger.kernel.org;
> > > catalin.marinas at arm.com; olof at lixom.net; bhelgaas at googl e.com;
> > > zhichang.yuan02 at gmail.com
> > > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> > > Hip06
> > >
> > > On Fri, Nov 11, 2016 at 01:39:35PM +0000, Gabriele Paoloni wrote:
> > > > Hi Arnd
> > > >
> > > > > -----Original Message-----
> > > > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > > > Sent: 10 November 2016 16:07
> > > > > To: Gabriele Paoloni
> > > > > Cc: linux-arm-kernel at lists.infradead.org; Yuanzhichang;
> > > > > mark.rutland at arm.com; devicetree at vger.kernel.org;
> > > > > lorenzo.pieralisi at arm.com; minyard at acm.org; linux-
> > > pci at vger.kernel.org;
> > > > > benh at kernel.crashing.org; John Garry; will.deacon at arm.com;
> linux-
> > > > > kernel at vger.kernel.org; xuwei (O); Linuxarm;
> zourongrong at gmail.com;
> > > > > robh+dt at kernel.org; kantyzc at 163.com; linux-
> serial at vger.kernel.org;
> > > > > catalin.marinas at arm.com; olof at lixom.net; liviu.dudau at arm.com;
> > > > > bhelgaas at googl e.com; zhichang.yuan02 at gmail.com
> > > > > Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver
> implementation on
> > > > > Hip06
> > > > >
> > > > > On Thursday, November 10, 2016 3:36:49 PM CET Gabriele Paoloni
> > > wrote:
> > > > > >
> > > > > > Where should we get the range from? For LPC we know that it
> is
> > > going
> > > > > > Work on anything that is not used by PCI I/O space, and this
> is
> > > > > > why we use [0, PCIBIOS_MIN_IO]
> > > > >
> > > > > It should be allocated the same way we allocate PCI config
> space
> > > > > segments. This is currently done with the io_range list in
> > > > > drivers/pci/pci.c, which isn't perfect but could be extended
> > > > > if necessary. Based on what others commented here, I'd rather
> > > > > make the differences between ISA/LPC and PCI I/O ranges smaller
> > > > > than larger.
> > >
> > > Gabriele,
> > >
> > > >
> > > > I am not sure this would make sense...
> > > >
> > > > IMHO all the mechanism around io_range_list is needed to provide
> the
> > > > "mapping" between I/O tokens and physical CPU addresses.
> > > >
> > > > Currently the available tokens range from 0 to IO_SPACE_LIMIT.
> > > >
> > > > As you know the I/O memory accessors operate on whatever
> > > > __of_address_to_resource sets into the resource (start, end).
> > > >
> > > > With this special device in place we cannot know if a resource is
> > > > assigned with an I/O token or a physical address, unless we
> forbid
> > > > the I/O tokens to be in a specific range.
> > > >
> > > > So this is why we are changing the offsets of all the functions
> > > > handling io_range_list (to make sure that a range is forbidden to
> > > > the tokens and is available to the physical addresses).
> > > >
> > > > We have chosen this forbidden range to be [0, PCIBIOS_MIN_IO)
> > > > because this is the maximum physical I/O range that a non PCI
> device
> > > > can operate on and because we believe this does not impose much
> > > > restriction on the available I/O token range; that now is
> > > > [PCIBIOS_MIN_IO, IO_SPACE_LIMIT].
> > > > So we believe that the chosen forbidden range can accommodate
> > > > any special ISA bus device with no much constraint on the rest
> > > > of I/O tokens...
> > >
> > > Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and
> you
> > > actually need another variable for "reserving" an area in the I/O
> space
> > > that can be used for physical addresses rather than I/O tokens.
> > >
> > > The one good example for using PCIBIOS_MIN_IO is when your
> > > platform/architecture
> > > does not support legacy ISA operations *at all*. In that case
> someone
> > > sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O
> range
> > > so that it doesn't get used. With Zhichang's patch you now start
> > > forcing
> > > those platforms to have a valid address below PCIBIOS_MIN_IO.
> >
> > But if PCIBIOS_MIN_IO is 0 then it means that all I/O space is to be
> used
> > by PCI controllers only...
> 
> Nope, that is not what it means. It means that PCI devices can see I/O
> addresses
> on the bus that start from 0. There never was any usage for non-PCI
> controllers

So I am a bit confused...
>From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
It seems that ISA buses operate on cpu I/O address range [0, 0xFFF].
I thought that was the reason why for most architectures we have
PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA controllers
usually use [0, PCIBIOS_MIN_IO - 1] )

For those architectures whose PCIBIOS_MIN_IO != 0x1000 probably
they are not fully compliant or they cannot fully support an ISA
controller...?

As said before this series forbid IO tokens to be in [0, PCIBIOS_MIN_IO)
to allow special ISA controllers to use that range with special
accessors.
Having a variable threshold would make life much more difficult
as there would be a probe dependency between the PCI controller and
the special ISA one (PCI to wait for the special ISA device to be
probed and set the right threshold value from DT or ACPI table).

Instead using PCIBIOS_MIN_IO is easier and should not impose much
constraint as [PCIBIOS_MIN_IO, IO_SPACE_LIMIT] is available to
the PCI controller for I/O tokens...

Thanks

Gab

> when PCIBIOS_MIN_IO != 0. That is what Zhichang is trying to do now and
> what
> I think is not the right thing (and not enough anyway).
> 
> > so if you have a special bus device using
> > an I/O range in this case should be a PCI controller...
> 
> That has always been the case. It is this series that wants to
> introduce the
> new meaning.
> 
> > i.e. I would
> > expect it to fall back into the case of I/O tokens redirection rather
> than
> > physical addresses redirection (as mentioned below from my previous
> reply).
> > What do you think?
> 
> I think you have looked too much at the code *with* Zhichang's patches
> applied.
> Take a step back and look at how PCIBIOS_MIN_IO is used now, before you
> apply
> the patches. It is all about PCI addresses and there is no notion of
> non-PCI
> busses using PCI framework. Only platforms and architectures that try
> to work
> around some legacy standards (ISA) or HW restrictions.
> 
> Best regards,
> Liviu
> 
> >
> > Thanks
> >
> > Gab
> >
> >
> > >
> > > For the general case you also have to bear in mind that
> PCIBIOS_MIN_IO
> > > could
> > > be zero. In that case, what is your "forbidden" range? [0, 0) ? So
> it
> > > makes
> > > sense to add a new #define that should only be defined by those
> > > architectures/
> > > platforms that want to reserve on top of PCIBIOS_MIN_IO another
> region
> > > where I/O tokens can't be generated for.
> > >
> > > Best regards,
> > > Liviu
> > >
> > > >
> > > > >
> > > > > > > Your current version has
> > > > > > >
> > > > > > >         if (arm64_extio_ops->pfout)
> > > \
> > > > > > >                 arm64_extio_ops->pfout(arm64_extio_ops-
> > > >devpara,\
> > > > > > >                        addr, value, sizeof(type));
> > > \
> > > > > > >
> > > > > > > Instead, just subtract the start of the range from the
> logical
> > > > > > > port number to transform it back into a bus-local port
> number:
> > > > > >
> > > > > > These accessors do not operate on IO tokens:
> > > > > >
> > > > > > If (arm64_extio_ops->start > addr || arm64_extio_ops->end <
> addr)
> > > > > > addr is not going to be an I/O token; in fact patch 2/3
> imposes
> > > that
> > > > > > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> > > > > PCIBIOS_MIN_IO
> > > > > > we have free physical addresses that the accessors can
> operate
> > > on.
> > > > >
> > > > > Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to
> refer
> > > to
> > > > > the logical I/O tokens, the purpose of that macro is really
> meant
> > > > > for allocating PCI I/O port numbers within the address space of
> > > > > one bus.
> > > >
> > > > As I mentioned above, special devices operate on CPU addresses
> > > directly,
> > > > not I/O tokens. For them there is no way to distinguish....
> > > >
> > > > >
> > > > > Note that it's equally likely that whichever next platform
> needs
> > > > > non-mapped I/O access like this actually needs them for PCI I/O
> > > space,
> > > > > and that will use it on addresses registered to a PCI host
> bridge.
> > > >
> > > > Ok so here you are talking about a platform that has got an I/O
> range
> > > > under the PCI host controller, right?
> > > > And this I/O range cannot be directly memory mapped but needs
> special
> > > > redirections for the I/O tokens, right?
> > > >
> > > > In this scenario registering the I/O ranges with the forbidden
> range
> > > > implemented by the current patch would still allow to redirect
> I/O
> > > > tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
> > > >
> > > > So effectively the special PCI host controller
> > > > 1) knows the physical range that needs special redirection
> > > > 2) register such range
> > > > 3) uses pci_pio_to_address() to retrieve the IO tokens for the
> > > >    special accessors
> > > > 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in
> 3)
> > > >
> > > > So to be honest I think this patch can fit well both with
> > > > special PCI controllers that need I/O tokens redirection and with
> > > > special non-PCI controllers that need non-PCI I/O physical
> > > > address redirection...
> > > >
> > > > Thanks (and sorry for the long reply but I didn't know how
> > > > to make the explanation shorter :) )
> > > >
> > > > Gab
> > > >
> > > > >
> > > > > If we separate the two steps:
> > > > >
> > > > > a) assign a range of logical I/O port numbers to a bus
> > > > > b) register a set of helpers for redirecting logical I/O
> > > > >    port to a helper function
> > > > >
> > > > > then I think the code will get cleaner and more flexible.
> > > > > It should actually then be able to replace the powerpc
> > > > > specific implementation.
> > > > >
> > > > > 	Arnd
> > >
> > > --
> > > ====================
> > > | I would like to |
> > > | fix the world,  |
> > > | but they're not |
> > > | giving me the   |
> > >  \ source code!  /
> > >   ---------------
> > >     ?\_(?)_/?
> 
> --
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ?\_(?)_/?

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-09 21:34         ` Arnd Bergmann
  (?)
@ 2016-11-14 11:06           ` One Thousand Gnomes
  -1 siblings, 0 replies; 286+ messages in thread
From: One Thousand Gnomes @ 2016-11-14 11:06 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, Gabriele Paoloni, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, benh, minyard, catalin.marinas,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, olof, robh+dt, zourongrong, linux-serial, linux-pci,
	bhelgaas, liviu.dudau, kantyzc, zhichang.yuan02

On Wed, 09 Nov 2016 22:34:38 +0100
Arnd Bergmann <arnd@arndb.de> wrote:

> On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni wrote:
> > > On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:  
> > > > +       /*
> > > > +        * The first PCIBIOS_MIN_IO is reserved specifically for  
> > > indirectIO.  
> > > > +        * It will separate indirectIO range from pci host bridge to
> > > > +        * avoid the possible PIO conflict.
> > > > +        * Set the indirectIO range directly here.
> > > > +        */
> > > > +       lpcdev->io_ops.start = 0;
> > > > +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> > > > +       lpcdev->io_ops.devpara = lpcdev;
> > > > +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> > > > +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> > > > +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> > > > +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;  
> > > 
> > > I have to look at patch 2 in more detail again, after missing a few
> > > review
> > > rounds. I'm still a bit skeptical about hardcoding a logical I/O port
> > > range here, and would hope that we can just go through the same
> > > assignment of logical port ranges that we have for PCI buses,
> > > decoupling
> > > the bus addresses from the linux-internal ones.  
> > 
> > The point here is that we want to avoid any conflict/overlap between
> > the LPC I/O space and the PCI I/O space. With the assignment above
> > we make sure that LPC never interfere with PCI I/O space.  
> 
> But we already abstract the PCI I/O space using dynamic registration.
> There is no need to hardcode the logical address for ISA, though
> I think we can hardcode the bus address to start at zero here.

Pedantically ISA starts at 0x100. The LPC may start at 0x00 as it also
covers motherboard devices (0x00-0xFF). It is also possible that the
'LPC' space is only partially routed to the PCI bridges because some if
it magially disappears on CPU die (at least on x86) and has done since
the era of socket 7 (eg the Cyrix 6x86 doesn't route 0x22/0x23 out of the
CPU).

Assuming LPC starts at 0 ought to be ok given the PCI root bridge
shouldn't see the transactions.

The LPC or it's equivalent may also not be routed via the PCI bridges at
all, so you could have an LPC mapping that is unused or partially used
with another bus actually getting some classes of LPC traffic - on x86 at
least.

Alan

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-14 11:06           ` One Thousand Gnomes
  0 siblings, 0 replies; 286+ messages in thread
From: One Thousand Gnomes @ 2016-11-14 11:06 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Gabriele Paoloni, Yuanzhichang, mark.rutland-5wv7dgnIgG8,
	devicetree-u79uwXL29TY76Z2rM5mHXA, lorenzo.pieralisi-5wv7dgnIgG8,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, minyard-HInyCGIudOg,
	catalin.marinas-5wv7dgnIgG8, John Garry, will.deacon-5wv7dgnIgG8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, xuwei (O),
	Linuxarm, olof-nZhT3qVonbNeoWH0uzbU5w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w

On Wed, 09 Nov 2016 22:34:38 +0100
Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:

> On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni wrote:
> > > On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:  
> > > > +       /*
> > > > +        * The first PCIBIOS_MIN_IO is reserved specifically for  
> > > indirectIO.  
> > > > +        * It will separate indirectIO range from pci host bridge to
> > > > +        * avoid the possible PIO conflict.
> > > > +        * Set the indirectIO range directly here.
> > > > +        */
> > > > +       lpcdev->io_ops.start = 0;
> > > > +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> > > > +       lpcdev->io_ops.devpara = lpcdev;
> > > > +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> > > > +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> > > > +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> > > > +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;  
> > > 
> > > I have to look at patch 2 in more detail again, after missing a few
> > > review
> > > rounds. I'm still a bit skeptical about hardcoding a logical I/O port
> > > range here, and would hope that we can just go through the same
> > > assignment of logical port ranges that we have for PCI buses,
> > > decoupling
> > > the bus addresses from the linux-internal ones.  
> > 
> > The point here is that we want to avoid any conflict/overlap between
> > the LPC I/O space and the PCI I/O space. With the assignment above
> > we make sure that LPC never interfere with PCI I/O space.  
> 
> But we already abstract the PCI I/O space using dynamic registration.
> There is no need to hardcode the logical address for ISA, though
> I think we can hardcode the bus address to start at zero here.

Pedantically ISA starts at 0x100. The LPC may start at 0x00 as it also
covers motherboard devices (0x00-0xFF). It is also possible that the
'LPC' space is only partially routed to the PCI bridges because some if
it magially disappears on CPU die (at least on x86) and has done since
the era of socket 7 (eg the Cyrix 6x86 doesn't route 0x22/0x23 out of the
CPU).

Assuming LPC starts at 0 ought to be ok given the PCI root bridge
shouldn't see the transactions.

The LPC or it's equivalent may also not be routed via the PCI bridges at
all, so you could have an LPC mapping that is unused or partially used
with another bus actually getting some classes of LPC traffic - on x86 at
least.

Alan
--
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] 286+ messages in thread

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-14 11:06           ` One Thousand Gnomes
  0 siblings, 0 replies; 286+ messages in thread
From: One Thousand Gnomes @ 2016-11-14 11:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 09 Nov 2016 22:34:38 +0100
Arnd Bergmann <arnd@arndb.de> wrote:

> On Wednesday, November 9, 2016 12:10:43 PM CET Gabriele Paoloni wrote:
> > > On Tuesday, November 8, 2016 11:47:09 AM CET zhichang.yuan wrote:  
> > > > +       /*
> > > > +        * The first PCIBIOS_MIN_IO is reserved specifically for  
> > > indirectIO.  
> > > > +        * It will separate indirectIO range from pci host bridge to
> > > > +        * avoid the possible PIO conflict.
> > > > +        * Set the indirectIO range directly here.
> > > > +        */
> > > > +       lpcdev->io_ops.start = 0;
> > > > +       lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
> > > > +       lpcdev->io_ops.devpara = lpcdev;
> > > > +       lpcdev->io_ops.pfin = hisilpc_comm_in;
> > > > +       lpcdev->io_ops.pfout = hisilpc_comm_out;
> > > > +       lpcdev->io_ops.pfins = hisilpc_comm_ins;
> > > > +       lpcdev->io_ops.pfouts = hisilpc_comm_outs;  
> > > 
> > > I have to look at patch 2 in more detail again, after missing a few
> > > review
> > > rounds. I'm still a bit skeptical about hardcoding a logical I/O port
> > > range here, and would hope that we can just go through the same
> > > assignment of logical port ranges that we have for PCI buses,
> > > decoupling
> > > the bus addresses from the linux-internal ones.  
> > 
> > The point here is that we want to avoid any conflict/overlap between
> > the LPC I/O space and the PCI I/O space. With the assignment above
> > we make sure that LPC never interfere with PCI I/O space.  
> 
> But we already abstract the PCI I/O space using dynamic registration.
> There is no need to hardcode the logical address for ISA, though
> I think we can hardcode the bus address to start at zero here.

Pedantically ISA starts at 0x100. The LPC may start at 0x00 as it also
covers motherboard devices (0x00-0xFF). It is also possible that the
'LPC' space is only partially routed to the PCI bridges because some if
it magially disappears on CPU die (at least on x86) and has done since
the era of socket 7 (eg the Cyrix 6x86 doesn't route 0x22/0x23 out of the
CPU).

Assuming LPC starts at 0 ought to be ok given the PCI root bridge
shouldn't see the transactions.

The LPC or it's equivalent may also not be routed via the PCI bridges at
all, so you could have an LPC mapping that is unused or partially used
with another bus actually getting some classes of LPC traffic - on x86 at
least.

Alan

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
  2016-11-09 21:38           ` Arnd Bergmann
  (?)
@ 2016-11-14 11:11             ` One Thousand Gnomes
  -1 siblings, 0 replies; 286+ messages in thread
From: One Thousand Gnomes @ 2016-11-14 11:11 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Mark Rutland, zhichang.yuan, catalin.marinas, will.deacon,
	robh+dt, bhelgaas, olof, linux-arm-kernel, lorenzo.pieralisi,
	linux-kernel, linuxarm, devicetree, linux-pci, linux-serial,
	minyard, benh, liviu.dudau, zourongrong, john.garry,
	gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5, marc.zyngier

> > It's not a safe assumption for x86 at least. There are a few systems with
> > multiple ISA busses particularly older laptops with a docking station.  
> 
> But do they have multiple ISA domains? There is no real harm in supporting
> it, the (small) downsides I can think of are:

I don't believe they x86 class ones have multiple ISA domains. But as
I've said I don't know how the electronics in the older ThinkPad worked
when it used two PIIX4s with some LPC or ISA stuff on each.

It works in DOS and unmodified Linux so I'm pretty sure there are no
additional domains. Likewise the various x86 schemes that route some bits
of ISA bus off into strange places work in DOS and don't have any
overlaps.

yenta_socket handles PCI/PCMCIA bridging and routes a range of that flat
ISA space appropriately to the card.

Alan

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-14 11:11             ` One Thousand Gnomes
  0 siblings, 0 replies; 286+ messages in thread
From: One Thousand Gnomes @ 2016-11-14 11:11 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Mark Rutland, zhichang.yuan, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, olof-nZhT3qVonbNeoWH0uzbU5w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	lorenzo.pieralisi-5wv7dgnIgG8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linuxarm-hv44wF8Li93QT0dZR+AlfA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA, minyard-HInyCGIudOg,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, liviu.dudau-5wv7dgnIgG8,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
	john.garry-hv44wF8Li93QT0dZR+AlfA,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w, kantyzc-9Onoh4P/yGk,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q, marc.zyngier-5wv7dgnIgG8

> > It's not a safe assumption for x86 at least. There are a few systems with
> > multiple ISA busses particularly older laptops with a docking station.  
> 
> But do they have multiple ISA domains? There is no real harm in supporting
> it, the (small) downsides I can think of are:

I don't believe they x86 class ones have multiple ISA domains. But as
I've said I don't know how the electronics in the older ThinkPad worked
when it used two PIIX4s with some LPC or ISA stuff on each.

It works in DOS and unmodified Linux so I'm pretty sure there are no
additional domains. Likewise the various x86 schemes that route some bits
of ISA bus off into strange places work in DOS and don't have any
overlaps.

yenta_socket handles PCI/PCMCIA bridging and routes a range of that flat
ISA space appropriately to the card.

Alan
--
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] 286+ messages in thread

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-14 11:11             ` One Thousand Gnomes
  0 siblings, 0 replies; 286+ messages in thread
From: One Thousand Gnomes @ 2016-11-14 11:11 UTC (permalink / raw)
  To: linux-arm-kernel

> > It's not a safe assumption for x86 at least. There are a few systems with
> > multiple ISA busses particularly older laptops with a docking station.  
> 
> But do they have multiple ISA domains? There is no real harm in supporting
> it, the (small) downsides I can think of are:

I don't believe they x86 class ones have multiple ISA domains. But as
I've said I don't know how the electronics in the older ThinkPad worked
when it used two PIIX4s with some LPC or ISA stuff on each.

It works in DOS and unmodified Linux so I'm pretty sure there are no
additional domains. Likewise the various x86 schemes that route some bits
of ISA bus off into strange places work in DOS and don't have any
overlaps.

yenta_socket handles PCI/PCMCIA bridging and routes a range of that flat
ISA space appropriately to the card.

Alan

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-14  8:26                           ` Gabriele Paoloni
  (?)
  (?)
@ 2016-11-14 11:26                             ` liviu.dudau
  -1 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau @ 2016-11-14 11:26 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Arnd Bergmann, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, bhelgaas@googl e.com, zhichang.yuan02

On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> Hi Liviu
> 

[snip]

> > > >
> > > > Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and
> > you
> > > > actually need another variable for "reserving" an area in the I/O
> > space
> > > > that can be used for physical addresses rather than I/O tokens.
> > > >
> > > > The one good example for using PCIBIOS_MIN_IO is when your
> > > > platform/architecture
> > > > does not support legacy ISA operations *at all*. In that case
> > someone
> > > > sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O
> > range
> > > > so that it doesn't get used. With Zhichang's patch you now start
> > > > forcing
> > > > those platforms to have a valid address below PCIBIOS_MIN_IO.
> > >
> > > But if PCIBIOS_MIN_IO is 0 then it means that all I/O space is to be
> > used
> > > by PCI controllers only...
> > 
> > Nope, that is not what it means. It means that PCI devices can see I/O
> > addresses
> > on the bus that start from 0. There never was any usage for non-PCI
> > controllers
> 
> So I am a bit confused...
> From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> It seems that ISA buses operate on cpu I/O address range [0, 0xFFF].
> I thought that was the reason why for most architectures we have
> PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA controllers
> usually use [0, PCIBIOS_MIN_IO - 1] )

First of all, cpu I/O addresses is an x86-ism. ARM architectures and others
 have no separate address space for I/O, it is all merged into one unified
address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0 could mean
that we don't care about ISA I/O because the platform does not support having
an ISA bus (e.g.).


> 
> For those architectures whose PCIBIOS_MIN_IO != 0x1000 probably
> they are not fully compliant or they cannot fully support an ISA
> controller...?

Exactly. Not fully compliant is a bit strong, as ISA is a legacy feature and
when it comes to PCI-e you are allowed to ignore it. Having PCIBIOS_MIN_IO != 0x1000
is a way to signal that you don't fully support ISA.

> 
> As said before this series forbid IO tokens to be in [0, PCIBIOS_MIN_IO)
> to allow special ISA controllers to use that range with special
> accessors.
> Having a variable threshold would make life much more difficult
> as there would be a probe dependency between the PCI controller and
> the special ISA one (PCI to wait for the special ISA device to be
> probed and set the right threshold value from DT or ACPI table).
> 
> Instead using PCIBIOS_MIN_IO is easier and should not impose much
> constraint as [PCIBIOS_MIN_IO, IO_SPACE_LIMIT] is available to
> the PCI controller for I/O tokens...

What I am suggesting is to leave PCIBIOS_MIN_IO alone which still reserves
space for ISA controller and add a PCIBIOS_MIN_DIRECT_IO that will reserve
space for your direct address I/O on top of PCIBIOS_MIN_IO.

Best regards,
Liviu

> 
> Thanks
> 
> Gab
> 
> > when PCIBIOS_MIN_IO != 0. That is what Zhichang is trying to do now and
> > what
> > I think is not the right thing (and not enough anyway).
> > 
> > > so if you have a special bus device using
> > > an I/O range in this case should be a PCI controller...
> > 
> > That has always been the case. It is this series that wants to
> > introduce the
> > new meaning.
> > 
> > > i.e. I would
> > > expect it to fall back into the case of I/O tokens redirection rather
> > than
> > > physical addresses redirection (as mentioned below from my previous
> > reply).
> > > What do you think?
> > 
> > I think you have looked too much at the code *with* Zhichang's patches
> > applied.
> > Take a step back and look at how PCIBIOS_MIN_IO is used now, before you
> > apply
> > the patches. It is all about PCI addresses and there is no notion of
> > non-PCI
> > busses using PCI framework. Only platforms and architectures that try
> > to work
> > around some legacy standards (ISA) or HW restrictions.
> > 
> > Best regards,
> > Liviu
> > 
> > >
> > > Thanks
> > >
> > > Gab
> > >
> > >
> > > >
> > > > For the general case you also have to bear in mind that
> > PCIBIOS_MIN_IO
> > > > could
> > > > be zero. In that case, what is your "forbidden" range? [0, 0) ? So
> > it
> > > > makes
> > > > sense to add a new #define that should only be defined by those
> > > > architectures/
> > > > platforms that want to reserve on top of PCIBIOS_MIN_IO another
> > region
> > > > where I/O tokens can't be generated for.
> > > >
> > > > Best regards,
> > > > Liviu
> > > >
> > > > >
> > > > > >
> > > > > > > > Your current version has
> > > > > > > >
> > > > > > > >         if (arm64_extio_ops->pfout)
> > > > \
> > > > > > > >                 arm64_extio_ops->pfout(arm64_extio_ops-
> > > > >devpara,\
> > > > > > > >                        addr, value, sizeof(type));
> > > > \
> > > > > > > >
> > > > > > > > Instead, just subtract the start of the range from the
> > logical
> > > > > > > > port number to transform it back into a bus-local port
> > number:
> > > > > > >
> > > > > > > These accessors do not operate on IO tokens:
> > > > > > >
> > > > > > > If (arm64_extio_ops->start > addr || arm64_extio_ops->end <
> > addr)
> > > > > > > addr is not going to be an I/O token; in fact patch 2/3
> > imposes
> > > > that
> > > > > > > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> > > > > > PCIBIOS_MIN_IO
> > > > > > > we have free physical addresses that the accessors can
> > operate
> > > > on.
> > > > > >
> > > > > > Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to
> > refer
> > > > to
> > > > > > the logical I/O tokens, the purpose of that macro is really
> > meant
> > > > > > for allocating PCI I/O port numbers within the address space of
> > > > > > one bus.
> > > > >
> > > > > As I mentioned above, special devices operate on CPU addresses
> > > > directly,
> > > > > not I/O tokens. For them there is no way to distinguish....
> > > > >
> > > > > >
> > > > > > Note that it's equally likely that whichever next platform
> > needs
> > > > > > non-mapped I/O access like this actually needs them for PCI I/O
> > > > space,
> > > > > > and that will use it on addresses registered to a PCI host
> > bridge.
> > > > >
> > > > > Ok so here you are talking about a platform that has got an I/O
> > range
> > > > > under the PCI host controller, right?
> > > > > And this I/O range cannot be directly memory mapped but needs
> > special
> > > > > redirections for the I/O tokens, right?
> > > > >
> > > > > In this scenario registering the I/O ranges with the forbidden
> > range
> > > > > implemented by the current patch would still allow to redirect
> > I/O
> > > > > tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
> > > > >
> > > > > So effectively the special PCI host controller
> > > > > 1) knows the physical range that needs special redirection
> > > > > 2) register such range
> > > > > 3) uses pci_pio_to_address() to retrieve the IO tokens for the
> > > > >    special accessors
> > > > > 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in
> > 3)
> > > > >
> > > > > So to be honest I think this patch can fit well both with
> > > > > special PCI controllers that need I/O tokens redirection and with
> > > > > special non-PCI controllers that need non-PCI I/O physical
> > > > > address redirection...
> > > > >
> > > > > Thanks (and sorry for the long reply but I didn't know how
> > > > > to make the explanation shorter :) )
> > > > >
> > > > > Gab
> > > > >
> > > > > >
> > > > > > If we separate the two steps:
> > > > > >
> > > > > > a) assign a range of logical I/O port numbers to a bus
> > > > > > b) register a set of helpers for redirecting logical I/O
> > > > > >    port to a helper function
> > > > > >
> > > > > > then I think the code will get cleaner and more flexible.
> > > > > > It should actually then be able to replace the powerpc
> > > > > > specific implementation.
> > > > > >
> > > > > > 	Arnd

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

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-14 11:26                             ` liviu.dudau
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau @ 2016-11-14 11:26 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Arnd Bergmann, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt

On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> Hi Liviu
> 

[snip]

> > > >
> > > > Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and
> > you
> > > > actually need another variable for "reserving" an area in the I/O
> > space
> > > > that can be used for physical addresses rather than I/O tokens.
> > > >
> > > > The one good example for using PCIBIOS_MIN_IO is when your
> > > > platform/architecture
> > > > does not support legacy ISA operations *at all*. In that case
> > someone
> > > > sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O
> > range
> > > > so that it doesn't get used. With Zhichang's patch you now start
> > > > forcing
> > > > those platforms to have a valid address below PCIBIOS_MIN_IO.
> > >
> > > But if PCIBIOS_MIN_IO is 0 then it means that all I/O space is to be
> > used
> > > by PCI controllers only...
> > 
> > Nope, that is not what it means. It means that PCI devices can see I/O
> > addresses
> > on the bus that start from 0. There never was any usage for non-PCI
> > controllers
> 
> So I am a bit confused...
> From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> It seems that ISA buses operate on cpu I/O address range [0, 0xFFF].
> I thought that was the reason why for most architectures we have
> PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA controllers
> usually use [0, PCIBIOS_MIN_IO - 1] )

First of all, cpu I/O addresses is an x86-ism. ARM architectures and others
 have no separate address space for I/O, it is all merged into one unified
address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0 could mean
that we don't care about ISA I/O because the platform does not support having
an ISA bus (e.g.).


> 
> For those architectures whose PCIBIOS_MIN_IO != 0x1000 probably
> they are not fully compliant or they cannot fully support an ISA
> controller...?

Exactly. Not fully compliant is a bit strong, as ISA is a legacy feature and
when it comes to PCI-e you are allowed to ignore it. Having PCIBIOS_MIN_IO != 0x1000
is a way to signal that you don't fully support ISA.

> 
> As said before this series forbid IO tokens to be in [0, PCIBIOS_MIN_IO)
> to allow special ISA controllers to use that range with special
> accessors.
> Having a variable threshold would make life much more difficult
> as there would be a probe dependency between the PCI controller and
> the special ISA one (PCI to wait for the special ISA device to be
> probed and set the right threshold value from DT or ACPI table).
> 
> Instead using PCIBIOS_MIN_IO is easier and should not impose much
> constraint as [PCIBIOS_MIN_IO, IO_SPACE_LIMIT] is available to
> the PCI controller for I/O tokens...

What I am suggesting is to leave PCIBIOS_MIN_IO alone which still reserves
space for ISA controller and add a PCIBIOS_MIN_DIRECT_IO that will reserve
space for your direct address I/O on top of PCIBIOS_MIN_IO.

Best regards,
Liviu

> 
> Thanks
> 
> Gab
> 
> > when PCIBIOS_MIN_IO != 0. That is what Zhichang is trying to do now and
> > what
> > I think is not the right thing (and not enough anyway).
> > 
> > > so if you have a special bus device using
> > > an I/O range in this case should be a PCI controller...
> > 
> > That has always been the case. It is this series that wants to
> > introduce the
> > new meaning.
> > 
> > > i.e. I would
> > > expect it to fall back into the case of I/O tokens redirection rather
> > than
> > > physical addresses redirection (as mentioned below from my previous
> > reply).
> > > What do you think?
> > 
> > I think you have looked too much at the code *with* Zhichang's patches
> > applied.
> > Take a step back and look at how PCIBIOS_MIN_IO is used now, before you
> > apply
> > the patches. It is all about PCI addresses and there is no notion of
> > non-PCI
> > busses using PCI framework. Only platforms and architectures that try
> > to work
> > around some legacy standards (ISA) or HW restrictions.
> > 
> > Best regards,
> > Liviu
> > 
> > >
> > > Thanks
> > >
> > > Gab
> > >
> > >
> > > >
> > > > For the general case you also have to bear in mind that
> > PCIBIOS_MIN_IO
> > > > could
> > > > be zero. In that case, what is your "forbidden" range? [0, 0) ? So
> > it
> > > > makes
> > > > sense to add a new #define that should only be defined by those
> > > > architectures/
> > > > platforms that want to reserve on top of PCIBIOS_MIN_IO another
> > region
> > > > where I/O tokens can't be generated for.
> > > >
> > > > Best regards,
> > > > Liviu
> > > >
> > > > >
> > > > > >
> > > > > > > > Your current version has
> > > > > > > >
> > > > > > > >         if (arm64_extio_ops->pfout)
> > > > \
> > > > > > > >                 arm64_extio_ops->pfout(arm64_extio_ops-
> > > > >devpara,\
> > > > > > > >                        addr, value, sizeof(type));
> > > > \
> > > > > > > >
> > > > > > > > Instead, just subtract the start of the range from the
> > logical
> > > > > > > > port number to transform it back into a bus-local port
> > number:
> > > > > > >
> > > > > > > These accessors do not operate on IO tokens:
> > > > > > >
> > > > > > > If (arm64_extio_ops->start > addr || arm64_extio_ops->end <
> > addr)
> > > > > > > addr is not going to be an I/O token; in fact patch 2/3
> > imposes
> > > > that
> > > > > > > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> > > > > > PCIBIOS_MIN_IO
> > > > > > > we have free physical addresses that the accessors can
> > operate
> > > > on.
> > > > > >
> > > > > > Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to
> > refer
> > > > to
> > > > > > the logical I/O tokens, the purpose of that macro is really
> > meant
> > > > > > for allocating PCI I/O port numbers within the address space of
> > > > > > one bus.
> > > > >
> > > > > As I mentioned above, special devices operate on CPU addresses
> > > > directly,
> > > > > not I/O tokens. For them there is no way to distinguish....
> > > > >
> > > > > >
> > > > > > Note that it's equally likely that whichever next platform
> > needs
> > > > > > non-mapped I/O access like this actually needs them for PCI I/O
> > > > space,
> > > > > > and that will use it on addresses registered to a PCI host
> > bridge.
> > > > >
> > > > > Ok so here you are talking about a platform that has got an I/O
> > range
> > > > > under the PCI host controller, right?
> > > > > And this I/O range cannot be directly memory mapped but needs
> > special
> > > > > redirections for the I/O tokens, right?
> > > > >
> > > > > In this scenario registering the I/O ranges with the forbidden
> > range
> > > > > implemented by the current patch would still allow to redirect
> > I/O
> > > > > tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
> > > > >
> > > > > So effectively the special PCI host controller
> > > > > 1) knows the physical range that needs special redirection
> > > > > 2) register such range
> > > > > 3) uses pci_pio_to_address() to retrieve the IO tokens for the
> > > > >    special accessors
> > > > > 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in
> > 3)
> > > > >
> > > > > So to be honest I think this patch can fit well both with
> > > > > special PCI controllers that need I/O tokens redirection and with
> > > > > special non-PCI controllers that need non-PCI I/O physical
> > > > > address redirection...
> > > > >
> > > > > Thanks (and sorry for the long reply but I didn't know how
> > > > > to make the explanation shorter :) )
> > > > >
> > > > > Gab
> > > > >
> > > > > >
> > > > > > If we separate the two steps:
> > > > > >
> > > > > > a) assign a range of logical I/O port numbers to a bus
> > > > > > b) register a set of helpers for redirecting logical I/O
> > > > > >    port to a helper function
> > > > > >
> > > > > > then I think the code will get cleaner and more flexible.
> > > > > > It should actually then be able to replace the powerpc
> > > > > > specific implementation.
> > > > > >
> > > > > > 	Arnd

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

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-14 11:26                             ` liviu.dudau
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau @ 2016-11-14 11:26 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: Arnd Bergmann, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, bhelgaas@googl e.com, zhichang.yuan02

On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> Hi Liviu
> 

[snip]

> > > >
> > > > Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and
> > you
> > > > actually need another variable for "reserving" an area in the I/O
> > space
> > > > that can be used for physical addresses rather than I/O tokens.
> > > >
> > > > The one good example for using PCIBIOS_MIN_IO is when your
> > > > platform/architecture
> > > > does not support legacy ISA operations *at all*. In that case
> > someone
> > > > sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O
> > range
> > > > so that it doesn't get used. With Zhichang's patch you now start
> > > > forcing
> > > > those platforms to have a valid address below PCIBIOS_MIN_IO.
> > >
> > > But if PCIBIOS_MIN_IO is 0 then it means that all I/O space is to be
> > used
> > > by PCI controllers only...
> > 
> > Nope, that is not what it means. It means that PCI devices can see I/O
> > addresses
> > on the bus that start from 0. There never was any usage for non-PCI
> > controllers
> 
> So I am a bit confused...
> From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> It seems that ISA buses operate on cpu I/O address range [0, 0xFFF].
> I thought that was the reason why for most architectures we have
> PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA controllers
> usually use [0, PCIBIOS_MIN_IO - 1] )

First of all, cpu I/O addresses is an x86-ism. ARM architectures and others
 have no separate address space for I/O, it is all merged into one unified
address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0 could mean
that we don't care about ISA I/O because the platform does not support having
an ISA bus (e.g.).


> 
> For those architectures whose PCIBIOS_MIN_IO != 0x1000 probably
> they are not fully compliant or they cannot fully support an ISA
> controller...?

Exactly. Not fully compliant is a bit strong, as ISA is a legacy feature and
when it comes to PCI-e you are allowed to ignore it. Having PCIBIOS_MIN_IO != 0x1000
is a way to signal that you don't fully support ISA.

> 
> As said before this series forbid IO tokens to be in [0, PCIBIOS_MIN_IO)
> to allow special ISA controllers to use that range with special
> accessors.
> Having a variable threshold would make life much more difficult
> as there would be a probe dependency between the PCI controller and
> the special ISA one (PCI to wait for the special ISA device to be
> probed and set the right threshold value from DT or ACPI table).
> 
> Instead using PCIBIOS_MIN_IO is easier and should not impose much
> constraint as [PCIBIOS_MIN_IO, IO_SPACE_LIMIT] is available to
> the PCI controller for I/O tokens...

What I am suggesting is to leave PCIBIOS_MIN_IO alone which still reserves
space for ISA controller and add a PCIBIOS_MIN_DIRECT_IO that will reserve
space for your direct address I/O on top of PCIBIOS_MIN_IO.

Best regards,
Liviu

> 
> Thanks
> 
> Gab
> 
> > when PCIBIOS_MIN_IO != 0. That is what Zhichang is trying to do now and
> > what
> > I think is not the right thing (and not enough anyway).
> > 
> > > so if you have a special bus device using
> > > an I/O range in this case should be a PCI controller...
> > 
> > That has always been the case. It is this series that wants to
> > introduce the
> > new meaning.
> > 
> > > i.e. I would
> > > expect it to fall back into the case of I/O tokens redirection rather
> > than
> > > physical addresses redirection (as mentioned below from my previous
> > reply).
> > > What do you think?
> > 
> > I think you have looked too much at the code *with* Zhichang's patches
> > applied.
> > Take a step back and look at how PCIBIOS_MIN_IO is used now, before you
> > apply
> > the patches. It is all about PCI addresses and there is no notion of
> > non-PCI
> > busses using PCI framework. Only platforms and architectures that try
> > to work
> > around some legacy standards (ISA) or HW restrictions.
> > 
> > Best regards,
> > Liviu
> > 
> > >
> > > Thanks
> > >
> > > Gab
> > >
> > >
> > > >
> > > > For the general case you also have to bear in mind that
> > PCIBIOS_MIN_IO
> > > > could
> > > > be zero. In that case, what is your "forbidden" range? [0, 0) ? So
> > it
> > > > makes
> > > > sense to add a new #define that should only be defined by those
> > > > architectures/
> > > > platforms that want to reserve on top of PCIBIOS_MIN_IO another
> > region
> > > > where I/O tokens can't be generated for.
> > > >
> > > > Best regards,
> > > > Liviu
> > > >
> > > > >
> > > > > >
> > > > > > > > Your current version has
> > > > > > > >
> > > > > > > >         if (arm64_extio_ops->pfout)
> > > > \
> > > > > > > >                 arm64_extio_ops->pfout(arm64_extio_ops-
> > > > >devpara,\
> > > > > > > >                        addr, value, sizeof(type));
> > > > \
> > > > > > > >
> > > > > > > > Instead, just subtract the start of the range from the
> > logical
> > > > > > > > port number to transform it back into a bus-local port
> > number:
> > > > > > >
> > > > > > > These accessors do not operate on IO tokens:
> > > > > > >
> > > > > > > If (arm64_extio_ops->start > addr || arm64_extio_ops->end <
> > addr)
> > > > > > > addr is not going to be an I/O token; in fact patch 2/3
> > imposes
> > > > that
> > > > > > > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> > > > > > PCIBIOS_MIN_IO
> > > > > > > we have free physical addresses that the accessors can
> > operate
> > > > on.
> > > > > >
> > > > > > Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to
> > refer
> > > > to
> > > > > > the logical I/O tokens, the purpose of that macro is really
> > meant
> > > > > > for allocating PCI I/O port numbers within the address space of
> > > > > > one bus.
> > > > >
> > > > > As I mentioned above, special devices operate on CPU addresses
> > > > directly,
> > > > > not I/O tokens. For them there is no way to distinguish....
> > > > >
> > > > > >
> > > > > > Note that it's equally likely that whichever next platform
> > needs
> > > > > > non-mapped I/O access like this actually needs them for PCI I/O
> > > > space,
> > > > > > and that will use it on addresses registered to a PCI host
> > bridge.
> > > > >
> > > > > Ok so here you are talking about a platform that has got an I/O
> > range
> > > > > under the PCI host controller, right?
> > > > > And this I/O range cannot be directly memory mapped but needs
> > special
> > > > > redirections for the I/O tokens, right?
> > > > >
> > > > > In this scenario registering the I/O ranges with the forbidden
> > range
> > > > > implemented by the current patch would still allow to redirect
> > I/O
> > > > > tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
> > > > >
> > > > > So effectively the special PCI host controller
> > > > > 1) knows the physical range that needs special redirection
> > > > > 2) register such range
> > > > > 3) uses pci_pio_to_address() to retrieve the IO tokens for the
> > > > >    special accessors
> > > > > 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in
> > 3)
> > > > >
> > > > > So to be honest I think this patch can fit well both with
> > > > > special PCI controllers that need I/O tokens redirection and with
> > > > > special non-PCI controllers that need non-PCI I/O physical
> > > > > address redirection...
> > > > >
> > > > > Thanks (and sorry for the long reply but I didn't know how
> > > > > to make the explanation shorter :) )
> > > > >
> > > > > Gab
> > > > >
> > > > > >
> > > > > > If we separate the two steps:
> > > > > >
> > > > > > a) assign a range of logical I/O port numbers to a bus
> > > > > > b) register a set of helpers for redirecting logical I/O
> > > > > >    port to a helper function
> > > > > >
> > > > > > then I think the code will get cleaner and more flexible.
> > > > > > It should actually then be able to replace the powerpc
> > > > > > specific implementation.
> > > > > >
> > > > > > 	Arnd

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

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-14 11:26                             ` liviu.dudau
  0 siblings, 0 replies; 286+ messages in thread
From: liviu.dudau at arm.com @ 2016-11-14 11:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> Hi Liviu
> 

[snip]

> > > >
> > > > Your idea is a good one, however you are abusing PCIBIOS_MIN_IO and
> > you
> > > > actually need another variable for "reserving" an area in the I/O
> > space
> > > > that can be used for physical addresses rather than I/O tokens.
> > > >
> > > > The one good example for using PCIBIOS_MIN_IO is when your
> > > > platform/architecture
> > > > does not support legacy ISA operations *at all*. In that case
> > someone
> > > > sets the PCIBIOS_MIN_IO to a non-zero value to reserve that I/O
> > range
> > > > so that it doesn't get used. With Zhichang's patch you now start
> > > > forcing
> > > > those platforms to have a valid address below PCIBIOS_MIN_IO.
> > >
> > > But if PCIBIOS_MIN_IO is 0 then it means that all I/O space is to be
> > used
> > > by PCI controllers only...
> > 
> > Nope, that is not what it means. It means that PCI devices can see I/O
> > addresses
> > on the bus that start from 0. There never was any usage for non-PCI
> > controllers
> 
> So I am a bit confused...
> From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> It seems that ISA buses operate on cpu I/O address range [0, 0xFFF].
> I thought that was the reason why for most architectures we have
> PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA controllers
> usually use [0, PCIBIOS_MIN_IO - 1] )

First of all, cpu I/O addresses is an x86-ism. ARM architectures and others
 have no separate address space for I/O, it is all merged into one unified
address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0 could mean
that we don't care about ISA I/O because the platform does not support having
an ISA bus (e.g.).


> 
> For those architectures whose PCIBIOS_MIN_IO != 0x1000 probably
> they are not fully compliant or they cannot fully support an ISA
> controller...?

Exactly. Not fully compliant is a bit strong, as ISA is a legacy feature and
when it comes to PCI-e you are allowed to ignore it. Having PCIBIOS_MIN_IO != 0x1000
is a way to signal that you don't fully support ISA.

> 
> As said before this series forbid IO tokens to be in [0, PCIBIOS_MIN_IO)
> to allow special ISA controllers to use that range with special
> accessors.
> Having a variable threshold would make life much more difficult
> as there would be a probe dependency between the PCI controller and
> the special ISA one (PCI to wait for the special ISA device to be
> probed and set the right threshold value from DT or ACPI table).
> 
> Instead using PCIBIOS_MIN_IO is easier and should not impose much
> constraint as [PCIBIOS_MIN_IO, IO_SPACE_LIMIT] is available to
> the PCI controller for I/O tokens...

What I am suggesting is to leave PCIBIOS_MIN_IO alone which still reserves
space for ISA controller and add a PCIBIOS_MIN_DIRECT_IO that will reserve
space for your direct address I/O on top of PCIBIOS_MIN_IO.

Best regards,
Liviu

> 
> Thanks
> 
> Gab
> 
> > when PCIBIOS_MIN_IO != 0. That is what Zhichang is trying to do now and
> > what
> > I think is not the right thing (and not enough anyway).
> > 
> > > so if you have a special bus device using
> > > an I/O range in this case should be a PCI controller...
> > 
> > That has always been the case. It is this series that wants to
> > introduce the
> > new meaning.
> > 
> > > i.e. I would
> > > expect it to fall back into the case of I/O tokens redirection rather
> > than
> > > physical addresses redirection (as mentioned below from my previous
> > reply).
> > > What do you think?
> > 
> > I think you have looked too much at the code *with* Zhichang's patches
> > applied.
> > Take a step back and look at how PCIBIOS_MIN_IO is used now, before you
> > apply
> > the patches. It is all about PCI addresses and there is no notion of
> > non-PCI
> > busses using PCI framework. Only platforms and architectures that try
> > to work
> > around some legacy standards (ISA) or HW restrictions.
> > 
> > Best regards,
> > Liviu
> > 
> > >
> > > Thanks
> > >
> > > Gab
> > >
> > >
> > > >
> > > > For the general case you also have to bear in mind that
> > PCIBIOS_MIN_IO
> > > > could
> > > > be zero. In that case, what is your "forbidden" range? [0, 0) ? So
> > it
> > > > makes
> > > > sense to add a new #define that should only be defined by those
> > > > architectures/
> > > > platforms that want to reserve on top of PCIBIOS_MIN_IO another
> > region
> > > > where I/O tokens can't be generated for.
> > > >
> > > > Best regards,
> > > > Liviu
> > > >
> > > > >
> > > > > >
> > > > > > > > Your current version has
> > > > > > > >
> > > > > > > >         if (arm64_extio_ops->pfout)
> > > > \
> > > > > > > >                 arm64_extio_ops->pfout(arm64_extio_ops-
> > > > >devpara,\
> > > > > > > >                        addr, value, sizeof(type));
> > > > \
> > > > > > > >
> > > > > > > > Instead, just subtract the start of the range from the
> > logical
> > > > > > > > port number to transform it back into a bus-local port
> > number:
> > > > > > >
> > > > > > > These accessors do not operate on IO tokens:
> > > > > > >
> > > > > > > If (arm64_extio_ops->start > addr || arm64_extio_ops->end <
> > addr)
> > > > > > > addr is not going to be an I/O token; in fact patch 2/3
> > imposes
> > > > that
> > > > > > > the I/O tokens will start at PCIBIOS_MIN_IO. So from 0 to
> > > > > > PCIBIOS_MIN_IO
> > > > > > > we have free physical addresses that the accessors can
> > operate
> > > > on.
> > > > > >
> > > > > > Ah, I missed that part. I'd rather not use PCIBIOS_MIN_IO to
> > refer
> > > > to
> > > > > > the logical I/O tokens, the purpose of that macro is really
> > meant
> > > > > > for allocating PCI I/O port numbers within the address space of
> > > > > > one bus.
> > > > >
> > > > > As I mentioned above, special devices operate on CPU addresses
> > > > directly,
> > > > > not I/O tokens. For them there is no way to distinguish....
> > > > >
> > > > > >
> > > > > > Note that it's equally likely that whichever next platform
> > needs
> > > > > > non-mapped I/O access like this actually needs them for PCI I/O
> > > > space,
> > > > > > and that will use it on addresses registered to a PCI host
> > bridge.
> > > > >
> > > > > Ok so here you are talking about a platform that has got an I/O
> > range
> > > > > under the PCI host controller, right?
> > > > > And this I/O range cannot be directly memory mapped but needs
> > special
> > > > > redirections for the I/O tokens, right?
> > > > >
> > > > > In this scenario registering the I/O ranges with the forbidden
> > range
> > > > > implemented by the current patch would still allow to redirect
> > I/O
> > > > > tokens as long as arm64_extio_ops->start >= PCIBIOS_MIN_IO
> > > > >
> > > > > So effectively the special PCI host controller
> > > > > 1) knows the physical range that needs special redirection
> > > > > 2) register such range
> > > > > 3) uses pci_pio_to_address() to retrieve the IO tokens for the
> > > > >    special accessors
> > > > > 4) sets arm64_extio_ops->start/end to the IO tokens retrieved in
> > 3)
> > > > >
> > > > > So to be honest I think this patch can fit well both with
> > > > > special PCI controllers that need I/O tokens redirection and with
> > > > > special non-PCI controllers that need non-PCI I/O physical
> > > > > address redirection...
> > > > >
> > > > > Thanks (and sorry for the long reply but I didn't know how
> > > > > to make the explanation shorter :) )
> > > > >
> > > > > Gab
> > > > >
> > > > > >
> > > > > > If we separate the two steps:
> > > > > >
> > > > > > a) assign a range of logical I/O port numbers to a bus
> > > > > > b) register a set of helpers for redirecting logical I/O
> > > > > >    port to a helper function
> > > > > >
> > > > > > then I think the code will get cleaner and more flexible.
> > > > > > It should actually then be able to replace the powerpc
> > > > > > specific implementation.
> > > > > >
> > > > > > 	Arnd

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

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-11-11 10:07             ` zhichang.yuan
  (?)
@ 2016-11-18  9:20               ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18  9:20 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: zhichang.yuan, Benjamin Herrenschmidt, Mark Rutland,
	gabriele.paoloni, catalin.marinas, will.deacon, linuxarm,
	lorenzo.pieralisi, xuwei5, linux-serial, linux-pci, devicetree,
	minyard, marc.zyngier, liviu.dudau, john.garry, zourongrong,
	robh+dt, bhelgaas, kantyzc, zhichang.yuan02, linux-kernel, olof

On Friday, November 11, 2016 6:07:07 PM CET zhichang.yuan wrote:
> 
> I have similar idea as your PPC MMIO.
> 
> We notice the prototype of {in/out()} is something like that:
> 
> static inline u8 inb(unsigned long addr)
> static inline void outb(u8 value, unsigned long addr)
> 
> The type of parameter 'addr' is unsigned long. For I/O space, it is big enough.
> So, could you divide this 'addr' into several bit segments? The top 8 bits is
> defined as bus index. For normal direct IO, the bus index is 0. For those bus
> device which need indirectIO or some special I/O accessors, when these devices
> are initializing, can request to allocate an unique ID to them, and register
> their own accessors to the entry which is corresponding to the ID.

Ah, have you looked at the IA64 code? It does exactly this.
For ARM64 we decided to use the same basic approach as powerpc with
a single range of virtual memory for mapping it as that somewhat
simplified all cases we knew about at the time.

> In this way, we can support multiple domains, I think.
> But I am not sure whether it is feasible, for example, are there some
> architectures/platforms had populated the top 8 bits? Do we need to request IO
> region from ioport_resource for those devices?  etc...

On a 64-bit architecture, the top 32 bits of the port number are
definitely free to use for this, and 8 bits are probably sufficient.

Even on 32 bit architectures, I can't see why we'd ever need more than
16 bits worth of addressing within a domain, so using 8 bit domain
and 16 bit address leaves 8 or 40 unused bits.

	Arnd

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-18  9:20               ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18  9:20 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Mark Rutland, catalin.marinas, gabriele.paoloni, linux-pci,
	will.deacon, linuxarm, lorenzo.pieralisi, xuwei5, linux-serial,
	Benjamin Herrenschmidt, devicetree, minyard, marc.zyngier,
	liviu.dudau, john.garry, olof, robh+dt, bhelgaas, kantyzc,
	zhichang.yuan02, linux-kernel, zhichang.yuan, zourongrong

On Friday, November 11, 2016 6:07:07 PM CET zhichang.yuan wrote:
> 
> I have similar idea as your PPC MMIO.
> 
> We notice the prototype of {in/out()} is something like that:
> 
> static inline u8 inb(unsigned long addr)
> static inline void outb(u8 value, unsigned long addr)
> 
> The type of parameter 'addr' is unsigned long. For I/O space, it is big enough.
> So, could you divide this 'addr' into several bit segments? The top 8 bits is
> defined as bus index. For normal direct IO, the bus index is 0. For those bus
> device which need indirectIO or some special I/O accessors, when these devices
> are initializing, can request to allocate an unique ID to them, and register
> their own accessors to the entry which is corresponding to the ID.

Ah, have you looked at the IA64 code? It does exactly this.
For ARM64 we decided to use the same basic approach as powerpc with
a single range of virtual memory for mapping it as that somewhat
simplified all cases we knew about at the time.

> In this way, we can support multiple domains, I think.
> But I am not sure whether it is feasible, for example, are there some
> architectures/platforms had populated the top 8 bits? Do we need to request IO
> region from ioport_resource for those devices?  etc...

On a 64-bit architecture, the top 32 bits of the port number are
definitely free to use for this, and 8 bits are probably sufficient.

Even on 32 bit architectures, I can't see why we'd ever need more than
16 bits worth of addressing within a domain, so using 8 bit domain
and 16 bit address leaves 8 or 40 unused bits.

	Arnd

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-18  9:20               ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18  9:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday, November 11, 2016 6:07:07 PM CET zhichang.yuan wrote:
> 
> I have similar idea as your PPC MMIO.
> 
> We notice the prototype of {in/out()} is something like that:
> 
> static inline u8 inb(unsigned long addr)
> static inline void outb(u8 value, unsigned long addr)
> 
> The type of parameter 'addr' is unsigned long. For I/O space, it is big enough.
> So, could you divide this 'addr' into several bit segments? The top 8 bits is
> defined as bus index. For normal direct IO, the bus index is 0. For those bus
> device which need indirectIO or some special I/O accessors, when these devices
> are initializing, can request to allocate an unique ID to them, and register
> their own accessors to the entry which is corresponding to the ID.

Ah, have you looked at the IA64 code? It does exactly this.
For ARM64 we decided to use the same basic approach as powerpc with
a single range of virtual memory for mapping it as that somewhat
simplified all cases we knew about at the time.

> In this way, we can support multiple domains, I think.
> But I am not sure whether it is feasible, for example, are there some
> architectures/platforms had populated the top 8 bits? Do we need to request IO
> region from ioport_resource for those devices?  etc...

On a 64-bit architecture, the top 32 bits of the port number are
definitely free to use for this, and 8 bits are probably sufficient.

Even on 32 bit architectures, I can't see why we'd ever need more than
16 bits worth of addressing within a domain, so using 8 bit domain
and 16 bit address leaves 8 or 40 unused bits.

	Arnd

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
  2016-11-14 11:11             ` One Thousand Gnomes
  (?)
  (?)
@ 2016-11-18  9:22               ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18  9:22 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: One Thousand Gnomes, Mark Rutland, gabriele.paoloni, benh,
	will.deacon, linuxarm, lorenzo.pieralisi, xuwei5, linux-serial,
	catalin.marinas, devicetree, minyard, marc.zyngier, liviu.dudau,
	john.garry, zourongrong, robh+dt, bhelgaas, kantyzc,
	zhichang.yuan02, linux-pci, linux-kernel, zhichang.yuan, olof

On Monday, November 14, 2016 11:11:11 AM CET One Thousand Gnomes wrote:
> > > It's not a safe assumption for x86 at least. There are a few systems with
> > > multiple ISA busses particularly older laptops with a docking station.  
> > 
> > But do they have multiple ISA domains? There is no real harm in supporting
> > it, the (small) downsides I can think of are:
> 
> I don't believe they x86 class ones have multiple ISA domains. But as
> I've said I don't know how the electronics in the older ThinkPad worked
> when it used two PIIX4s with some LPC or ISA stuff on each.
> 
> It works in DOS and unmodified Linux so I'm pretty sure there are no
> additional domains. Likewise the various x86 schemes that route some bits
> of ISA bus off into strange places work in DOS and don't have any
> overlaps.
> 
> yenta_socket handles PCI/PCMCIA bridging and routes a range of that flat
> ISA space appropriately to the card.

Right, that's what I had expected, so we still don't even
need to handle multiple ISA I/O address spaces for the
only known case of multiple ISA buses, though we may decide
to generalize the code like that anyway.

	Arnd

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-18  9:22               ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18  9:22 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Mark Rutland, One Thousand Gnomes, catalin.marinas,
	gabriele.paoloni, benh, will.deacon, linuxarm, lorenzo.pieralisi,
	xuwei5, linux-serial, linux-pci, devicetree, minyard,
	marc.zyngier, liviu.dudau, john.garry, olof, robh+dt, bhelgaas,
	kantyzc, zhichang.yuan02, linux-kernel, zhichang.yuan,
	zourongrong

On Monday, November 14, 2016 11:11:11 AM CET One Thousand Gnomes wrote:
> > > It's not a safe assumption for x86 at least. There are a few systems with
> > > multiple ISA busses particularly older laptops with a docking station.  
> > 
> > But do they have multiple ISA domains? There is no real harm in supporting
> > it, the (small) downsides I can think of are:
> 
> I don't believe they x86 class ones have multiple ISA domains. But as
> I've said I don't know how the electronics in the older ThinkPad worked
> when it used two PIIX4s with some LPC or ISA stuff on each.
> 
> It works in DOS and unmodified Linux so I'm pretty sure there are no
> additional domains. Likewise the various x86 schemes that route some bits
> of ISA bus off into strange places work in DOS and don't have any
> overlaps.
> 
> yenta_socket handles PCI/PCMCIA bridging and routes a range of that flat
> ISA space appropriately to the card.

Right, that's what I had expected, so we still don't even
need to handle multiple ISA I/O address spaces for the
only known case of multiple ISA buses, though we may decide
to generalize the code like that anyway.

	Arnd

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

* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-18  9:22               ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18  9:22 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Mark Rutland, One Thousand Gnomes, catalin.marinas,
	gabriele.paoloni, benh, will.deacon, linuxarm, lorenzo.pieralisi,
	xuwei5, linux-serial, linux-pci, devicetree, minyard,
	marc.zyngier, liviu.dudau, john.garry, olof, robh+dt, bhelgaas,
	kantyzc, zhichang.yuan02, linux-kernel, zhichang.yuan,
	zourongrong

On Monday, November 14, 2016 11:11:11 AM CET One Thousand Gnomes wrote:
> > > It's not a safe assumption for x86 at least. There are a few systems with
> > > multiple ISA busses particularly older laptops with a docking station.  
> > 
> > But do they have multiple ISA domains? There is no real harm in supporting
> > it, the (small) downsides I can think of are:
> 
> I don't believe they x86 class ones have multiple ISA domains. But as
> I've said I don't know how the electronics in the older ThinkPad worked
> when it used two PIIX4s with some LPC or ISA stuff on each.
> 
> It works in DOS and unmodified Linux so I'm pretty sure there are no
> additional domains. Likewise the various x86 schemes that route some bits
> of ISA bus off into strange places work in DOS and don't have any
> overlaps.
> 
> yenta_socket handles PCI/PCMCIA bridging and routes a range of that flat
> ISA space appropriately to the card.

Right, that's what I had expected, so we still don't even
need to handle multiple ISA I/O address spaces for the
only known case of multiple ISA buses, though we may decide
to generalize the code like that anyway.

	Arnd

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
@ 2016-11-18  9:22               ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18  9:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Monday, November 14, 2016 11:11:11 AM CET One Thousand Gnomes wrote:
> > > It's not a safe assumption for x86 at least. There are a few systems with
> > > multiple ISA busses particularly older laptops with a docking station.  
> > 
> > But do they have multiple ISA domains? There is no real harm in supporting
> > it, the (small) downsides I can think of are:
> 
> I don't believe they x86 class ones have multiple ISA domains. But as
> I've said I don't know how the electronics in the older ThinkPad worked
> when it used two PIIX4s with some LPC or ISA stuff on each.
> 
> It works in DOS and unmodified Linux so I'm pretty sure there are no
> additional domains. Likewise the various x86 schemes that route some bits
> of ISA bus off into strange places work in DOS and don't have any
> overlaps.
> 
> yenta_socket handles PCI/PCMCIA bridging and routes a range of that flat
> ISA space appropriately to the card.

Right, that's what I had expected, so we still don't even
need to handle multiple ISA I/O address spaces for the
only known case of multiple ISA buses, though we may decide
to generalize the code like that anyway.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 10:17                               ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 10:17 UTC (permalink / raw)
  To: liviu.dudau
  Cc: Gabriele Paoloni, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, bhelgaas, zhichang.yuan02,
	Jason Gunthorpe, Thomas Petazzoni

On Monday, November 14, 2016 11:26:25 AM CET liviu.dudau@arm.com wrote:
> On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> > > Nope, that is not what it means. It means that PCI devices can see I/O
> > > addresses
> > > on the bus that start from 0. There never was any usage for non-PCI
> > > controllers
> > 
> > So I am a bit confused...
> > From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > It seems that ISA buses operate on cpu I/O address range [0, 0xFFF].
> > I thought that was the reason why for most architectures we have
> > PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA controllers
> > usually use [0, PCIBIOS_MIN_IO - 1] )
> 
> First of all, cpu I/O addresses is an x86-ism. ARM architectures and others
>  have no separate address space for I/O, it is all merged into one unified
> address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0 could mean
> that we don't care about ISA I/O because the platform does not support having
> an ISA bus (e.g.).

I think to be more specific, PCIBIOS_MIN_IO=0 would indicate that you cannot
have a PCI-to-ISA or PCI-to-LPC bridge in any PCI domain. This is different
from having an LPC master outside of PCI, as that lives in its own domain
and has a separately addressable I/O space.

> > As said before this series forbid IO tokens to be in [0, PCIBIOS_MIN_IO)
> > to allow special ISA controllers to use that range with special
> > accessors.
> > Having a variable threshold would make life much more difficult
> > as there would be a probe dependency between the PCI controller and
> > the special ISA one (PCI to wait for the special ISA device to be
> > probed and set the right threshold value from DT or ACPI table).
> > 
> > Instead using PCIBIOS_MIN_IO is easier and should not impose much
> > constraint as [PCIBIOS_MIN_IO, IO_SPACE_LIMIT] is available to
> > the PCI controller for I/O tokens...
> 
> What I am suggesting is to leave PCIBIOS_MIN_IO alone which still reserves
> space for ISA controller and add a PCIBIOS_MIN_DIRECT_IO that will reserve
> space for your direct address I/O on top of PCIBIOS_MIN_IO.

The PCIBIOS_MIN_DIRECT_IO name still suggests having something related to
PCIBIOS_MIN_IO, but it really isn't. We are talking about multiple
concepts here that are not the same but that are somewhat related:

a) keeping PCI devices from allocating low I/O ports on the PCI bus
   that would conflict with ISA devices behind a bridge of the
   same bus.

b) reserving the low 0x0-0xfff range of the Linux-internal I/O
   space abstraction to a particular LPC or PCI domain to make
   legacy device drivers work that hardcode a particular port
   number.

c) Redirecting inb/outb to call a domain-specific accessor function
   rather than doing the normal MMIO window for an LPC master or
   more generally any arbitrary LPC or PCI domain that has a
   nonstandard I/O space. 
   [side note: actually if we generalized this, we could avoid
    assigning an MMIO range for the I/O space on the pci-mvebu
    driver, and that would help free up some other remapping
    windows]

I think there is no need to change a) here, we have PCIBIOS_MIN_IO
today and even if we don't need it, there is no obvious downside.
I would also argue that we can ignore b) for the discussion of
the HiSilicon LPC driver, we just need to assign some range
of logical addresses to each domain.

That means solving c) is the important problem here, and it
shouldn't be so hard.  We can do this either with a single
special domain as in the v5 patch series, or by generalizing it
so that any I/O space mapping gets looked up through the device
pointer of the bus master.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 10:17                               ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 10:17 UTC (permalink / raw)
  To: liviu.dudau-5wv7dgnIgG8
  Cc: Gabriele Paoloni,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Yuanzhichang,
	mark.rutland-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA,
	lorenzo.pieralisi-5wv7dgnIgG8, minyard-HInyCGIudOg,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, John Garry,
	will.deacon-5wv7dgnIgG8, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	xuwei (O),
	Linuxarm, zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org

On Monday, November 14, 2016 11:26:25 AM CET liviu.dudau-5wv7dgnIgG8@public.gmane.org wrote:
> On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> > > Nope, that is not what it means. It means that PCI devices can see I/O
> > > addresses
> > > on the bus that start from 0. There never was any usage for non-PCI
> > > controllers
> > 
> > So I am a bit confused...
> > From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > It seems that ISA buses operate on cpu I/O address range [0, 0xFFF].
> > I thought that was the reason why for most architectures we have
> > PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA controllers
> > usually use [0, PCIBIOS_MIN_IO - 1] )
> 
> First of all, cpu I/O addresses is an x86-ism. ARM architectures and others
>  have no separate address space for I/O, it is all merged into one unified
> address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0 could mean
> that we don't care about ISA I/O because the platform does not support having
> an ISA bus (e.g.).

I think to be more specific, PCIBIOS_MIN_IO=0 would indicate that you cannot
have a PCI-to-ISA or PCI-to-LPC bridge in any PCI domain. This is different
from having an LPC master outside of PCI, as that lives in its own domain
and has a separately addressable I/O space.

> > As said before this series forbid IO tokens to be in [0, PCIBIOS_MIN_IO)
> > to allow special ISA controllers to use that range with special
> > accessors.
> > Having a variable threshold would make life much more difficult
> > as there would be a probe dependency between the PCI controller and
> > the special ISA one (PCI to wait for the special ISA device to be
> > probed and set the right threshold value from DT or ACPI table).
> > 
> > Instead using PCIBIOS_MIN_IO is easier and should not impose much
> > constraint as [PCIBIOS_MIN_IO, IO_SPACE_LIMIT] is available to
> > the PCI controller for I/O tokens...
> 
> What I am suggesting is to leave PCIBIOS_MIN_IO alone which still reserves
> space for ISA controller and add a PCIBIOS_MIN_DIRECT_IO that will reserve
> space for your direct address I/O on top of PCIBIOS_MIN_IO.

The PCIBIOS_MIN_DIRECT_IO name still suggests having something related to
PCIBIOS_MIN_IO, but it really isn't. We are talking about multiple
concepts here that are not the same but that are somewhat related:

a) keeping PCI devices from allocating low I/O ports on the PCI bus
   that would conflict with ISA devices behind a bridge of the
   same bus.

b) reserving the low 0x0-0xfff range of the Linux-internal I/O
   space abstraction to a particular LPC or PCI domain to make
   legacy device drivers work that hardcode a particular port
   number.

c) Redirecting inb/outb to call a domain-specific accessor function
   rather than doing the normal MMIO window for an LPC master or
   more generally any arbitrary LPC or PCI domain that has a
   nonstandard I/O space. 
   [side note: actually if we generalized this, we could avoid
    assigning an MMIO range for the I/O space on the pci-mvebu
    driver, and that would help free up some other remapping
    windows]

I think there is no need to change a) here, we have PCIBIOS_MIN_IO
today and even if we don't need it, there is no obvious downside.
I would also argue that we can ignore b) for the discussion of
the HiSilicon LPC driver, we just need to assign some range
of logical addresses to each domain.

That means solving c) is the important problem here, and it
shouldn't be so hard.  We can do this either with a single
special domain as in the v5 patch series, or by generalizing it
so that any I/O space mapping gets looked up through the device
pointer of the bus master.

	Arnd
--
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] 286+ messages in thread

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 10:17                               ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 10:17 UTC (permalink / raw)
  To: liviu.dudau
  Cc: Gabriele Paoloni, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, bhelgaas, zhichang.yuan02,
	Jason Gunthorpe, Thomas Petazzoni

On Monday, November 14, 2016 11:26:25 AM CET liviu.dudau@arm.com wrote:
> On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> > > Nope, that is not what it means. It means that PCI devices can see I/O
> > > addresses
> > > on the bus that start from 0. There never was any usage for non-PCI
> > > controllers
> > 
> > So I am a bit confused...
> > From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > It seems that ISA buses operate on cpu I/O address range [0, 0xFFF].
> > I thought that was the reason why for most architectures we have
> > PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA controllers
> > usually use [0, PCIBIOS_MIN_IO - 1] )
> 
> First of all, cpu I/O addresses is an x86-ism. ARM architectures and others
>  have no separate address space for I/O, it is all merged into one unified
> address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0 could mean
> that we don't care about ISA I/O because the platform does not support having
> an ISA bus (e.g.).

I think to be more specific, PCIBIOS_MIN_IO=0 would indicate that you cannot
have a PCI-to-ISA or PCI-to-LPC bridge in any PCI domain. This is different
from having an LPC master outside of PCI, as that lives in its own domain
and has a separately addressable I/O space.

> > As said before this series forbid IO tokens to be in [0, PCIBIOS_MIN_IO)
> > to allow special ISA controllers to use that range with special
> > accessors.
> > Having a variable threshold would make life much more difficult
> > as there would be a probe dependency between the PCI controller and
> > the special ISA one (PCI to wait for the special ISA device to be
> > probed and set the right threshold value from DT or ACPI table).
> > 
> > Instead using PCIBIOS_MIN_IO is easier and should not impose much
> > constraint as [PCIBIOS_MIN_IO, IO_SPACE_LIMIT] is available to
> > the PCI controller for I/O tokens...
> 
> What I am suggesting is to leave PCIBIOS_MIN_IO alone which still reserves
> space for ISA controller and add a PCIBIOS_MIN_DIRECT_IO that will reserve
> space for your direct address I/O on top of PCIBIOS_MIN_IO.

The PCIBIOS_MIN_DIRECT_IO name still suggests having something related to
PCIBIOS_MIN_IO, but it really isn't. We are talking about multiple
concepts here that are not the same but that are somewhat related:

a) keeping PCI devices from allocating low I/O ports on the PCI bus
   that would conflict with ISA devices behind a bridge of the
   same bus.

b) reserving the low 0x0-0xfff range of the Linux-internal I/O
   space abstraction to a particular LPC or PCI domain to make
   legacy device drivers work that hardcode a particular port
   number.

c) Redirecting inb/outb to call a domain-specific accessor function
   rather than doing the normal MMIO window for an LPC master or
   more generally any arbitrary LPC or PCI domain that has a
   nonstandard I/O space. 
   [side note: actually if we generalized this, we could avoid
    assigning an MMIO range for the I/O space on the pci-mvebu
    driver, and that would help free up some other remapping
    windows]

I think there is no need to change a) here, we have PCIBIOS_MIN_IO
today and even if we don't need it, there is no obvious downside.
I would also argue that we can ignore b) for the discussion of
the HiSilicon LPC driver, we just need to assign some range
of logical addresses to each domain.

That means solving c) is the important problem here, and it
shouldn't be so hard.  We can do this either with a single
special domain as in the v5 patch series, or by generalizing it
so that any I/O space mapping gets looked up through the device
pointer of the bus master.

	Arnd

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 10:17                               ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 10:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Monday, November 14, 2016 11:26:25 AM CET liviu.dudau at arm.com wrote:
> On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> > > Nope, that is not what it means. It means that PCI devices can see I/O
> > > addresses
> > > on the bus that start from 0. There never was any usage for non-PCI
> > > controllers
> > 
> > So I am a bit confused...
> > From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > It seems that ISA buses operate on cpu I/O address range [0, 0xFFF].
> > I thought that was the reason why for most architectures we have
> > PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA controllers
> > usually use [0, PCIBIOS_MIN_IO - 1] )
> 
> First of all, cpu I/O addresses is an x86-ism. ARM architectures and others
>  have no separate address space for I/O, it is all merged into one unified
> address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0 could mean
> that we don't care about ISA I/O because the platform does not support having
> an ISA bus (e.g.).

I think to be more specific, PCIBIOS_MIN_IO=0 would indicate that you cannot
have a PCI-to-ISA or PCI-to-LPC bridge in any PCI domain. This is different
from having an LPC master outside of PCI, as that lives in its own domain
and has a separately addressable I/O space.

> > As said before this series forbid IO tokens to be in [0, PCIBIOS_MIN_IO)
> > to allow special ISA controllers to use that range with special
> > accessors.
> > Having a variable threshold would make life much more difficult
> > as there would be a probe dependency between the PCI controller and
> > the special ISA one (PCI to wait for the special ISA device to be
> > probed and set the right threshold value from DT or ACPI table).
> > 
> > Instead using PCIBIOS_MIN_IO is easier and should not impose much
> > constraint as [PCIBIOS_MIN_IO, IO_SPACE_LIMIT] is available to
> > the PCI controller for I/O tokens...
> 
> What I am suggesting is to leave PCIBIOS_MIN_IO alone which still reserves
> space for ISA controller and add a PCIBIOS_MIN_DIRECT_IO that will reserve
> space for your direct address I/O on top of PCIBIOS_MIN_IO.

The PCIBIOS_MIN_DIRECT_IO name still suggests having something related to
PCIBIOS_MIN_IO, but it really isn't. We are talking about multiple
concepts here that are not the same but that are somewhat related:

a) keeping PCI devices from allocating low I/O ports on the PCI bus
   that would conflict with ISA devices behind a bridge of the
   same bus.

b) reserving the low 0x0-0xfff range of the Linux-internal I/O
   space abstraction to a particular LPC or PCI domain to make
   legacy device drivers work that hardcode a particular port
   number.

c) Redirecting inb/outb to call a domain-specific accessor function
   rather than doing the normal MMIO window for an LPC master or
   more generally any arbitrary LPC or PCI domain that has a
   nonstandard I/O space. 
   [side note: actually if we generalized this, we could avoid
    assigning an MMIO range for the I/O space on the pci-mvebu
    driver, and that would help free up some other remapping
    windows]

I think there is no need to change a) here, we have PCIBIOS_MIN_IO
today and even if we don't need it, there is no obvious downside.
I would also argue that we can ignore b) for the discussion of
the HiSilicon LPC driver, we just need to assign some range
of logical addresses to each domain.

That means solving c) is the important problem here, and it
shouldn't be so hard.  We can do this either with a single
special domain as in the v5 patch series, or by generalizing it
so that any I/O space mapping gets looked up through the device
pointer of the bus master.

	Arnd

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-11-18  9:20               ` Arnd Bergmann
  (?)
@ 2016-11-18 11:12                 ` zhichang.yuan
  -1 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-18 11:12 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: Benjamin Herrenschmidt, Mark Rutland, gabriele.paoloni,
	catalin.marinas, will.deacon, linuxarm, lorenzo.pieralisi,
	xuwei5, linux-serial, linux-pci, devicetree, minyard,
	marc.zyngier, liviu.dudau, john.garry, zourongrong, robh+dt,
	bhelgaas, kantyzc, zhichang.yuan02, linux-kernel, olof

Hi, Arnd,


On 2016/11/18 17:20, Arnd Bergmann wrote:
> On Friday, November 11, 2016 6:07:07 PM CET zhichang.yuan wrote:
>>
>> I have similar idea as your PPC MMIO.
>>
>> We notice the prototype of {in/out()} is something like that:
>>
>> static inline u8 inb(unsigned long addr)
>> static inline void outb(u8 value, unsigned long addr)
>>
>> The type of parameter 'addr' is unsigned long. For I/O space, it is big enough.
>> So, could you divide this 'addr' into several bit segments? The top 8 bits is
>> defined as bus index. For normal direct IO, the bus index is 0. For those bus
>> device which need indirectIO or some special I/O accessors, when these devices
>> are initializing, can request to allocate an unique ID to them, and register
>> their own accessors to the entry which is corresponding to the ID.
> 
> Ah, have you looked at the IA64 code? It does exactly this.
> For ARM64 we decided to use the same basic approach as powerpc with
> a single range of virtual memory for mapping it as that somewhat
> simplified all cases we knew about at the time.

Yes. I spent some time to trace how to work on PPC. But the code is a bit long,
I am not clear on how the indirectIO there was supported.

I noticed there are CONFIG_PPC_INDIRECT_PIO and CONFIG_PPC_INDIRECT_MMIO on PPC.
It seems that only CONFIG_PPC_INDIRECT_MMIO applied some MSB to store the bus
tokens which are used to get iowa_busses[] for specific operation helpers.
I can not find how CONFIG_PPC_INDIRECT_PIO support multiple ISA domains. It
seems only Opal-lpc.c adopt this INDIRECT_PIO method.

Although CONFIG_PPC_INDIRECT_MMIO is for MMIO, seems not suitable for ISA/LPC
I/O. But this idea is helpful.

what else did I miss??

> 
>> In this way, we can support multiple domains, I think.
>> But I am not sure whether it is feasible, for example, are there some
>> architectures/platforms had populated the top 8 bits? Do we need to request IO
>> region from ioport_resource for those devices?  etc...
> 
> On a 64-bit architecture, the top 32 bits of the port number are
> definitely free to use for this, and 8 bits are probably sufficient.
> 
> Even on 32 bit architectures, I can't see why we'd ever need more than
> 16 bits worth of addressing within a domain, so using 8 bit domain
> and 16 bit address leaves 8 or 40 unused bits.

Yes. 8 bits are enough.
But the maximal PIO on some architectures are defined as ~0 or -1. There is no
any bare space left. Probably we can not ensure the upper 8 bits available.


Thanks,
Zhichang


> 
> 	Arnd
> 
> .
> 

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-18 11:12                 ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-18 11:12 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Benjamin Herrenschmidt, Mark Rutland,
	gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
	catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	linuxarm-hv44wF8Li93QT0dZR+AlfA, lorenzo.pieralisi-5wv7dgnIgG8,
	xuwei5-C8/M+/jPZTeaMJb+Lgu22Q,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, minyard-HInyCGIudOg,
	marc.zyngier-5wv7dgnIgG8, liviu.dudau-5wv7dgnIgG8,
	john.garry-hv44wF8Li93QT0dZR+AlfA,
	zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, bhelgaas-hpIqsD4AKlfQT0dZR+AlfA,
	kantyzc-9Onoh4P/yGk, zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, olof-nZhT3qVonbNeoWH0uzbU5w

Hi, Arnd,


On 2016/11/18 17:20, Arnd Bergmann wrote:
> On Friday, November 11, 2016 6:07:07 PM CET zhichang.yuan wrote:
>>
>> I have similar idea as your PPC MMIO.
>>
>> We notice the prototype of {in/out()} is something like that:
>>
>> static inline u8 inb(unsigned long addr)
>> static inline void outb(u8 value, unsigned long addr)
>>
>> The type of parameter 'addr' is unsigned long. For I/O space, it is big enough.
>> So, could you divide this 'addr' into several bit segments? The top 8 bits is
>> defined as bus index. For normal direct IO, the bus index is 0. For those bus
>> device which need indirectIO or some special I/O accessors, when these devices
>> are initializing, can request to allocate an unique ID to them, and register
>> their own accessors to the entry which is corresponding to the ID.
> 
> Ah, have you looked at the IA64 code? It does exactly this.
> For ARM64 we decided to use the same basic approach as powerpc with
> a single range of virtual memory for mapping it as that somewhat
> simplified all cases we knew about at the time.

Yes. I spent some time to trace how to work on PPC. But the code is a bit long,
I am not clear on how the indirectIO there was supported.

I noticed there are CONFIG_PPC_INDIRECT_PIO and CONFIG_PPC_INDIRECT_MMIO on PPC.
It seems that only CONFIG_PPC_INDIRECT_MMIO applied some MSB to store the bus
tokens which are used to get iowa_busses[] for specific operation helpers.
I can not find how CONFIG_PPC_INDIRECT_PIO support multiple ISA domains. It
seems only Opal-lpc.c adopt this INDIRECT_PIO method.

Although CONFIG_PPC_INDIRECT_MMIO is for MMIO, seems not suitable for ISA/LPC
I/O. But this idea is helpful.

what else did I miss??

> 
>> In this way, we can support multiple domains, I think.
>> But I am not sure whether it is feasible, for example, are there some
>> architectures/platforms had populated the top 8 bits? Do we need to request IO
>> region from ioport_resource for those devices?  etc...
> 
> On a 64-bit architecture, the top 32 bits of the port number are
> definitely free to use for this, and 8 bits are probably sufficient.
> 
> Even on 32 bit architectures, I can't see why we'd ever need more than
> 16 bits worth of addressing within a domain, so using 8 bit domain
> and 16 bit address leaves 8 or 40 unused bits.

Yes. 8 bits are enough.
But the maximal PIO on some architectures are defined as ~0 or -1. There is no
any bare space left. Probably we can not ensure the upper 8 bits available.


Thanks,
Zhichang


> 
> 	Arnd
> 
> .
> 

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-18 11:12                 ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-18 11:12 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, Arnd,


On 2016/11/18 17:20, Arnd Bergmann wrote:
> On Friday, November 11, 2016 6:07:07 PM CET zhichang.yuan wrote:
>>
>> I have similar idea as your PPC MMIO.
>>
>> We notice the prototype of {in/out()} is something like that:
>>
>> static inline u8 inb(unsigned long addr)
>> static inline void outb(u8 value, unsigned long addr)
>>
>> The type of parameter 'addr' is unsigned long. For I/O space, it is big enough.
>> So, could you divide this 'addr' into several bit segments? The top 8 bits is
>> defined as bus index. For normal direct IO, the bus index is 0. For those bus
>> device which need indirectIO or some special I/O accessors, when these devices
>> are initializing, can request to allocate an unique ID to them, and register
>> their own accessors to the entry which is corresponding to the ID.
> 
> Ah, have you looked at the IA64 code? It does exactly this.
> For ARM64 we decided to use the same basic approach as powerpc with
> a single range of virtual memory for mapping it as that somewhat
> simplified all cases we knew about at the time.

Yes. I spent some time to trace how to work on PPC. But the code is a bit long,
I am not clear on how the indirectIO there was supported.

I noticed there are CONFIG_PPC_INDIRECT_PIO and CONFIG_PPC_INDIRECT_MMIO on PPC.
It seems that only CONFIG_PPC_INDIRECT_MMIO applied some MSB to store the bus
tokens which are used to get iowa_busses[] for specific operation helpers.
I can not find how CONFIG_PPC_INDIRECT_PIO support multiple ISA domains. It
seems only Opal-lpc.c adopt this INDIRECT_PIO method.

Although CONFIG_PPC_INDIRECT_MMIO is for MMIO, seems not suitable for ISA/LPC
I/O. But this idea is helpful.

what else did I miss??

> 
>> In this way, we can support multiple domains, I think.
>> But I am not sure whether it is feasible, for example, are there some
>> architectures/platforms had populated the top 8 bits? Do we need to request IO
>> region from ioport_resource for those devices?  etc...
> 
> On a 64-bit architecture, the top 32 bits of the port number are
> definitely free to use for this, and 8 bits are probably sufficient.
> 
> Even on 32 bit architectures, I can't see why we'd ever need more than
> 16 bits worth of addressing within a domain, so using 8 bit domain
> and 16 bit address leaves 8 or 40 unused bits.

Yes. 8 bits are enough.
But the maximal PIO on some architectures are defined as ~0 or -1. There is no
any bare space left. Probably we can not ensure the upper 8 bits available.


Thanks,
Zhichang


> 
> 	Arnd
> 
> .
> 

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-11-18 11:12                 ` zhichang.yuan
@ 2016-11-18 11:38                   ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 11:38 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: linux-arm-kernel, Benjamin Herrenschmidt, Mark Rutland,
	gabriele.paoloni, catalin.marinas, will.deacon, linuxarm,
	lorenzo.pieralisi, xuwei5, linux-serial, linux-pci, devicetree,
	minyard, marc.zyngier, liviu.dudau, john.garry, zourongrong,
	robh+dt, bhelgaas, kantyzc, zhichang.yuan02, linux-kernel, olof

On Friday, November 18, 2016 7:12:35 PM CET zhichang.yuan wrote:
> Hi, Arnd,
> 
> 
> On 2016/11/18 17:20, Arnd Bergmann wrote:
> > On Friday, November 11, 2016 6:07:07 PM CET zhichang.yuan wrote:
> >>
> >> I have similar idea as your PPC MMIO.
> >>
> >> We notice the prototype of {in/out()} is something like that:
> >>
> >> static inline u8 inb(unsigned long addr)
> >> static inline void outb(u8 value, unsigned long addr)
> >>
> >> The type of parameter 'addr' is unsigned long. For I/O space, it is big enough.
> >> So, could you divide this 'addr' into several bit segments? The top 8 bits is
> >> defined as bus index. For normal direct IO, the bus index is 0. For those bus
> >> device which need indirectIO or some special I/O accessors, when these devices
> >> are initializing, can request to allocate an unique ID to them, and register
> >> their own accessors to the entry which is corresponding to the ID.
> > 
> > Ah, have you looked at the IA64 code? It does exactly this.
> > For ARM64 we decided to use the same basic approach as powerpc with
> > a single range of virtual memory for mapping it as that somewhat
> > simplified all cases we knew about at the time.
> 
> Yes. I spent some time to trace how to work on PPC. But the code is a bit long,
> I am not clear on how the indirectIO there was supported.
> 
> I noticed there are CONFIG_PPC_INDIRECT_PIO and CONFIG_PPC_INDIRECT_MMIO on PPC.
> It seems that only CONFIG_PPC_INDIRECT_MMIO applied some MSB to store the bus
> tokens which are used to get iowa_busses[] for specific operation helpers.
> I can not find how CONFIG_PPC_INDIRECT_PIO support multiple ISA domains. It
> seems only Opal-lpc.c adopt this INDIRECT_PIO method.
> 
> Although CONFIG_PPC_INDIRECT_MMIO is for MMIO, seems not suitable for ISA/LPC
> I/O. But this idea is helpful.
> 
> what else did I miss??

I mentioned two different things here: ia64 IIRC uses some bits of the
port number to look up the domain, while powerpc traditionally had no
support for any such lookup, it did the same thing as ARM64 with
virtual remapping of MMIO ranges into an address range starting at
a fixed virtual address.

CONFIG_PPC_INDIRECT_PIO is a fairly recent addition, I was not thinking
of that.

> >> In this way, we can support multiple domains, I think.
> >> But I am not sure whether it is feasible, for example, are there some
> >> architectures/platforms had populated the top 8 bits? Do we need to request IO
> >> region from ioport_resource for those devices?  etc...
> > 
> > On a 64-bit architecture, the top 32 bits of the port number are
> > definitely free to use for this, and 8 bits are probably sufficient.
> > 
> > Even on 32 bit architectures, I can't see why we'd ever need more than
> > 16 bits worth of addressing within a domain, so using 8 bit domain
> > and 16 bit address leaves 8 or 40 unused bits.
> 
> Yes. 8 bits are enough.
> But the maximal PIO on some architectures are defined as ~0 or -1. There is no
> any bare space left. Probably we can not ensure the upper 8 bits available.

Right, we clearly can't use it across all architectures. The trick with
architectures using ULONG_MAX as the limit for port numbers is that they
treat it as a 1:1 mapping between port numbers and virtual addresses,
which is yet another way to handle the MMIO-based devices, but that has
a number of downsides we don't need to get into now.

What I think the code should do is a generic workaround handling that
architectures can opt-in to. We'd start doing this on ARM64 only,
and can then decide whether to change ARM or PowerPC over to use
that as well.

	Arnd

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-18 11:38                   ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 11:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday, November 18, 2016 7:12:35 PM CET zhichang.yuan wrote:
> Hi, Arnd,
> 
> 
> On 2016/11/18 17:20, Arnd Bergmann wrote:
> > On Friday, November 11, 2016 6:07:07 PM CET zhichang.yuan wrote:
> >>
> >> I have similar idea as your PPC MMIO.
> >>
> >> We notice the prototype of {in/out()} is something like that:
> >>
> >> static inline u8 inb(unsigned long addr)
> >> static inline void outb(u8 value, unsigned long addr)
> >>
> >> The type of parameter 'addr' is unsigned long. For I/O space, it is big enough.
> >> So, could you divide this 'addr' into several bit segments? The top 8 bits is
> >> defined as bus index. For normal direct IO, the bus index is 0. For those bus
> >> device which need indirectIO or some special I/O accessors, when these devices
> >> are initializing, can request to allocate an unique ID to them, and register
> >> their own accessors to the entry which is corresponding to the ID.
> > 
> > Ah, have you looked at the IA64 code? It does exactly this.
> > For ARM64 we decided to use the same basic approach as powerpc with
> > a single range of virtual memory for mapping it as that somewhat
> > simplified all cases we knew about at the time.
> 
> Yes. I spent some time to trace how to work on PPC. But the code is a bit long,
> I am not clear on how the indirectIO there was supported.
> 
> I noticed there are CONFIG_PPC_INDIRECT_PIO and CONFIG_PPC_INDIRECT_MMIO on PPC.
> It seems that only CONFIG_PPC_INDIRECT_MMIO applied some MSB to store the bus
> tokens which are used to get iowa_busses[] for specific operation helpers.
> I can not find how CONFIG_PPC_INDIRECT_PIO support multiple ISA domains. It
> seems only Opal-lpc.c adopt this INDIRECT_PIO method.
> 
> Although CONFIG_PPC_INDIRECT_MMIO is for MMIO, seems not suitable for ISA/LPC
> I/O. But this idea is helpful.
> 
> what else did I miss??

I mentioned two different things here: ia64 IIRC uses some bits of the
port number to look up the domain, while powerpc traditionally had no
support for any such lookup, it did the same thing as ARM64 with
virtual remapping of MMIO ranges into an address range starting at
a fixed virtual address.

CONFIG_PPC_INDIRECT_PIO is a fairly recent addition, I was not thinking
of that.

> >> In this way, we can support multiple domains, I think.
> >> But I am not sure whether it is feasible, for example, are there some
> >> architectures/platforms had populated the top 8 bits? Do we need to request IO
> >> region from ioport_resource for those devices?  etc...
> > 
> > On a 64-bit architecture, the top 32 bits of the port number are
> > definitely free to use for this, and 8 bits are probably sufficient.
> > 
> > Even on 32 bit architectures, I can't see why we'd ever need more than
> > 16 bits worth of addressing within a domain, so using 8 bit domain
> > and 16 bit address leaves 8 or 40 unused bits.
> 
> Yes. 8 bits are enough.
> But the maximal PIO on some architectures are defined as ~0 or -1. There is no
> any bare space left. Probably we can not ensure the upper 8 bits available.

Right, we clearly can't use it across all architectures. The trick with
architectures using ULONG_MAX as the limit for port numbers is that they
treat it as a 1:1 mapping between port numbers and virtual addresses,
which is yet another way to handle the MMIO-based devices, but that has
a number of downsides we don't need to get into now.

What I think the code should do is a generic workaround handling that
architectures can opt-in to. We'd start doing this on ARM64 only,
and can then decide whether to change ARM or PowerPC over to use
that as well.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-10 12:36               ` zhichang.yuan
  (?)
  (?)
@ 2016-11-18 11:46                 ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 11:46 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: linux-arm-kernel, mark.rutland, devicetree, lorenzo.pieralisi,
	Gabriele Paoloni, minyard, linux-pci, benh, John Garry,
	will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, liviu.dudau, bhelgaas, zhichang.yuan02

[found this old mail in my drafts folder, might as well send it now]

On Thursday, November 10, 2016 8:36:24 PM CET zhichang.yuan wrote:
> Sorry! I can't catch your idea yet:(
> 
> When to register the I/O range? Is it done just after the successfully
> of_translate_address() during the children scanning?

No, you do it when first finding the bus itself, just like we do for
PCI host bridges.

> If yes, when a child is scanning, there is no range data in arm64_extio_ops. The
> addr_is_indirect_io() calling in of_get_isa_indirect_io() don't need. All we can
> check is just whether the address to be translated is IO and is under a parent
> device which has no 'ranges' property.

The children should only be scanned after the I/O range has been
registered for the parent.

> > Your current version has
> > 
> >         if (arm64_extio_ops->pfout)                             \
> >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> >                        addr, value, sizeof(type));             \
> > 
> > Instead, just subtract the start of the range from the logical
> > port number to transform it back into a bus-local port number:
> > 
> >         if (arm64_extio_ops->pfout)                             \
> >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> >                        addr - arm64_extio_ops->start, value, sizeof(type)); \
> > 
> I think there is some information needed sync.
> In the old patch-set, we don't bypass the pci_address_to_pio() after
> successfully of_translate_address(). In this way, we don't need to reserve any
> PIO space for our LPC since the logical port are from the same mapping
> algorithm. Based on this way, the port number in the device resource is logical
> one, then we need to subtract the start of the resource to get back the
> bus-local port.
> 
> From V3, we don't apply the mapping based on pci_address_to_pio(), the
> of_translate_address() return the bus-local port directly and store into
> relevant device resource. So, in the current arm64_extio_ops->pfout(), the
> reverse translation don't need anymore. The input "addr" is bus-local port now.

Ok, so this would have to be changed again: If we want to support multiple
bus domains, of_translate_address() must translate between the bus specific
address and the general Linux I/O port number. Even without doing that,
it seems nicer to not overlap the range of the first PCI host bridge.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 11:46                 ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 11:46 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: linux-arm-kernel, mark.rutland, devicetree, lorenzo.pieralisi,
	Gabriele Paoloni, minyard, linux-pci, benh, John Garry,
	will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc

[found this old mail in my drafts folder, might as well send it now]

On Thursday, November 10, 2016 8:36:24 PM CET zhichang.yuan wrote:
> Sorry! I can't catch your idea yet:(
> 
> When to register the I/O range? Is it done just after the successfully
> of_translate_address() during the children scanning?

No, you do it when first finding the bus itself, just like we do for
PCI host bridges.

> If yes, when a child is scanning, there is no range data in arm64_extio_ops. The
> addr_is_indirect_io() calling in of_get_isa_indirect_io() don't need. All we can
> check is just whether the address to be translated is IO and is under a parent
> device which has no 'ranges' property.

The children should only be scanned after the I/O range has been
registered for the parent.

> > Your current version has
> > 
> >         if (arm64_extio_ops->pfout)                             \
> >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> >                        addr, value, sizeof(type));             \
> > 
> > Instead, just subtract the start of the range from the logical
> > port number to transform it back into a bus-local port number:
> > 
> >         if (arm64_extio_ops->pfout)                             \
> >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> >                        addr - arm64_extio_ops->start, value, sizeof(type)); \
> > 
> I think there is some information needed sync.
> In the old patch-set, we don't bypass the pci_address_to_pio() after
> successfully of_translate_address(). In this way, we don't need to reserve any
> PIO space for our LPC since the logical port are from the same mapping
> algorithm. Based on this way, the port number in the device resource is logical
> one, then we need to subtract the start of the resource to get back the
> bus-local port.
> 
> From V3, we don't apply the mapping based on pci_address_to_pio(), the
> of_translate_address() return the bus-local port directly and store into
> relevant device resource. So, in the current arm64_extio_ops->pfout(), the
> reverse translation don't need anymore. The input "addr" is bus-local port now.

Ok, so this would have to be changed again: If we want to support multiple
bus domains, of_translate_address() must translate between the bus specific
address and the general Linux I/O port number. Even without doing that,
it seems nicer to not overlap the range of the first PCI host bridge.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 11:46                 ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 11:46 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: mark.rutland, benh, Gabriele Paoloni, catalin.marinas,
	will.deacon, Linuxarm, lorenzo.pieralisi, xuwei (O),
	linux-serial, linux-pci, devicetree, minyard, liviu.dudau,
	John Garry, zourongrong, robh+dt, bhelgaas, kantyzc,
	zhichang.yuan02, linux-arm-kernel, linux-kernel, olof

[found this old mail in my drafts folder, might as well send it now]

On Thursday, November 10, 2016 8:36:24 PM CET zhichang.yuan wrote:
> Sorry! I can't catch your idea yet:(
> 
> When to register the I/O range? Is it done just after the successfully
> of_translate_address() during the children scanning?

No, you do it when first finding the bus itself, just like we do for
PCI host bridges.

> If yes, when a child is scanning, there is no range data in arm64_extio_ops. The
> addr_is_indirect_io() calling in of_get_isa_indirect_io() don't need. All we can
> check is just whether the address to be translated is IO and is under a parent
> device which has no 'ranges' property.

The children should only be scanned after the I/O range has been
registered for the parent.

> > Your current version has
> > 
> >         if (arm64_extio_ops->pfout)                             \
> >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> >                        addr, value, sizeof(type));             \
> > 
> > Instead, just subtract the start of the range from the logical
> > port number to transform it back into a bus-local port number:
> > 
> >         if (arm64_extio_ops->pfout)                             \
> >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> >                        addr - arm64_extio_ops->start, value, sizeof(type)); \
> > 
> I think there is some information needed sync.
> In the old patch-set, we don't bypass the pci_address_to_pio() after
> successfully of_translate_address(). In this way, we don't need to reserve any
> PIO space for our LPC since the logical port are from the same mapping
> algorithm. Based on this way, the port number in the device resource is logical
> one, then we need to subtract the start of the resource to get back the
> bus-local port.
> 
> From V3, we don't apply the mapping based on pci_address_to_pio(), the
> of_translate_address() return the bus-local port directly and store into
> relevant device resource. So, in the current arm64_extio_ops->pfout(), the
> reverse translation don't need anymore. The input "addr" is bus-local port now.

Ok, so this would have to be changed again: If we want to support multiple
bus domains, of_translate_address() must translate between the bus specific
address and the general Linux I/O port number. Even without doing that,
it seems nicer to not overlap the range of the first PCI host bridge.

	Arnd

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 11:46                 ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 11:46 UTC (permalink / raw)
  To: linux-arm-kernel

[found this old mail in my drafts folder, might as well send it now]

On Thursday, November 10, 2016 8:36:24 PM CET zhichang.yuan wrote:
> Sorry! I can't catch your idea yet:(
> 
> When to register the I/O range? Is it done just after the successfully
> of_translate_address() during the children scanning?

No, you do it when first finding the bus itself, just like we do for
PCI host bridges.

> If yes, when a child is scanning, there is no range data in arm64_extio_ops. The
> addr_is_indirect_io() calling in of_get_isa_indirect_io() don't need. All we can
> check is just whether the address to be translated is IO and is under a parent
> device which has no 'ranges' property.

The children should only be scanned after the I/O range has been
registered for the parent.

> > Your current version has
> > 
> >         if (arm64_extio_ops->pfout)                             \
> >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> >                        addr, value, sizeof(type));             \
> > 
> > Instead, just subtract the start of the range from the logical
> > port number to transform it back into a bus-local port number:
> > 
> >         if (arm64_extio_ops->pfout)                             \
> >                 arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> >                        addr - arm64_extio_ops->start, value, sizeof(type)); \
> > 
> I think there is some information needed sync.
> In the old patch-set, we don't bypass the pci_address_to_pio() after
> successfully of_translate_address(). In this way, we don't need to reserve any
> PIO space for our LPC since the logical port are from the same mapping
> algorithm. Based on this way, the port number in the device resource is logical
> one, then we need to subtract the start of the resource to get back the
> bus-local port.
> 
> From V3, we don't apply the mapping based on pci_address_to_pio(), the
> of_translate_address() return the bus-local port directly and store into
> relevant device resource. So, in the current arm64_extio_ops->pfout(), the
> reverse translation don't need anymore. The input "addr" is bus-local port now.

Ok, so this would have to be changed again: If we want to support multiple
bus domains, of_translate_address() must translate between the bus specific
address and the general Linux I/O port number. Even without doing that,
it seems nicer to not overlap the range of the first PCI host bridge.

	Arnd

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-18 10:17                               ` Arnd Bergmann
  (?)
  (?)
@ 2016-11-18 12:07                                 ` Gabriele Paoloni
  -1 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-18 12:07 UTC (permalink / raw)
  To: Arnd Bergmann, liviu.dudau
  Cc: linux-arm-kernel, Yuanzhichang, mark.rutland, devicetree,
	lorenzo.pieralisi, minyard, linux-pci, benh, John Garry,
	will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, bhelgaas@go ogle.com, zhichang.yuan02,
	Jason Gunthorpe, Thomas Petazzoni

Hi Arnd many thanks for your help here

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 18 November 2016 10:18
> To: liviu.dudau@arm.com
> Cc: Gabriele Paoloni; linux-arm-kernel@lists.infradead.org;
> Yuanzhichang; mark.rutland@arm.com; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> catalin.marinas@arm.com; olof@lixom.net; bhelgaas@go ogle.com;
> zhichang.yuan02@gmail.com; Jason Gunthorpe; Thomas Petazzoni
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Monday, November 14, 2016 11:26:25 AM CET liviu.dudau@arm.com wrote:
> > On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> > > > Nope, that is not what it means. It means that PCI devices can
> see I/O
> > > > addresses
> > > > on the bus that start from 0. There never was any usage for non-
> PCI
> > > > controllers
> > >
> > > So I am a bit confused...
> > > From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > > It seems that ISA buses operate on cpu I/O address range [0,
> 0xFFF].
> > > I thought that was the reason why for most architectures we have
> > > PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA controllers
> > > usually use [0, PCIBIOS_MIN_IO - 1] )
> >
> > First of all, cpu I/O addresses is an x86-ism. ARM architectures and
> others
> >  have no separate address space for I/O, it is all merged into one
> unified
> > address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0 could
> mean
> > that we don't care about ISA I/O because the platform does not
> support having
> > an ISA bus (e.g.).
> 
> I think to be more specific, PCIBIOS_MIN_IO=0 would indicate that you
> cannot
> have a PCI-to-ISA or PCI-to-LPC bridge in any PCI domain. This is
> different
> from having an LPC master outside of PCI, as that lives in its own
> domain
> and has a separately addressable I/O space.

Yes correct so if we go for the single domain solution arch that
have PCIBIOS_MIN_IO=0 cannot support special devices such as LPC
unless we also redefine PCIBIOS_MIN_IO, right?

> 
> > > As said before this series forbid IO tokens to be in [0,
> PCIBIOS_MIN_IO)
> > > to allow special ISA controllers to use that range with special
> > > accessors.
> > > Having a variable threshold would make life much more difficult
> > > as there would be a probe dependency between the PCI controller and
> > > the special ISA one (PCI to wait for the special ISA device to be
> > > probed and set the right threshold value from DT or ACPI table).
> > >
> > > Instead using PCIBIOS_MIN_IO is easier and should not impose much
> > > constraint as [PCIBIOS_MIN_IO, IO_SPACE_LIMIT] is available to
> > > the PCI controller for I/O tokens...
> >
> > What I am suggesting is to leave PCIBIOS_MIN_IO alone which still
> reserves
> > space for ISA controller and add a PCIBIOS_MIN_DIRECT_IO that will
> reserve
> > space for your direct address I/O on top of PCIBIOS_MIN_IO.
> 
> The PCIBIOS_MIN_DIRECT_IO name still suggests having something related
> to
> PCIBIOS_MIN_IO, but it really isn't. We are talking about multiple
> concepts here that are not the same but that are somewhat related:
> 
> a) keeping PCI devices from allocating low I/O ports on the PCI bus
>    that would conflict with ISA devices behind a bridge of the
>    same bus.
> 
> b) reserving the low 0x0-0xfff range of the Linux-internal I/O
>    space abstraction to a particular LPC or PCI domain to make
>    legacy device drivers work that hardcode a particular port
>    number.
> 
> c) Redirecting inb/outb to call a domain-specific accessor function
>    rather than doing the normal MMIO window for an LPC master or
>    more generally any arbitrary LPC or PCI domain that has a
>    nonstandard I/O space.
>    [side note: actually if we generalized this, we could avoid
>     assigning an MMIO range for the I/O space on the pci-mvebu
>     driver, and that would help free up some other remapping
>     windows]
> 
> I think there is no need to change a) here, we have PCIBIOS_MIN_IO
> today and even if we don't need it, there is no obvious downside.
> I would also argue that we can ignore b) for the discussion of
> the HiSilicon LPC driver, we just need to assign some range
> of logical addresses to each domain.
> 
> That means solving c) is the important problem here, and it
> shouldn't be so hard.  We can do this either with a single
> special domain as in the v5 patch series, or by generalizing it
> so that any I/O space mapping gets looked up through the device
> pointer of the bus master.

I am not very on the "generalized" multi-domain solution...
Currently the IO accessors prototypes have an unsigned long addr
as input parameter. If we live in a multi-domain IO system
how can we distinguish inside the accessor which domain addr
belongs to?

Thanks

Gab

> 
> 	Arnd

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 12:07                                 ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-18 12:07 UTC (permalink / raw)
  To: Arnd Bergmann, liviu.dudau-5wv7dgnIgG8
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Yuanzhichang,
	mark.rutland-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA,
	lorenzo.pieralisi-5wv7dgnIgG8, minyard-HInyCGIudOg,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, John Garry,
	will.deacon-5wv7dgnIgG8, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	xuwei (O),
	Linuxarm, zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, kantyzc-9Onoh4P/yGk

Hi Arnd many thanks for your help here

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd-r2nGTMty4D4@public.gmane.org]
> Sent: 18 November 2016 10:18
> To: liviu.dudau-5wv7dgnIgG8@public.gmane.org
> Cc: Gabriele Paoloni; linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org;
> Yuanzhichang; mark.rutland-5wv7dgnIgG8@public.gmane.org; devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org; minyard-HInyCGIudOg@public.gmane.org; linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org; John Garry; will.deacon-5wv7dgnIgG8@public.gmane.org; linux-
> kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; xuwei (O); Linuxarm; zourongrong-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org;
> robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org; kantyzc-9Onoh4P/yGk@public.gmane.org; linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> catalin.marinas-5wv7dgnIgG8@public.gmane.org; olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org; bhelgaas@go ogle.com;
> zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org; Jason Gunthorpe; Thomas Petazzoni
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Monday, November 14, 2016 11:26:25 AM CET liviu.dudau-5wv7dgnIgG8@public.gmane.org wrote:
> > On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> > > > Nope, that is not what it means. It means that PCI devices can
> see I/O
> > > > addresses
> > > > on the bus that start from 0. There never was any usage for non-
> PCI
> > > > controllers
> > >
> > > So I am a bit confused...
> > > From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > > It seems that ISA buses operate on cpu I/O address range [0,
> 0xFFF].
> > > I thought that was the reason why for most architectures we have
> > > PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA controllers
> > > usually use [0, PCIBIOS_MIN_IO - 1] )
> >
> > First of all, cpu I/O addresses is an x86-ism. ARM architectures and
> others
> >  have no separate address space for I/O, it is all merged into one
> unified
> > address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0 could
> mean
> > that we don't care about ISA I/O because the platform does not
> support having
> > an ISA bus (e.g.).
> 
> I think to be more specific, PCIBIOS_MIN_IO=0 would indicate that you
> cannot
> have a PCI-to-ISA or PCI-to-LPC bridge in any PCI domain. This is
> different
> from having an LPC master outside of PCI, as that lives in its own
> domain
> and has a separately addressable I/O space.

Yes correct so if we go for the single domain solution arch that
have PCIBIOS_MIN_IO=0 cannot support special devices such as LPC
unless we also redefine PCIBIOS_MIN_IO, right?

> 
> > > As said before this series forbid IO tokens to be in [0,
> PCIBIOS_MIN_IO)
> > > to allow special ISA controllers to use that range with special
> > > accessors.
> > > Having a variable threshold would make life much more difficult
> > > as there would be a probe dependency between the PCI controller and
> > > the special ISA one (PCI to wait for the special ISA device to be
> > > probed and set the right threshold value from DT or ACPI table).
> > >
> > > Instead using PCIBIOS_MIN_IO is easier and should not impose much
> > > constraint as [PCIBIOS_MIN_IO, IO_SPACE_LIMIT] is available to
> > > the PCI controller for I/O tokens...
> >
> > What I am suggesting is to leave PCIBIOS_MIN_IO alone which still
> reserves
> > space for ISA controller and add a PCIBIOS_MIN_DIRECT_IO that will
> reserve
> > space for your direct address I/O on top of PCIBIOS_MIN_IO.
> 
> The PCIBIOS_MIN_DIRECT_IO name still suggests having something related
> to
> PCIBIOS_MIN_IO, but it really isn't. We are talking about multiple
> concepts here that are not the same but that are somewhat related:
> 
> a) keeping PCI devices from allocating low I/O ports on the PCI bus
>    that would conflict with ISA devices behind a bridge of the
>    same bus.
> 
> b) reserving the low 0x0-0xfff range of the Linux-internal I/O
>    space abstraction to a particular LPC or PCI domain to make
>    legacy device drivers work that hardcode a particular port
>    number.
> 
> c) Redirecting inb/outb to call a domain-specific accessor function
>    rather than doing the normal MMIO window for an LPC master or
>    more generally any arbitrary LPC or PCI domain that has a
>    nonstandard I/O space.
>    [side note: actually if we generalized this, we could avoid
>     assigning an MMIO range for the I/O space on the pci-mvebu
>     driver, and that would help free up some other remapping
>     windows]
> 
> I think there is no need to change a) here, we have PCIBIOS_MIN_IO
> today and even if we don't need it, there is no obvious downside.
> I would also argue that we can ignore b) for the discussion of
> the HiSilicon LPC driver, we just need to assign some range
> of logical addresses to each domain.
> 
> That means solving c) is the important problem here, and it
> shouldn't be so hard.  We can do this either with a single
> special domain as in the v5 patch series, or by generalizing it
> so that any I/O space mapping gets looked up through the device
> pointer of the bus master.

I am not very on the "generalized" multi-domain solution...
Currently the IO accessors prototypes have an unsigned long addr
as input parameter. If we live in a multi-domain IO system
how can we distinguish inside the accessor which domain addr
belongs to?

Thanks

Gab

> 
> 	Arnd
--
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] 286+ messages in thread

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 12:07                                 ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-18 12:07 UTC (permalink / raw)
  To: Arnd Bergmann, liviu.dudau
  Cc: linux-arm-kernel, Yuanzhichang, mark.rutland, devicetree,
	lorenzo.pieralisi, minyard, linux-pci, benh, John Garry,
	will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, bhelgaas@go ogle.com, zhichang.yuan02,
	Jason Gunthorpe, Thomas Petazzoni

Hi Arnd many thanks for your help here

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 18 November 2016 10:18
> To: liviu.dudau@arm.com
> Cc: Gabriele Paoloni; linux-arm-kernel@lists.infradead.org;
> Yuanzhichang; mark.rutland@arm.com; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> catalin.marinas@arm.com; olof@lixom.net; bhelgaas@go ogle.com;
> zhichang.yuan02@gmail.com; Jason Gunthorpe; Thomas Petazzoni
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Monday, November 14, 2016 11:26:25 AM CET liviu.dudau@arm.com wrote:
> > On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> > > > Nope, that is not what it means. It means that PCI devices can
> see I/O
> > > > addresses
> > > > on the bus that start from 0. There never was any usage for non-
> PCI
> > > > controllers
> > >
> > > So I am a bit confused...
> > > From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > > It seems that ISA buses operate on cpu I/O address range [0,
> 0xFFF].
> > > I thought that was the reason why for most architectures we have
> > > PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA controllers
> > > usually use [0, PCIBIOS_MIN_IO - 1] )
> >
> > First of all, cpu I/O addresses is an x86-ism. ARM architectures and
> others
> >  have no separate address space for I/O, it is all merged into one
> unified
> > address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0 could
> mean
> > that we don't care about ISA I/O because the platform does not
> support having
> > an ISA bus (e.g.).
> 
> I think to be more specific, PCIBIOS_MIN_IO=0 would indicate that you
> cannot
> have a PCI-to-ISA or PCI-to-LPC bridge in any PCI domain. This is
> different
> from having an LPC master outside of PCI, as that lives in its own
> domain
> and has a separately addressable I/O space.

Yes correct so if we go for the single domain solution arch that
have PCIBIOS_MIN_IO=0 cannot support special devices such as LPC
unless we also redefine PCIBIOS_MIN_IO, right?

> 
> > > As said before this series forbid IO tokens to be in [0,
> PCIBIOS_MIN_IO)
> > > to allow special ISA controllers to use that range with special
> > > accessors.
> > > Having a variable threshold would make life much more difficult
> > > as there would be a probe dependency between the PCI controller and
> > > the special ISA one (PCI to wait for the special ISA device to be
> > > probed and set the right threshold value from DT or ACPI table).
> > >
> > > Instead using PCIBIOS_MIN_IO is easier and should not impose much
> > > constraint as [PCIBIOS_MIN_IO, IO_SPACE_LIMIT] is available to
> > > the PCI controller for I/O tokens...
> >
> > What I am suggesting is to leave PCIBIOS_MIN_IO alone which still
> reserves
> > space for ISA controller and add a PCIBIOS_MIN_DIRECT_IO that will
> reserve
> > space for your direct address I/O on top of PCIBIOS_MIN_IO.
> 
> The PCIBIOS_MIN_DIRECT_IO name still suggests having something related
> to
> PCIBIOS_MIN_IO, but it really isn't. We are talking about multiple
> concepts here that are not the same but that are somewhat related:
> 
> a) keeping PCI devices from allocating low I/O ports on the PCI bus
>    that would conflict with ISA devices behind a bridge of the
>    same bus.
> 
> b) reserving the low 0x0-0xfff range of the Linux-internal I/O
>    space abstraction to a particular LPC or PCI domain to make
>    legacy device drivers work that hardcode a particular port
>    number.
> 
> c) Redirecting inb/outb to call a domain-specific accessor function
>    rather than doing the normal MMIO window for an LPC master or
>    more generally any arbitrary LPC or PCI domain that has a
>    nonstandard I/O space.
>    [side note: actually if we generalized this, we could avoid
>     assigning an MMIO range for the I/O space on the pci-mvebu
>     driver, and that would help free up some other remapping
>     windows]
> 
> I think there is no need to change a) here, we have PCIBIOS_MIN_IO
> today and even if we don't need it, there is no obvious downside.
> I would also argue that we can ignore b) for the discussion of
> the HiSilicon LPC driver, we just need to assign some range
> of logical addresses to each domain.
> 
> That means solving c) is the important problem here, and it
> shouldn't be so hard.  We can do this either with a single
> special domain as in the v5 patch series, or by generalizing it
> so that any I/O space mapping gets looked up through the device
> pointer of the bus master.

I am not very on the "generalized" multi-domain solution...
Currently the IO accessors prototypes have an unsigned long addr
as input parameter. If we live in a multi-domain IO system
how can we distinguish inside the accessor which domain addr
belongs to?

Thanks

Gab

> 
> 	Arnd

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 12:07                                 ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-18 12:07 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd many thanks for your help here

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 18 November 2016 10:18
> To: liviu.dudau at arm.com
> Cc: Gabriele Paoloni; linux-arm-kernel at lists.infradead.org;
> Yuanzhichang; mark.rutland at arm.com; devicetree at vger.kernel.org;
> lorenzo.pieralisi at arm.com; minyard at acm.org; linux-pci at vger.kernel.org;
> benh at kernel.crashing.org; John Garry; will.deacon at arm.com; linux-
> kernel at vger.kernel.org; xuwei (O); Linuxarm; zourongrong at gmail.com;
> robh+dt at kernel.org; kantyzc at 163.com; linux-serial at vger.kernel.org;
> catalin.marinas at arm.com; olof at lixom.net; bhelgaas at go ogle.com;
> zhichang.yuan02 at gmail.com; Jason Gunthorpe; Thomas Petazzoni
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Monday, November 14, 2016 11:26:25 AM CET liviu.dudau at arm.com wrote:
> > On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> > > > Nope, that is not what it means. It means that PCI devices can
> see I/O
> > > > addresses
> > > > on the bus that start from 0. There never was any usage for non-
> PCI
> > > > controllers
> > >
> > > So I am a bit confused...
> > > From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > > It seems that ISA buses operate on cpu I/O address range [0,
> 0xFFF].
> > > I thought that was the reason why for most architectures we have
> > > PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA controllers
> > > usually use [0, PCIBIOS_MIN_IO - 1] )
> >
> > First of all, cpu I/O addresses is an x86-ism. ARM architectures and
> others
> >  have no separate address space for I/O, it is all merged into one
> unified
> > address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0 could
> mean
> > that we don't care about ISA I/O because the platform does not
> support having
> > an ISA bus (e.g.).
> 
> I think to be more specific, PCIBIOS_MIN_IO=0 would indicate that you
> cannot
> have a PCI-to-ISA or PCI-to-LPC bridge in any PCI domain. This is
> different
> from having an LPC master outside of PCI, as that lives in its own
> domain
> and has a separately addressable I/O space.

Yes correct so if we go for the single domain solution arch that
have PCIBIOS_MIN_IO=0 cannot support special devices such as LPC
unless we also redefine PCIBIOS_MIN_IO, right?

> 
> > > As said before this series forbid IO tokens to be in [0,
> PCIBIOS_MIN_IO)
> > > to allow special ISA controllers to use that range with special
> > > accessors.
> > > Having a variable threshold would make life much more difficult
> > > as there would be a probe dependency between the PCI controller and
> > > the special ISA one (PCI to wait for the special ISA device to be
> > > probed and set the right threshold value from DT or ACPI table).
> > >
> > > Instead using PCIBIOS_MIN_IO is easier and should not impose much
> > > constraint as [PCIBIOS_MIN_IO, IO_SPACE_LIMIT] is available to
> > > the PCI controller for I/O tokens...
> >
> > What I am suggesting is to leave PCIBIOS_MIN_IO alone which still
> reserves
> > space for ISA controller and add a PCIBIOS_MIN_DIRECT_IO that will
> reserve
> > space for your direct address I/O on top of PCIBIOS_MIN_IO.
> 
> The PCIBIOS_MIN_DIRECT_IO name still suggests having something related
> to
> PCIBIOS_MIN_IO, but it really isn't. We are talking about multiple
> concepts here that are not the same but that are somewhat related:
> 
> a) keeping PCI devices from allocating low I/O ports on the PCI bus
>    that would conflict with ISA devices behind a bridge of the
>    same bus.
> 
> b) reserving the low 0x0-0xfff range of the Linux-internal I/O
>    space abstraction to a particular LPC or PCI domain to make
>    legacy device drivers work that hardcode a particular port
>    number.
> 
> c) Redirecting inb/outb to call a domain-specific accessor function
>    rather than doing the normal MMIO window for an LPC master or
>    more generally any arbitrary LPC or PCI domain that has a
>    nonstandard I/O space.
>    [side note: actually if we generalized this, we could avoid
>     assigning an MMIO range for the I/O space on the pci-mvebu
>     driver, and that would help free up some other remapping
>     windows]
> 
> I think there is no need to change a) here, we have PCIBIOS_MIN_IO
> today and even if we don't need it, there is no obvious downside.
> I would also argue that we can ignore b) for the discussion of
> the HiSilicon LPC driver, we just need to assign some range
> of logical addresses to each domain.
> 
> That means solving c) is the important problem here, and it
> shouldn't be so hard.  We can do this either with a single
> special domain as in the v5 patch series, or by generalizing it
> so that any I/O space mapping gets looked up through the device
> pointer of the bus master.

I am not very on the "generalized" multi-domain solution...
Currently the IO accessors prototypes have an unsigned long addr
as input parameter. If we live in a multi-domain IO system
how can we distinguish inside the accessor which domain addr
belongs to?

Thanks

Gab

> 
> 	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-18 12:07                                 ` Gabriele Paoloni
  (?)
  (?)
@ 2016-11-18 12:24                                   ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 12:24 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: liviu.dudau, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, bhelgaas@go ogle.com, zhichang.yuan02,
	Jason Gunthorpe, Thomas Petazzoni

On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > On Monday, November 14, 2016 11:26:25 AM CET liviu.dudau@arm.com wrote:
> > > On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> > > > > Nope, that is not what it means. It means that PCI devices can
> > see I/O
> > > > > addresses
> > > > > on the bus that start from 0. There never was any usage for non-
> > PCI
> > > > > controllers
> > > >
> > > > So I am a bit confused...
> > > > From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > > > It seems that ISA buses operate on cpu I/O address range [0,
> > 0xFFF].
> > > > I thought that was the reason why for most architectures we have
> > > > PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA controllers
> > > > usually use [0, PCIBIOS_MIN_IO - 1] )
> > >
> > > First of all, cpu I/O addresses is an x86-ism. ARM architectures and
> > others
> > >  have no separate address space for I/O, it is all merged into one
> > unified
> > > address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0 could
> > mean
> > > that we don't care about ISA I/O because the platform does not
> > support having
> > > an ISA bus (e.g.).
> > 
> > I think to be more specific, PCIBIOS_MIN_IO=0 would indicate that you
> > cannot
> > have a PCI-to-ISA or PCI-to-LPC bridge in any PCI domain. This is
> > different
> > from having an LPC master outside of PCI, as that lives in its own
> > domain
> > and has a separately addressable I/O space.
> 
> Yes correct so if we go for the single domain solution arch that
> have PCIBIOS_MIN_IO=0 cannot support special devices such as LPC
> unless we also redefine PCIBIOS_MIN_IO, right?

This is what I was referring to below as the difference between
a) and b): Setting PCIBIOS_MIN_IO=0 means you cannot have LPC
behind PCI, but it shouldn't stop you from having a separate
LPC bridge.

> > The PCIBIOS_MIN_DIRECT_IO name still suggests having something related
> > to
> > PCIBIOS_MIN_IO, but it really isn't. We are talking about multiple
> > concepts here that are not the same but that are somewhat related:
> > 
> > a) keeping PCI devices from allocating low I/O ports on the PCI bus
> >    that would conflict with ISA devices behind a bridge of the
> >    same bus.
> > 
> > b) reserving the low 0x0-0xfff range of the Linux-internal I/O
> >    space abstraction to a particular LPC or PCI domain to make
> >    legacy device drivers work that hardcode a particular port
> >    number.
> > 
> > c) Redirecting inb/outb to call a domain-specific accessor function
> >    rather than doing the normal MMIO window for an LPC master or
> >    more generally any arbitrary LPC or PCI domain that has a
> >    nonstandard I/O space.
> >    [side note: actually if we generalized this, we could avoid
> >     assigning an MMIO range for the I/O space on the pci-mvebu
> >     driver, and that would help free up some other remapping
> >     windows]
> > 
> > I think there is no need to change a) here, we have PCIBIOS_MIN_IO
> > today and even if we don't need it, there is no obvious downside.
> > I would also argue that we can ignore b) for the discussion of
> > the HiSilicon LPC driver, we just need to assign some range
> > of logical addresses to each domain.
> > 
> > That means solving c) is the important problem here, and it
> > shouldn't be so hard.  We can do this either with a single
> > special domain as in the v5 patch series, or by generalizing it
> > so that any I/O space mapping gets looked up through the device
> > pointer of the bus master.
> 
> I am not very on the "generalized" multi-domain solution...
> Currently the IO accessors prototypes have an unsigned long addr
> as input parameter. If we live in a multi-domain IO system
> how can we distinguish inside the accessor which domain addr
> belongs to?

The easiest change compared to the v5 code would be to walk
a linked list of 'struct extio_ops' structures rather than
assuming there is only ever one of them. I think one of the
earlier versions actually did this.

Another option the IA64 approach mentioned in another subthread
today, looking up the operations based on an index from the
upper bits of the port number. If we do this, we probably
want to do that for all PIO access and replace the entire
virtual address remapping logic with that. I think Bjorn
in the past argued in favor of such an approach, while I
advocated the current scheme for simplicity based on how
every I/O space these days is just memory mapped (which now
turned out to be false, both on powerpc and arm64).

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 12:24                                   ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 12:24 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: liviu.dudau, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt@kernel.org

On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > On Monday, November 14, 2016 11:26:25 AM CET liviu.dudau@arm.com wrote:
> > > On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> > > > > Nope, that is not what it means. It means that PCI devices can
> > see I/O
> > > > > addresses
> > > > > on the bus that start from 0. There never was any usage for non-
> > PCI
> > > > > controllers
> > > >
> > > > So I am a bit confused...
> > > > From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > > > It seems that ISA buses operate on cpu I/O address range [0,
> > 0xFFF].
> > > > I thought that was the reason why for most architectures we have
> > > > PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA controllers
> > > > usually use [0, PCIBIOS_MIN_IO - 1] )
> > >
> > > First of all, cpu I/O addresses is an x86-ism. ARM architectures and
> > others
> > >  have no separate address space for I/O, it is all merged into one
> > unified
> > > address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0 could
> > mean
> > > that we don't care about ISA I/O because the platform does not
> > support having
> > > an ISA bus (e.g.).
> > 
> > I think to be more specific, PCIBIOS_MIN_IO=0 would indicate that you
> > cannot
> > have a PCI-to-ISA or PCI-to-LPC bridge in any PCI domain. This is
> > different
> > from having an LPC master outside of PCI, as that lives in its own
> > domain
> > and has a separately addressable I/O space.
> 
> Yes correct so if we go for the single domain solution arch that
> have PCIBIOS_MIN_IO=0 cannot support special devices such as LPC
> unless we also redefine PCIBIOS_MIN_IO, right?

This is what I was referring to below as the difference between
a) and b): Setting PCIBIOS_MIN_IO=0 means you cannot have LPC
behind PCI, but it shouldn't stop you from having a separate
LPC bridge.

> > The PCIBIOS_MIN_DIRECT_IO name still suggests having something related
> > to
> > PCIBIOS_MIN_IO, but it really isn't. We are talking about multiple
> > concepts here that are not the same but that are somewhat related:
> > 
> > a) keeping PCI devices from allocating low I/O ports on the PCI bus
> >    that would conflict with ISA devices behind a bridge of the
> >    same bus.
> > 
> > b) reserving the low 0x0-0xfff range of the Linux-internal I/O
> >    space abstraction to a particular LPC or PCI domain to make
> >    legacy device drivers work that hardcode a particular port
> >    number.
> > 
> > c) Redirecting inb/outb to call a domain-specific accessor function
> >    rather than doing the normal MMIO window for an LPC master or
> >    more generally any arbitrary LPC or PCI domain that has a
> >    nonstandard I/O space.
> >    [side note: actually if we generalized this, we could avoid
> >     assigning an MMIO range for the I/O space on the pci-mvebu
> >     driver, and that would help free up some other remapping
> >     windows]
> > 
> > I think there is no need to change a) here, we have PCIBIOS_MIN_IO
> > today and even if we don't need it, there is no obvious downside.
> > I would also argue that we can ignore b) for the discussion of
> > the HiSilicon LPC driver, we just need to assign some range
> > of logical addresses to each domain.
> > 
> > That means solving c) is the important problem here, and it
> > shouldn't be so hard.  We can do this either with a single
> > special domain as in the v5 patch series, or by generalizing it
> > so that any I/O space mapping gets looked up through the device
> > pointer of the bus master.
> 
> I am not very on the "generalized" multi-domain solution...
> Currently the IO accessors prototypes have an unsigned long addr
> as input parameter. If we live in a multi-domain IO system
> how can we distinguish inside the accessor which domain addr
> belongs to?

The easiest change compared to the v5 code would be to walk
a linked list of 'struct extio_ops' structures rather than
assuming there is only ever one of them. I think one of the
earlier versions actually did this.

Another option the IA64 approach mentioned in another subthread
today, looking up the operations based on an index from the
upper bits of the port number. If we do this, we probably
want to do that for all PIO access and replace the entire
virtual address remapping logic with that. I think Bjorn
in the past argued in favor of such an approach, while I
advocated the current scheme for simplicity based on how
every I/O space these days is just memory mapped (which now
turned out to be false, both on powerpc and arm64).

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 12:24                                   ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 12:24 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: mark.rutland, benh, catalin.marinas, liviu.dudau, Linuxarm,
	lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, linux-serial, linux-pci, devicetree, minyard,
	will.deacon, John Garry, zourongrong, robh+dt,
	bhelgaas@go ogle.com, kantyzc, zhichang.yuan02, linux-arm-kernel,
	Thomas Petazzoni, linux-kernel, Yuanzhichang, olof

On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > On Monday, November 14, 2016 11:26:25 AM CET liviu.dudau@arm.com wrote:
> > > On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> > > > > Nope, that is not what it means. It means that PCI devices can
> > see I/O
> > > > > addresses
> > > > > on the bus that start from 0. There never was any usage for non-
> > PCI
> > > > > controllers
> > > >
> > > > So I am a bit confused...
> > > > From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > > > It seems that ISA buses operate on cpu I/O address range [0,
> > 0xFFF].
> > > > I thought that was the reason why for most architectures we have
> > > > PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA controllers
> > > > usually use [0, PCIBIOS_MIN_IO - 1] )
> > >
> > > First of all, cpu I/O addresses is an x86-ism. ARM architectures and
> > others
> > >  have no separate address space for I/O, it is all merged into one
> > unified
> > > address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0 could
> > mean
> > > that we don't care about ISA I/O because the platform does not
> > support having
> > > an ISA bus (e.g.).
> > 
> > I think to be more specific, PCIBIOS_MIN_IO=0 would indicate that you
> > cannot
> > have a PCI-to-ISA or PCI-to-LPC bridge in any PCI domain. This is
> > different
> > from having an LPC master outside of PCI, as that lives in its own
> > domain
> > and has a separately addressable I/O space.
> 
> Yes correct so if we go for the single domain solution arch that
> have PCIBIOS_MIN_IO=0 cannot support special devices such as LPC
> unless we also redefine PCIBIOS_MIN_IO, right?

This is what I was referring to below as the difference between
a) and b): Setting PCIBIOS_MIN_IO=0 means you cannot have LPC
behind PCI, but it shouldn't stop you from having a separate
LPC bridge.

> > The PCIBIOS_MIN_DIRECT_IO name still suggests having something related
> > to
> > PCIBIOS_MIN_IO, but it really isn't. We are talking about multiple
> > concepts here that are not the same but that are somewhat related:
> > 
> > a) keeping PCI devices from allocating low I/O ports on the PCI bus
> >    that would conflict with ISA devices behind a bridge of the
> >    same bus.
> > 
> > b) reserving the low 0x0-0xfff range of the Linux-internal I/O
> >    space abstraction to a particular LPC or PCI domain to make
> >    legacy device drivers work that hardcode a particular port
> >    number.
> > 
> > c) Redirecting inb/outb to call a domain-specific accessor function
> >    rather than doing the normal MMIO window for an LPC master or
> >    more generally any arbitrary LPC or PCI domain that has a
> >    nonstandard I/O space.
> >    [side note: actually if we generalized this, we could avoid
> >     assigning an MMIO range for the I/O space on the pci-mvebu
> >     driver, and that would help free up some other remapping
> >     windows]
> > 
> > I think there is no need to change a) here, we have PCIBIOS_MIN_IO
> > today and even if we don't need it, there is no obvious downside.
> > I would also argue that we can ignore b) for the discussion of
> > the HiSilicon LPC driver, we just need to assign some range
> > of logical addresses to each domain.
> > 
> > That means solving c) is the important problem here, and it
> > shouldn't be so hard.  We can do this either with a single
> > special domain as in the v5 patch series, or by generalizing it
> > so that any I/O space mapping gets looked up through the device
> > pointer of the bus master.
> 
> I am not very on the "generalized" multi-domain solution...
> Currently the IO accessors prototypes have an unsigned long addr
> as input parameter. If we live in a multi-domain IO system
> how can we distinguish inside the accessor which domain addr
> belongs to?

The easiest change compared to the v5 code would be to walk
a linked list of 'struct extio_ops' structures rather than
assuming there is only ever one of them. I think one of the
earlier versions actually did this.

Another option the IA64 approach mentioned in another subthread
today, looking up the operations based on an index from the
upper bits of the port number. If we do this, we probably
want to do that for all PIO access and replace the entire
virtual address remapping logic with that. I think Bjorn
in the past argued in favor of such an approach, while I
advocated the current scheme for simplicity based on how
every I/O space these days is just memory mapped (which now
turned out to be false, both on powerpc and arm64).

	Arnd

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 12:24                                   ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 12:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > On Monday, November 14, 2016 11:26:25 AM CET liviu.dudau at arm.com wrote:
> > > On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> > > > > Nope, that is not what it means. It means that PCI devices can
> > see I/O
> > > > > addresses
> > > > > on the bus that start from 0. There never was any usage for non-
> > PCI
> > > > > controllers
> > > >
> > > > So I am a bit confused...
> > > > From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > > > It seems that ISA buses operate on cpu I/O address range [0,
> > 0xFFF].
> > > > I thought that was the reason why for most architectures we have
> > > > PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA controllers
> > > > usually use [0, PCIBIOS_MIN_IO - 1] )
> > >
> > > First of all, cpu I/O addresses is an x86-ism. ARM architectures and
> > others
> > >  have no separate address space for I/O, it is all merged into one
> > unified
> > > address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0 could
> > mean
> > > that we don't care about ISA I/O because the platform does not
> > support having
> > > an ISA bus (e.g.).
> > 
> > I think to be more specific, PCIBIOS_MIN_IO=0 would indicate that you
> > cannot
> > have a PCI-to-ISA or PCI-to-LPC bridge in any PCI domain. This is
> > different
> > from having an LPC master outside of PCI, as that lives in its own
> > domain
> > and has a separately addressable I/O space.
> 
> Yes correct so if we go for the single domain solution arch that
> have PCIBIOS_MIN_IO=0 cannot support special devices such as LPC
> unless we also redefine PCIBIOS_MIN_IO, right?

This is what I was referring to below as the difference between
a) and b): Setting PCIBIOS_MIN_IO=0 means you cannot have LPC
behind PCI, but it shouldn't stop you from having a separate
LPC bridge.

> > The PCIBIOS_MIN_DIRECT_IO name still suggests having something related
> > to
> > PCIBIOS_MIN_IO, but it really isn't. We are talking about multiple
> > concepts here that are not the same but that are somewhat related:
> > 
> > a) keeping PCI devices from allocating low I/O ports on the PCI bus
> >    that would conflict with ISA devices behind a bridge of the
> >    same bus.
> > 
> > b) reserving the low 0x0-0xfff range of the Linux-internal I/O
> >    space abstraction to a particular LPC or PCI domain to make
> >    legacy device drivers work that hardcode a particular port
> >    number.
> > 
> > c) Redirecting inb/outb to call a domain-specific accessor function
> >    rather than doing the normal MMIO window for an LPC master or
> >    more generally any arbitrary LPC or PCI domain that has a
> >    nonstandard I/O space.
> >    [side note: actually if we generalized this, we could avoid
> >     assigning an MMIO range for the I/O space on the pci-mvebu
> >     driver, and that would help free up some other remapping
> >     windows]
> > 
> > I think there is no need to change a) here, we have PCIBIOS_MIN_IO
> > today and even if we don't need it, there is no obvious downside.
> > I would also argue that we can ignore b) for the discussion of
> > the HiSilicon LPC driver, we just need to assign some range
> > of logical addresses to each domain.
> > 
> > That means solving c) is the important problem here, and it
> > shouldn't be so hard.  We can do this either with a single
> > special domain as in the v5 patch series, or by generalizing it
> > so that any I/O space mapping gets looked up through the device
> > pointer of the bus master.
> 
> I am not very on the "generalized" multi-domain solution...
> Currently the IO accessors prototypes have an unsigned long addr
> as input parameter. If we live in a multi-domain IO system
> how can we distinguish inside the accessor which domain addr
> belongs to?

The easiest change compared to the v5 code would be to walk
a linked list of 'struct extio_ops' structures rather than
assuming there is only ever one of them. I think one of the
earlier versions actually did this.

Another option the IA64 approach mentioned in another subthread
today, looking up the operations based on an index from the
upper bits of the port number. If we do this, we probably
want to do that for all PIO access and replace the entire
virtual address remapping logic with that. I think Bjorn
in the past argued in favor of such an approach, while I
advocated the current scheme for simplicity based on how
every I/O space these days is just memory mapped (which now
turned out to be false, both on powerpc and arm64).

	Arnd

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-18 12:24                                   ` Arnd Bergmann
  (?)
  (?)
@ 2016-11-18 12:53                                     ` Gabriele Paoloni
  -1 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-18 12:53 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: liviu.dudau, linux-arm-kernel, Yuanzhichang, mark.rutland,
	devicetree, lorenzo.pieralisi, minyard, linux-pci, benh,
	John Garry, will.deacon, linux-kernel, xuwei (O),
	Linuxarm, zourongrong, robh+dt, kantyzc, linux-serial,
	catalin.marinas, olof, bhelgaas@go og le.com, zhichang.yuan02,
	Jason Gunthorpe, Thomas Petazzoni

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 18 November 2016 12:24
> To: Gabriele Paoloni
> Cc: liviu.dudau@arm.com; linux-arm-kernel@lists.infradead.org;
> Yuanzhichang; mark.rutland@arm.com; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> catalin.marinas@arm.com; olof@lixom.net; bhelgaas@go og le.com;
> zhichang.yuan02@gmail.com; Jason Gunthorpe; Thomas Petazzoni
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni wrote:
> > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > On Monday, November 14, 2016 11:26:25 AM CET liviu.dudau@arm.com
> wrote:
> > > > On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> > > > > > Nope, that is not what it means. It means that PCI devices
> can
> > > see I/O
> > > > > > addresses
> > > > > > on the bus that start from 0. There never was any usage for
> non-
> > > PCI
> > > > > > controllers
> > > > >
> > > > > So I am a bit confused...
> > > > > From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > > > > It seems that ISA buses operate on cpu I/O address range [0,
> > > 0xFFF].
> > > > > I thought that was the reason why for most architectures we
> have
> > > > > PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA
> controllers
> > > > > usually use [0, PCIBIOS_MIN_IO - 1] )
> > > >
> > > > First of all, cpu I/O addresses is an x86-ism. ARM architectures
> and
> > > others
> > > >  have no separate address space for I/O, it is all merged into
> one
> > > unified
> > > > address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0
> could
> > > mean
> > > > that we don't care about ISA I/O because the platform does not
> > > support having
> > > > an ISA bus (e.g.).
> > >
> > > I think to be more specific, PCIBIOS_MIN_IO=0 would indicate that
> you
> > > cannot
> > > have a PCI-to-ISA or PCI-to-LPC bridge in any PCI domain. This is
> > > different
> > > from having an LPC master outside of PCI, as that lives in its own
> > > domain
> > > and has a separately addressable I/O space.
> >
> > Yes correct so if we go for the single domain solution arch that
> > have PCIBIOS_MIN_IO=0 cannot support special devices such as LPC
> > unless we also redefine PCIBIOS_MIN_IO, right?
> 
> This is what I was referring to below as the difference between
> a) and b): Setting PCIBIOS_MIN_IO=0 means you cannot have LPC
> behind PCI, but it shouldn't stop you from having a separate
> LPC bridge.
> 
> > > The PCIBIOS_MIN_DIRECT_IO name still suggests having something
> related
> > > to
> > > PCIBIOS_MIN_IO, but it really isn't. We are talking about multiple
> > > concepts here that are not the same but that are somewhat related:
> > >
> > > a) keeping PCI devices from allocating low I/O ports on the PCI bus
> > >    that would conflict with ISA devices behind a bridge of the
> > >    same bus.
> > >
> > > b) reserving the low 0x0-0xfff range of the Linux-internal I/O
> > >    space abstraction to a particular LPC or PCI domain to make
> > >    legacy device drivers work that hardcode a particular port
> > >    number.
> > >
> > > c) Redirecting inb/outb to call a domain-specific accessor function
> > >    rather than doing the normal MMIO window for an LPC master or
> > >    more generally any arbitrary LPC or PCI domain that has a
> > >    nonstandard I/O space.
> > >    [side note: actually if we generalized this, we could avoid
> > >     assigning an MMIO range for the I/O space on the pci-mvebu
> > >     driver, and that would help free up some other remapping
> > >     windows]
> > >
> > > I think there is no need to change a) here, we have PCIBIOS_MIN_IO
> > > today and even if we don't need it, there is no obvious downside.
> > > I would also argue that we can ignore b) for the discussion of
> > > the HiSilicon LPC driver, we just need to assign some range
> > > of logical addresses to each domain.
> > >
> > > That means solving c) is the important problem here, and it
> > > shouldn't be so hard.  We can do this either with a single
> > > special domain as in the v5 patch series, or by generalizing it
> > > so that any I/O space mapping gets looked up through the device
> > > pointer of the bus master.
> >
> > I am not very on the "generalized" multi-domain solution...
> > Currently the IO accessors prototypes have an unsigned long addr
> > as input parameter. If we live in a multi-domain IO system
> > how can we distinguish inside the accessor which domain addr
> > belongs to?
> 
> The easiest change compared to the v5 code would be to walk
> a linked list of 'struct extio_ops' structures rather than
> assuming there is only ever one of them. I think one of the
> earlier versions actually did this.

Right but if my understanding is correct if we live in a multi-
domain I/O space world when you have an input addr in the I/O
accessors this addr can be duplicated (for example for the standard
PCI IO domain and for our special LPC domain).
So effectively even if you walk a linked list there is a problem
of disambiguation...am I right? 

> 
> Another option the IA64 approach mentioned in another subthread
> today, looking up the operations based on an index from the
> upper bits of the port number. If we do this, we probably
> want to do that for all PIO access and replace the entire
> virtual address remapping logic with that. I think Bjorn
> in the past argued in favor of such an approach, while I
> advocated the current scheme for simplicity based on how
> every I/O space these days is just memory mapped (which now
> turned out to be false, both on powerpc and arm64).

This seems really complex...I am a bit worried that possibly
we end up in having the maintainers saying that it is not worth
to re-invent the world just for this special LPC device...

To be honest with you I would keep things simple for this
LPC and introduce more complex reworks later if more devices
need to be introduced.

What if we stick on a single domain now where we introduce a
reserved threshold for the IO space (say INDIRECT_MAX_IO).

We define INDIRECT_MAX_IO as 0 in "include/linux/extio.h" and
we define INDIRECT_MAX_IO as 0x1000 in "arch/arm64/include/asm/io.h"

So effectively this threshold can change according to the
architecture and so far we only define it for ARM64 as we need
it for ARM64...

Thoughts?

Thanks again

Gab

> 
> 	Arnd

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 12:53                                     ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-18 12:53 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: liviu.dudau-5wv7dgnIgG8,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Yuanzhichang,
	mark.rutland-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA,
	lorenzo.pieralisi-5wv7dgnIgG8, minyard-HInyCGIudOg,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, John Garry,
	will.deacon-5wv7dgnIgG8, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	xuwei (O),
	Linuxarm, zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd-r2nGTMty4D4@public.gmane.org]
> Sent: 18 November 2016 12:24
> To: Gabriele Paoloni
> Cc: liviu.dudau-5wv7dgnIgG8@public.gmane.org; linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org;
> Yuanzhichang; mark.rutland-5wv7dgnIgG8@public.gmane.org; devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org; minyard-HInyCGIudOg@public.gmane.org; linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org; John Garry; will.deacon-5wv7dgnIgG8@public.gmane.org; linux-
> kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; xuwei (O); Linuxarm; zourongrong-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org;
> robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org; kantyzc-9Onoh4P/yGk@public.gmane.org; linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> catalin.marinas-5wv7dgnIgG8@public.gmane.org; olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org; bhelgaas@go og le.com;
> zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org; Jason Gunthorpe; Thomas Petazzoni
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni wrote:
> > > From: Arnd Bergmann [mailto:arnd-r2nGTMty4D4@public.gmane.org]
> > > On Monday, November 14, 2016 11:26:25 AM CET liviu.dudau-5wv7dgnIgG8@public.gmane.org
> wrote:
> > > > On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> > > > > > Nope, that is not what it means. It means that PCI devices
> can
> > > see I/O
> > > > > > addresses
> > > > > > on the bus that start from 0. There never was any usage for
> non-
> > > PCI
> > > > > > controllers
> > > > >
> > > > > So I am a bit confused...
> > > > > From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > > > > It seems that ISA buses operate on cpu I/O address range [0,
> > > 0xFFF].
> > > > > I thought that was the reason why for most architectures we
> have
> > > > > PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA
> controllers
> > > > > usually use [0, PCIBIOS_MIN_IO - 1] )
> > > >
> > > > First of all, cpu I/O addresses is an x86-ism. ARM architectures
> and
> > > others
> > > >  have no separate address space for I/O, it is all merged into
> one
> > > unified
> > > > address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0
> could
> > > mean
> > > > that we don't care about ISA I/O because the platform does not
> > > support having
> > > > an ISA bus (e.g.).
> > >
> > > I think to be more specific, PCIBIOS_MIN_IO=0 would indicate that
> you
> > > cannot
> > > have a PCI-to-ISA or PCI-to-LPC bridge in any PCI domain. This is
> > > different
> > > from having an LPC master outside of PCI, as that lives in its own
> > > domain
> > > and has a separately addressable I/O space.
> >
> > Yes correct so if we go for the single domain solution arch that
> > have PCIBIOS_MIN_IO=0 cannot support special devices such as LPC
> > unless we also redefine PCIBIOS_MIN_IO, right?
> 
> This is what I was referring to below as the difference between
> a) and b): Setting PCIBIOS_MIN_IO=0 means you cannot have LPC
> behind PCI, but it shouldn't stop you from having a separate
> LPC bridge.
> 
> > > The PCIBIOS_MIN_DIRECT_IO name still suggests having something
> related
> > > to
> > > PCIBIOS_MIN_IO, but it really isn't. We are talking about multiple
> > > concepts here that are not the same but that are somewhat related:
> > >
> > > a) keeping PCI devices from allocating low I/O ports on the PCI bus
> > >    that would conflict with ISA devices behind a bridge of the
> > >    same bus.
> > >
> > > b) reserving the low 0x0-0xfff range of the Linux-internal I/O
> > >    space abstraction to a particular LPC or PCI domain to make
> > >    legacy device drivers work that hardcode a particular port
> > >    number.
> > >
> > > c) Redirecting inb/outb to call a domain-specific accessor function
> > >    rather than doing the normal MMIO window for an LPC master or
> > >    more generally any arbitrary LPC or PCI domain that has a
> > >    nonstandard I/O space.
> > >    [side note: actually if we generalized this, we could avoid
> > >     assigning an MMIO range for the I/O space on the pci-mvebu
> > >     driver, and that would help free up some other remapping
> > >     windows]
> > >
> > > I think there is no need to change a) here, we have PCIBIOS_MIN_IO
> > > today and even if we don't need it, there is no obvious downside.
> > > I would also argue that we can ignore b) for the discussion of
> > > the HiSilicon LPC driver, we just need to assign some range
> > > of logical addresses to each domain.
> > >
> > > That means solving c) is the important problem here, and it
> > > shouldn't be so hard.  We can do this either with a single
> > > special domain as in the v5 patch series, or by generalizing it
> > > so that any I/O space mapping gets looked up through the device
> > > pointer of the bus master.
> >
> > I am not very on the "generalized" multi-domain solution...
> > Currently the IO accessors prototypes have an unsigned long addr
> > as input parameter. If we live in a multi-domain IO system
> > how can we distinguish inside the accessor which domain addr
> > belongs to?
> 
> The easiest change compared to the v5 code would be to walk
> a linked list of 'struct extio_ops' structures rather than
> assuming there is only ever one of them. I think one of the
> earlier versions actually did this.

Right but if my understanding is correct if we live in a multi-
domain I/O space world when you have an input addr in the I/O
accessors this addr can be duplicated (for example for the standard
PCI IO domain and for our special LPC domain).
So effectively even if you walk a linked list there is a problem
of disambiguation...am I right? 

> 
> Another option the IA64 approach mentioned in another subthread
> today, looking up the operations based on an index from the
> upper bits of the port number. If we do this, we probably
> want to do that for all PIO access and replace the entire
> virtual address remapping logic with that. I think Bjorn
> in the past argued in favor of such an approach, while I
> advocated the current scheme for simplicity based on how
> every I/O space these days is just memory mapped (which now
> turned out to be false, both on powerpc and arm64).

This seems really complex...I am a bit worried that possibly
we end up in having the maintainers saying that it is not worth
to re-invent the world just for this special LPC device...

To be honest with you I would keep things simple for this
LPC and introduce more complex reworks later if more devices
need to be introduced.

What if we stick on a single domain now where we introduce a
reserved threshold for the IO space (say INDIRECT_MAX_IO).

We define INDIRECT_MAX_IO as 0 in "include/linux/extio.h" and
we define INDIRECT_MAX_IO as 0x1000 in "arch/arm64/include/asm/io.h"

So effectively this threshold can change according to the
architecture and so far we only define it for ARM64 as we need
it for ARM64...

Thoughts?

Thanks again

Gab

> 
> 	Arnd
--
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] 286+ messages in thread

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 12:53                                     ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-18 12:53 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: mark.rutland, benh, catalin.marinas, liviu.dudau, Linuxarm,
	lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, linux-serial, linux-pci, devicetree, minyard,
	will.deacon, John Garry, zourongrong, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02,
	linux-arm-kernel, Thomas Petazzoni, linux-kernel, Yuanzhichang,
	olof

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 18 November 2016 12:24
> To: Gabriele Paoloni
> Cc: liviu.dudau@arm.com; linux-arm-kernel@lists.infradead.org;
> Yuanzhichang; mark.rutland@arm.com; devicetree@vger.kernel.org;
> lorenzo.pieralisi@arm.com; minyard@acm.org; linux-pci@vger.kernel.org;
> benh@kernel.crashing.org; John Garry; will.deacon@arm.com; linux-
> kernel@vger.kernel.org; xuwei (O); Linuxarm; zourongrong@gmail.com;
> robh+dt@kernel.org; kantyzc@163.com; linux-serial@vger.kernel.org;
> catalin.marinas@arm.com; olof@lixom.net; bhelgaas@go og le.com;
> zhichang.yuan02@gmail.com; Jason Gunthorpe; Thomas Petazzoni
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni wrote:
> > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > On Monday, November 14, 2016 11:26:25 AM CET liviu.dudau@arm.com
> wrote:
> > > > On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> > > > > > Nope, that is not what it means. It means that PCI devices
> can
> > > see I/O
> > > > > > addresses
> > > > > > on the bus that start from 0. There never was any usage for
> non-
> > > PCI
> > > > > > controllers
> > > > >
> > > > > So I am a bit confused...
> > > > > From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > > > > It seems that ISA buses operate on cpu I/O address range [0,
> > > 0xFFF].
> > > > > I thought that was the reason why for most architectures we
> have
> > > > > PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA
> controllers
> > > > > usually use [0, PCIBIOS_MIN_IO - 1] )
> > > >
> > > > First of all, cpu I/O addresses is an x86-ism. ARM architectures
> and
> > > others
> > > >  have no separate address space for I/O, it is all merged into
> one
> > > unified
> > > > address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0
> could
> > > mean
> > > > that we don't care about ISA I/O because the platform does not
> > > support having
> > > > an ISA bus (e.g.).
> > >
> > > I think to be more specific, PCIBIOS_MIN_IO=0 would indicate that
> you
> > > cannot
> > > have a PCI-to-ISA or PCI-to-LPC bridge in any PCI domain. This is
> > > different
> > > from having an LPC master outside of PCI, as that lives in its own
> > > domain
> > > and has a separately addressable I/O space.
> >
> > Yes correct so if we go for the single domain solution arch that
> > have PCIBIOS_MIN_IO=0 cannot support special devices such as LPC
> > unless we also redefine PCIBIOS_MIN_IO, right?
> 
> This is what I was referring to below as the difference between
> a) and b): Setting PCIBIOS_MIN_IO=0 means you cannot have LPC
> behind PCI, but it shouldn't stop you from having a separate
> LPC bridge.
> 
> > > The PCIBIOS_MIN_DIRECT_IO name still suggests having something
> related
> > > to
> > > PCIBIOS_MIN_IO, but it really isn't. We are talking about multiple
> > > concepts here that are not the same but that are somewhat related:
> > >
> > > a) keeping PCI devices from allocating low I/O ports on the PCI bus
> > >    that would conflict with ISA devices behind a bridge of the
> > >    same bus.
> > >
> > > b) reserving the low 0x0-0xfff range of the Linux-internal I/O
> > >    space abstraction to a particular LPC or PCI domain to make
> > >    legacy device drivers work that hardcode a particular port
> > >    number.
> > >
> > > c) Redirecting inb/outb to call a domain-specific accessor function
> > >    rather than doing the normal MMIO window for an LPC master or
> > >    more generally any arbitrary LPC or PCI domain that has a
> > >    nonstandard I/O space.
> > >    [side note: actually if we generalized this, we could avoid
> > >     assigning an MMIO range for the I/O space on the pci-mvebu
> > >     driver, and that would help free up some other remapping
> > >     windows]
> > >
> > > I think there is no need to change a) here, we have PCIBIOS_MIN_IO
> > > today and even if we don't need it, there is no obvious downside.
> > > I would also argue that we can ignore b) for the discussion of
> > > the HiSilicon LPC driver, we just need to assign some range
> > > of logical addresses to each domain.
> > >
> > > That means solving c) is the important problem here, and it
> > > shouldn't be so hard.  We can do this either with a single
> > > special domain as in the v5 patch series, or by generalizing it
> > > so that any I/O space mapping gets looked up through the device
> > > pointer of the bus master.
> >
> > I am not very on the "generalized" multi-domain solution...
> > Currently the IO accessors prototypes have an unsigned long addr
> > as input parameter. If we live in a multi-domain IO system
> > how can we distinguish inside the accessor which domain addr
> > belongs to?
> 
> The easiest change compared to the v5 code would be to walk
> a linked list of 'struct extio_ops' structures rather than
> assuming there is only ever one of them. I think one of the
> earlier versions actually did this.

Right but if my understanding is correct if we live in a multi-
domain I/O space world when you have an input addr in the I/O
accessors this addr can be duplicated (for example for the standard
PCI IO domain and for our special LPC domain).
So effectively even if you walk a linked list there is a problem
of disambiguation...am I right? 

> 
> Another option the IA64 approach mentioned in another subthread
> today, looking up the operations based on an index from the
> upper bits of the port number. If we do this, we probably
> want to do that for all PIO access and replace the entire
> virtual address remapping logic with that. I think Bjorn
> in the past argued in favor of such an approach, while I
> advocated the current scheme for simplicity based on how
> every I/O space these days is just memory mapped (which now
> turned out to be false, both on powerpc and arm64).

This seems really complex...I am a bit worried that possibly
we end up in having the maintainers saying that it is not worth
to re-invent the world just for this special LPC device...

To be honest with you I would keep things simple for this
LPC and introduce more complex reworks later if more devices
need to be introduced.

What if we stick on a single domain now where we introduce a
reserved threshold for the IO space (say INDIRECT_MAX_IO).

We define INDIRECT_MAX_IO as 0 in "include/linux/extio.h" and
we define INDIRECT_MAX_IO as 0x1000 in "arch/arm64/include/asm/io.h"

So effectively this threshold can change according to the
architecture and so far we only define it for ARM64 as we need
it for ARM64...

Thoughts?

Thanks again

Gab

> 
> 	Arnd

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 12:53                                     ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-18 12:53 UTC (permalink / raw)
  To: linux-arm-kernel

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 18 November 2016 12:24
> To: Gabriele Paoloni
> Cc: liviu.dudau at arm.com; linux-arm-kernel at lists.infradead.org;
> Yuanzhichang; mark.rutland at arm.com; devicetree at vger.kernel.org;
> lorenzo.pieralisi at arm.com; minyard at acm.org; linux-pci at vger.kernel.org;
> benh at kernel.crashing.org; John Garry; will.deacon at arm.com; linux-
> kernel at vger.kernel.org; xuwei (O); Linuxarm; zourongrong at gmail.com;
> robh+dt at kernel.org; kantyzc at 163.com; linux-serial at vger.kernel.org;
> catalin.marinas at arm.com; olof at lixom.net; bhelgaas at go og le.com;
> zhichang.yuan02 at gmail.com; Jason Gunthorpe; Thomas Petazzoni
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni wrote:
> > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > On Monday, November 14, 2016 11:26:25 AM CET liviu.dudau at arm.com
> wrote:
> > > > On Mon, Nov 14, 2016 at 08:26:42AM +0000, Gabriele Paoloni wrote:
> > > > > > Nope, that is not what it means. It means that PCI devices
> can
> > > see I/O
> > > > > > addresses
> > > > > > on the bus that start from 0. There never was any usage for
> non-
> > > PCI
> > > > > > controllers
> > > > >
> > > > > So I am a bit confused...
> > > > > From http://www.firmware.org/1275/bindings/isa/isa0_4d.ps
> > > > > It seems that ISA buses operate on cpu I/O address range [0,
> > > 0xFFF].
> > > > > I thought that was the reason why for most architectures we
> have
> > > > > PCIBIOS_MIN_IO equal to 0x1000 (so I thought that ISA
> controllers
> > > > > usually use [0, PCIBIOS_MIN_IO - 1] )
> > > >
> > > > First of all, cpu I/O addresses is an x86-ism. ARM architectures
> and
> > > others
> > > >  have no separate address space for I/O, it is all merged into
> one
> > > unified
> > > > address space. So, on arm/arm64 for example, PCIBIOS_MIN_IO = 0
> could
> > > mean
> > > > that we don't care about ISA I/O because the platform does not
> > > support having
> > > > an ISA bus (e.g.).
> > >
> > > I think to be more specific, PCIBIOS_MIN_IO=0 would indicate that
> you
> > > cannot
> > > have a PCI-to-ISA or PCI-to-LPC bridge in any PCI domain. This is
> > > different
> > > from having an LPC master outside of PCI, as that lives in its own
> > > domain
> > > and has a separately addressable I/O space.
> >
> > Yes correct so if we go for the single domain solution arch that
> > have PCIBIOS_MIN_IO=0 cannot support special devices such as LPC
> > unless we also redefine PCIBIOS_MIN_IO, right?
> 
> This is what I was referring to below as the difference between
> a) and b): Setting PCIBIOS_MIN_IO=0 means you cannot have LPC
> behind PCI, but it shouldn't stop you from having a separate
> LPC bridge.
> 
> > > The PCIBIOS_MIN_DIRECT_IO name still suggests having something
> related
> > > to
> > > PCIBIOS_MIN_IO, but it really isn't. We are talking about multiple
> > > concepts here that are not the same but that are somewhat related:
> > >
> > > a) keeping PCI devices from allocating low I/O ports on the PCI bus
> > >    that would conflict with ISA devices behind a bridge of the
> > >    same bus.
> > >
> > > b) reserving the low 0x0-0xfff range of the Linux-internal I/O
> > >    space abstraction to a particular LPC or PCI domain to make
> > >    legacy device drivers work that hardcode a particular port
> > >    number.
> > >
> > > c) Redirecting inb/outb to call a domain-specific accessor function
> > >    rather than doing the normal MMIO window for an LPC master or
> > >    more generally any arbitrary LPC or PCI domain that has a
> > >    nonstandard I/O space.
> > >    [side note: actually if we generalized this, we could avoid
> > >     assigning an MMIO range for the I/O space on the pci-mvebu
> > >     driver, and that would help free up some other remapping
> > >     windows]
> > >
> > > I think there is no need to change a) here, we have PCIBIOS_MIN_IO
> > > today and even if we don't need it, there is no obvious downside.
> > > I would also argue that we can ignore b) for the discussion of
> > > the HiSilicon LPC driver, we just need to assign some range
> > > of logical addresses to each domain.
> > >
> > > That means solving c) is the important problem here, and it
> > > shouldn't be so hard.  We can do this either with a single
> > > special domain as in the v5 patch series, or by generalizing it
> > > so that any I/O space mapping gets looked up through the device
> > > pointer of the bus master.
> >
> > I am not very on the "generalized" multi-domain solution...
> > Currently the IO accessors prototypes have an unsigned long addr
> > as input parameter. If we live in a multi-domain IO system
> > how can we distinguish inside the accessor which domain addr
> > belongs to?
> 
> The easiest change compared to the v5 code would be to walk
> a linked list of 'struct extio_ops' structures rather than
> assuming there is only ever one of them. I think one of the
> earlier versions actually did this.

Right but if my understanding is correct if we live in a multi-
domain I/O space world when you have an input addr in the I/O
accessors this addr can be duplicated (for example for the standard
PCI IO domain and for our special LPC domain).
So effectively even if you walk a linked list there is a problem
of disambiguation...am I right? 

> 
> Another option the IA64 approach mentioned in another subthread
> today, looking up the operations based on an index from the
> upper bits of the port number. If we do this, we probably
> want to do that for all PIO access and replace the entire
> virtual address remapping logic with that. I think Bjorn
> in the past argued in favor of such an approach, while I
> advocated the current scheme for simplicity based on how
> every I/O space these days is just memory mapped (which now
> turned out to be false, both on powerpc and arm64).

This seems really complex...I am a bit worried that possibly
we end up in having the maintainers saying that it is not worth
to re-invent the world just for this special LPC device...

To be honest with you I would keep things simple for this
LPC and introduce more complex reworks later if more devices
need to be introduced.

What if we stick on a single domain now where we introduce a
reserved threshold for the IO space (say INDIRECT_MAX_IO).

We define INDIRECT_MAX_IO as 0 in "include/linux/extio.h" and
we define INDIRECT_MAX_IO as 0x1000 in "arch/arm64/include/asm/io.h"

So effectively this threshold can change according to the
architecture and so far we only define it for ARM64 as we need
it for ARM64...

Thoughts?

Thanks again

Gab

> 
> 	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-18 12:53                                     ` Gabriele Paoloni
  (?)
@ 2016-11-18 13:42                                       ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 13:42 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Gabriele Paoloni, mark.rutland, benh, catalin.marinas,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, linux-serial, linux-pci, devicetree, minyard,
	will.deacon, John Garry, zourongrong, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02,
	Thomas Petazzoni, linux-kernel, Yuanzhichang, olof

On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni wrote:
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> > On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni wrote:
> > > > I think there is no need to change a) here, we have PCIBIOS_MIN_IO
> > > > today and even if we don't need it, there is no obvious downside.
> > > > I would also argue that we can ignore b) for the discussion of
> > > > the HiSilicon LPC driver, we just need to assign some range
> > > > of logical addresses to each domain.
> > > >
> > > > That means solving c) is the important problem here, and it
> > > > shouldn't be so hard.  We can do this either with a single
> > > > special domain as in the v5 patch series, or by generalizing it
> > > > so that any I/O space mapping gets looked up through the device
> > > > pointer of the bus master.
> > >
> > > I am not very on the "generalized" multi-domain solution...
> > > Currently the IO accessors prototypes have an unsigned long addr
> > > as input parameter. If we live in a multi-domain IO system
> > > how can we distinguish inside the accessor which domain addr
> > > belongs to?
> > 
> > The easiest change compared to the v5 code would be to walk
> > a linked list of 'struct extio_ops' structures rather than
> > assuming there is only ever one of them. I think one of the
> > earlier versions actually did this.
> 
> Right but if my understanding is correct if we live in a multi-
> domain I/O space world when you have an input addr in the I/O
> accessors this addr can be duplicated (for example for the standard
> PCI IO domain and for our special LPC domain).
> So effectively even if you walk a linked list there is a problem
> of disambiguation...am I right? 

No, unlike the PCI memory space, the PIO addresses are not
usually distinct, i.e. every PCI bus has its own 64K I/O
addresses starting at zero. We linearize them into the
Linux I/O space using the per-domain io_offset value.

For the ISA/LPC spaces there are only 4k of addresses, they
the bus addresses always overlap, but we can trivially
figure out the bus address from Linux I/O port number
by subtracting the start of the range.

> > Another option the IA64 approach mentioned in another subthread
> > today, looking up the operations based on an index from the
> > upper bits of the port number. If we do this, we probably
> > want to do that for all PIO access and replace the entire
> > virtual address remapping logic with that. I think Bjorn
> > in the past argued in favor of such an approach, while I
> > advocated the current scheme for simplicity based on how
> > every I/O space these days is just memory mapped (which now
> > turned out to be false, both on powerpc and arm64).
> 
> This seems really complex...I am a bit worried that possibly
> we end up in having the maintainers saying that it is not worth
> to re-invent the world just for this special LPC device...

It would clearly be a rather invasive change, but the
end-result isn't necessarily more complex than what we
have today, as we'd kill off the crazy pci_pio_to_address()
and pci_address_to_pio() hacks in address translation.

> To be honest with you I would keep things simple for this
> LPC and introduce more complex reworks later if more devices
> need to be introduced.
> 
> What if we stick on a single domain now where we introduce a
> reserved threshold for the IO space (say INDIRECT_MAX_IO).

I said having a single domain is fine, but I still don't
like the idea of reserving low port numbers for this hack,
it would mean that the numbers change for everyone else.

> We define INDIRECT_MAX_IO as 0 in "include/linux/extio.h" and
> we define INDIRECT_MAX_IO as 0x1000 in "arch/arm64/include/asm/io.h"
> 
> So effectively this threshold can change according to the
> architecture and so far we only define it for ARM64 as we need
> it for ARM64...

I liked the idea of having it done in asm-generic/io.h (in an ifdef)
and lib/*.c under an as someone suggested earlier. There is nothing
ARM64 specific in the implementation.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 13:42                                       ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 13:42 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Gabriele Paoloni, mark.rutland, benh, catalin.marinas,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, linux-serial, linux-pci, devicetree, minyard,
	will.deacon, John Garry, zourongrong

On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni wrote:
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> > On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni wrote:
> > > > I think there is no need to change a) here, we have PCIBIOS_MIN_IO
> > > > today and even if we don't need it, there is no obvious downside.
> > > > I would also argue that we can ignore b) for the discussion of
> > > > the HiSilicon LPC driver, we just need to assign some range
> > > > of logical addresses to each domain.
> > > >
> > > > That means solving c) is the important problem here, and it
> > > > shouldn't be so hard.  We can do this either with a single
> > > > special domain as in the v5 patch series, or by generalizing it
> > > > so that any I/O space mapping gets looked up through the device
> > > > pointer of the bus master.
> > >
> > > I am not very on the "generalized" multi-domain solution...
> > > Currently the IO accessors prototypes have an unsigned long addr
> > > as input parameter. If we live in a multi-domain IO system
> > > how can we distinguish inside the accessor which domain addr
> > > belongs to?
> > 
> > The easiest change compared to the v5 code would be to walk
> > a linked list of 'struct extio_ops' structures rather than
> > assuming there is only ever one of them. I think one of the
> > earlier versions actually did this.
> 
> Right but if my understanding is correct if we live in a multi-
> domain I/O space world when you have an input addr in the I/O
> accessors this addr can be duplicated (for example for the standard
> PCI IO domain and for our special LPC domain).
> So effectively even if you walk a linked list there is a problem
> of disambiguation...am I right? 

No, unlike the PCI memory space, the PIO addresses are not
usually distinct, i.e. every PCI bus has its own 64K I/O
addresses starting at zero. We linearize them into the
Linux I/O space using the per-domain io_offset value.

For the ISA/LPC spaces there are only 4k of addresses, they
the bus addresses always overlap, but we can trivially
figure out the bus address from Linux I/O port number
by subtracting the start of the range.

> > Another option the IA64 approach mentioned in another subthread
> > today, looking up the operations based on an index from the
> > upper bits of the port number. If we do this, we probably
> > want to do that for all PIO access and replace the entire
> > virtual address remapping logic with that. I think Bjorn
> > in the past argued in favor of such an approach, while I
> > advocated the current scheme for simplicity based on how
> > every I/O space these days is just memory mapped (which now
> > turned out to be false, both on powerpc and arm64).
> 
> This seems really complex...I am a bit worried that possibly
> we end up in having the maintainers saying that it is not worth
> to re-invent the world just for this special LPC device...

It would clearly be a rather invasive change, but the
end-result isn't necessarily more complex than what we
have today, as we'd kill off the crazy pci_pio_to_address()
and pci_address_to_pio() hacks in address translation.

> To be honest with you I would keep things simple for this
> LPC and introduce more complex reworks later if more devices
> need to be introduced.
> 
> What if we stick on a single domain now where we introduce a
> reserved threshold for the IO space (say INDIRECT_MAX_IO).

I said having a single domain is fine, but I still don't
like the idea of reserving low port numbers for this hack,
it would mean that the numbers change for everyone else.

> We define INDIRECT_MAX_IO as 0 in "include/linux/extio.h" and
> we define INDIRECT_MAX_IO as 0x1000 in "arch/arm64/include/asm/io.h"
> 
> So effectively this threshold can change according to the
> architecture and so far we only define it for ARM64 as we need
> it for ARM64...

I liked the idea of having it done in asm-generic/io.h (in an ifdef)
and lib/*.c under an as someone suggested earlier. There is nothing
ARM64 specific in the implementation.

	Arnd

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 13:42                                       ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 13:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni wrote:
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> > On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni wrote:
> > > > I think there is no need to change a) here, we have PCIBIOS_MIN_IO
> > > > today and even if we don't need it, there is no obvious downside.
> > > > I would also argue that we can ignore b) for the discussion of
> > > > the HiSilicon LPC driver, we just need to assign some range
> > > > of logical addresses to each domain.
> > > >
> > > > That means solving c) is the important problem here, and it
> > > > shouldn't be so hard.  We can do this either with a single
> > > > special domain as in the v5 patch series, or by generalizing it
> > > > so that any I/O space mapping gets looked up through the device
> > > > pointer of the bus master.
> > >
> > > I am not very on the "generalized" multi-domain solution...
> > > Currently the IO accessors prototypes have an unsigned long addr
> > > as input parameter. If we live in a multi-domain IO system
> > > how can we distinguish inside the accessor which domain addr
> > > belongs to?
> > 
> > The easiest change compared to the v5 code would be to walk
> > a linked list of 'struct extio_ops' structures rather than
> > assuming there is only ever one of them. I think one of the
> > earlier versions actually did this.
> 
> Right but if my understanding is correct if we live in a multi-
> domain I/O space world when you have an input addr in the I/O
> accessors this addr can be duplicated (for example for the standard
> PCI IO domain and for our special LPC domain).
> So effectively even if you walk a linked list there is a problem
> of disambiguation...am I right? 

No, unlike the PCI memory space, the PIO addresses are not
usually distinct, i.e. every PCI bus has its own 64K I/O
addresses starting at zero. We linearize them into the
Linux I/O space using the per-domain io_offset value.

For the ISA/LPC spaces there are only 4k of addresses, they
the bus addresses always overlap, but we can trivially
figure out the bus address from Linux I/O port number
by subtracting the start of the range.

> > Another option the IA64 approach mentioned in another subthread
> > today, looking up the operations based on an index from the
> > upper bits of the port number. If we do this, we probably
> > want to do that for all PIO access and replace the entire
> > virtual address remapping logic with that. I think Bjorn
> > in the past argued in favor of such an approach, while I
> > advocated the current scheme for simplicity based on how
> > every I/O space these days is just memory mapped (which now
> > turned out to be false, both on powerpc and arm64).
> 
> This seems really complex...I am a bit worried that possibly
> we end up in having the maintainers saying that it is not worth
> to re-invent the world just for this special LPC device...

It would clearly be a rather invasive change, but the
end-result isn't necessarily more complex than what we
have today, as we'd kill off the crazy pci_pio_to_address()
and pci_address_to_pio() hacks in address translation.

> To be honest with you I would keep things simple for this
> LPC and introduce more complex reworks later if more devices
> need to be introduced.
> 
> What if we stick on a single domain now where we introduce a
> reserved threshold for the IO space (say INDIRECT_MAX_IO).

I said having a single domain is fine, but I still don't
like the idea of reserving low port numbers for this hack,
it would mean that the numbers change for everyone else.

> We define INDIRECT_MAX_IO as 0 in "include/linux/extio.h" and
> we define INDIRECT_MAX_IO as 0x1000 in "arch/arm64/include/asm/io.h"
> 
> So effectively this threshold can change according to the
> architecture and so far we only define it for ARM64 as we need
> it for ARM64...

I liked the idea of having it done in asm-generic/io.h (in an ifdef)
and lib/*.c under an as someone suggested earlier. There is nothing
ARM64 specific in the implementation.

	Arnd

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-18 13:42                                       ` Arnd Bergmann
  (?)
  (?)
@ 2016-11-18 16:18                                         ` Gabriele Paoloni
  -1 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-18 16:18 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: mark.rutland, benh, catalin.marinas, liviu.dudau, Linuxarm,
	lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, linux-serial, linux-pci, devicetree, minyard,
	will.deacon, John Garry, zourongrong, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02,
	Thomas Petazzoni, linux-kernel, Yuanzhichang, olof

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 18 November 2016 13:43
> To: linux-arm-kernel@lists.infradead.org
> Cc: Gabriele Paoloni; mark.rutland@arm.com; benh@kernel.crashing.org;
> catalin.marinas@arm.com; liviu.dudau@arm.com; Linuxarm;
> lorenzo.pieralisi@arm.com; xuwei (O); Jason Gunthorpe; linux-
> serial@vger.kernel.org; linux-pci@vger.kernel.org;
> devicetree@vger.kernel.org; minyard@acm.org; will.deacon@arm.com; John
> Garry; zourongrong@gmail.com; robh+dt@kernel.org; bhelgaas@go og
> le.com; kantyzc@163.com; zhichang.yuan02@gmail.com; Thomas Petazzoni;
> linux-kernel@vger.kernel.org; Yuanzhichang; olof@lixom.net
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni
> wrote:
> > > > > I think there is no need to change a) here, we have
> PCIBIOS_MIN_IO
> > > > > today and even if we don't need it, there is no obvious
> downside.
> > > > > I would also argue that we can ignore b) for the discussion of
> > > > > the HiSilicon LPC driver, we just need to assign some range
> > > > > of logical addresses to each domain.
> > > > >
> > > > > That means solving c) is the important problem here, and it
> > > > > shouldn't be so hard.  We can do this either with a single
> > > > > special domain as in the v5 patch series, or by generalizing it
> > > > > so that any I/O space mapping gets looked up through the device
> > > > > pointer of the bus master.
> > > >
> > > > I am not very on the "generalized" multi-domain solution...
> > > > Currently the IO accessors prototypes have an unsigned long addr
> > > > as input parameter. If we live in a multi-domain IO system
> > > > how can we distinguish inside the accessor which domain addr
> > > > belongs to?
> > >
> > > The easiest change compared to the v5 code would be to walk
> > > a linked list of 'struct extio_ops' structures rather than
> > > assuming there is only ever one of them. I think one of the
> > > earlier versions actually did this.
> >
> > Right but if my understanding is correct if we live in a multi-
> > domain I/O space world when you have an input addr in the I/O
> > accessors this addr can be duplicated (for example for the standard
> > PCI IO domain and for our special LPC domain).
> > So effectively even if you walk a linked list there is a problem
> > of disambiguation...am I right?
> 
> No, unlike the PCI memory space, the PIO addresses are not
> usually distinct, i.e. every PCI bus has its own 64K I/O
> addresses starting at zero. We linearize them into the
> Linux I/O space using the per-domain io_offset value.

I am going to summarize my understanding here below:

It seems to me that what is linearized is the virtual address
space associated to the IO address space. This address space
goes from PCI_IOBASE to (PCI_IOBASE + IO_SPACE_LIMIT).

The I/O accessors perform rd/wr operation on this address
space using a port IO token.

Each token map into a cpu physical address range
Each cpu physical address range maps to a bus address range
if the bus controller specifies a range property.

Devices under a bus controller specify the bus addresses that
they operate on in their reg property.

So each device can use the same bus addresses under two
separate bus controllers as long as the bus controller
use the range properties to map the same bus range to different
cpu address range. 

> 
> For the ISA/LPC spaces there are only 4k of addresses, they
> the bus addresses always overlap, but we can trivially
> figure out the bus address from Linux I/O port number
> by subtracting the start of the range.

Are you saying that our LPC controller should specify a
range property to map bus addresses into a cpu address range? 

> 
> > > Another option the IA64 approach mentioned in another subthread
> > > today, looking up the operations based on an index from the
> > > upper bits of the port number. If we do this, we probably
> > > want to do that for all PIO access and replace the entire
> > > virtual address remapping logic with that. I think Bjorn
> > > in the past argued in favor of such an approach, while I
> > > advocated the current scheme for simplicity based on how
> > > every I/O space these days is just memory mapped (which now
> > > turned out to be false, both on powerpc and arm64).
> >
> > This seems really complex...I am a bit worried that possibly
> > we end up in having the maintainers saying that it is not worth
> > to re-invent the world just for this special LPC device...
> 
> It would clearly be a rather invasive change, but the
> end-result isn't necessarily more complex than what we
> have today, as we'd kill off the crazy pci_pio_to_address()
> and pci_address_to_pio() hacks in address translation.

I have to look better into this...can you provide me a reference
to the Bjorn argument in favor of this approach?

> 
> > To be honest with you I would keep things simple for this
> > LPC and introduce more complex reworks later if more devices
> > need to be introduced.
> >
> > What if we stick on a single domain now where we introduce a
> > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> 
> I said having a single domain is fine, but I still don't
> like the idea of reserving low port numbers for this hack,
> it would mean that the numbers change for everyone else.

I don't get this much...I/O tokens that are passed to the I/O
accessors are not fixed anyway and they vary depending on the order
of adding ranges to io_range_list...so I don't see a big issue
with this...

> 
> > We define INDIRECT_MAX_IO as 0 in "include/linux/extio.h" and
> > we define INDIRECT_MAX_IO as 0x1000 in "arch/arm64/include/asm/io.h"
> >
> > So effectively this threshold can change according to the
> > architecture and so far we only define it for ARM64 as we need
> > it for ARM64...
> 
> I liked the idea of having it done in asm-generic/io.h (in an ifdef)
> and lib/*.c under an as someone suggested earlier. There is nothing
> ARM64 specific in the implementation.

Correct and ideally if the INDIRECT_MAX_IO approach was taken then we
should define INDIRECT_MAX_IO for any architecture that can support the
special LPC devices. We would define it for ARM64 just because LPC
is used in our case under ARM64; the idea was to leave other architecture
to define their own ones as needed...but probably this is wrong and
we should have defined this for all the architectures.

Many thanks

Gab

> 
> 	Arnd

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 16:18                                         ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-18 16:18 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: mark.rutland, benh, catalin.marinas, liviu.dudau, Linuxarm,
	lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, linux-serial, linux-pci, devicetree, minyard,
	will.deacon, John Garry, zourongrong, robh+dt

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 18 November 2016 13:43
> To: linux-arm-kernel@lists.infradead.org
> Cc: Gabriele Paoloni; mark.rutland@arm.com; benh@kernel.crashing.org;
> catalin.marinas@arm.com; liviu.dudau@arm.com; Linuxarm;
> lorenzo.pieralisi@arm.com; xuwei (O); Jason Gunthorpe; linux-
> serial@vger.kernel.org; linux-pci@vger.kernel.org;
> devicetree@vger.kernel.org; minyard@acm.org; will.deacon@arm.com; John
> Garry; zourongrong@gmail.com; robh+dt@kernel.org; bhelgaas@go og
> le.com; kantyzc@163.com; zhichang.yuan02@gmail.com; Thomas Petazzoni;
> linux-kernel@vger.kernel.org; Yuanzhichang; olof@lixom.net
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni
> wrote:
> > > > > I think there is no need to change a) here, we have
> PCIBIOS_MIN_IO
> > > > > today and even if we don't need it, there is no obvious
> downside.
> > > > > I would also argue that we can ignore b) for the discussion of
> > > > > the HiSilicon LPC driver, we just need to assign some range
> > > > > of logical addresses to each domain.
> > > > >
> > > > > That means solving c) is the important problem here, and it
> > > > > shouldn't be so hard.  We can do this either with a single
> > > > > special domain as in the v5 patch series, or by generalizing it
> > > > > so that any I/O space mapping gets looked up through the device
> > > > > pointer of the bus master.
> > > >
> > > > I am not very on the "generalized" multi-domain solution...
> > > > Currently the IO accessors prototypes have an unsigned long addr
> > > > as input parameter. If we live in a multi-domain IO system
> > > > how can we distinguish inside the accessor which domain addr
> > > > belongs to?
> > >
> > > The easiest change compared to the v5 code would be to walk
> > > a linked list of 'struct extio_ops' structures rather than
> > > assuming there is only ever one of them. I think one of the
> > > earlier versions actually did this.
> >
> > Right but if my understanding is correct if we live in a multi-
> > domain I/O space world when you have an input addr in the I/O
> > accessors this addr can be duplicated (for example for the standard
> > PCI IO domain and for our special LPC domain).
> > So effectively even if you walk a linked list there is a problem
> > of disambiguation...am I right?
> 
> No, unlike the PCI memory space, the PIO addresses are not
> usually distinct, i.e. every PCI bus has its own 64K I/O
> addresses starting at zero. We linearize them into the
> Linux I/O space using the per-domain io_offset value.

I am going to summarize my understanding here below:

It seems to me that what is linearized is the virtual address
space associated to the IO address space. This address space
goes from PCI_IOBASE to (PCI_IOBASE + IO_SPACE_LIMIT).

The I/O accessors perform rd/wr operation on this address
space using a port IO token.

Each token map into a cpu physical address range
Each cpu physical address range maps to a bus address range
if the bus controller specifies a range property.

Devices under a bus controller specify the bus addresses that
they operate on in their reg property.

So each device can use the same bus addresses under two
separate bus controllers as long as the bus controller
use the range properties to map the same bus range to different
cpu address range. 

> 
> For the ISA/LPC spaces there are only 4k of addresses, they
> the bus addresses always overlap, but we can trivially
> figure out the bus address from Linux I/O port number
> by subtracting the start of the range.

Are you saying that our LPC controller should specify a
range property to map bus addresses into a cpu address range? 

> 
> > > Another option the IA64 approach mentioned in another subthread
> > > today, looking up the operations based on an index from the
> > > upper bits of the port number. If we do this, we probably
> > > want to do that for all PIO access and replace the entire
> > > virtual address remapping logic with that. I think Bjorn
> > > in the past argued in favor of such an approach, while I
> > > advocated the current scheme for simplicity based on how
> > > every I/O space these days is just memory mapped (which now
> > > turned out to be false, both on powerpc and arm64).
> >
> > This seems really complex...I am a bit worried that possibly
> > we end up in having the maintainers saying that it is not worth
> > to re-invent the world just for this special LPC device...
> 
> It would clearly be a rather invasive change, but the
> end-result isn't necessarily more complex than what we
> have today, as we'd kill off the crazy pci_pio_to_address()
> and pci_address_to_pio() hacks in address translation.

I have to look better into this...can you provide me a reference
to the Bjorn argument in favor of this approach?

> 
> > To be honest with you I would keep things simple for this
> > LPC and introduce more complex reworks later if more devices
> > need to be introduced.
> >
> > What if we stick on a single domain now where we introduce a
> > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> 
> I said having a single domain is fine, but I still don't
> like the idea of reserving low port numbers for this hack,
> it would mean that the numbers change for everyone else.

I don't get this much...I/O tokens that are passed to the I/O
accessors are not fixed anyway and they vary depending on the order
of adding ranges to io_range_list...so I don't see a big issue
with this...

> 
> > We define INDIRECT_MAX_IO as 0 in "include/linux/extio.h" and
> > we define INDIRECT_MAX_IO as 0x1000 in "arch/arm64/include/asm/io.h"
> >
> > So effectively this threshold can change according to the
> > architecture and so far we only define it for ARM64 as we need
> > it for ARM64...
> 
> I liked the idea of having it done in asm-generic/io.h (in an ifdef)
> and lib/*.c under an as someone suggested earlier. There is nothing
> ARM64 specific in the implementation.

Correct and ideally if the INDIRECT_MAX_IO approach was taken then we
should define INDIRECT_MAX_IO for any architecture that can support the
special LPC devices. We would define it for ARM64 just because LPC
is used in our case under ARM64; the idea was to leave other architecture
to define their own ones as needed...but probably this is wrong and
we should have defined this for all the architectures.

Many thanks

Gab

> 
> 	Arnd

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 16:18                                         ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-18 16:18 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: mark.rutland, benh, catalin.marinas, liviu.dudau, Linuxarm,
	lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, linux-serial, linux-pci, devicetree, minyard,
	will.deacon, John Garry, zourongrong, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02,
	Thomas Petazzoni, linux-kernel, Yuanzhichang, olof

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 18 November 2016 13:43
> To: linux-arm-kernel@lists.infradead.org
> Cc: Gabriele Paoloni; mark.rutland@arm.com; benh@kernel.crashing.org;
> catalin.marinas@arm.com; liviu.dudau@arm.com; Linuxarm;
> lorenzo.pieralisi@arm.com; xuwei (O); Jason Gunthorpe; linux-
> serial@vger.kernel.org; linux-pci@vger.kernel.org;
> devicetree@vger.kernel.org; minyard@acm.org; will.deacon@arm.com; John
> Garry; zourongrong@gmail.com; robh+dt@kernel.org; bhelgaas@go og
> le.com; kantyzc@163.com; zhichang.yuan02@gmail.com; Thomas Petazzoni;
> linux-kernel@vger.kernel.org; Yuanzhichang; olof@lixom.net
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni
> wrote:
> > > > > I think there is no need to change a) here, we have
> PCIBIOS_MIN_IO
> > > > > today and even if we don't need it, there is no obvious
> downside.
> > > > > I would also argue that we can ignore b) for the discussion of
> > > > > the HiSilicon LPC driver, we just need to assign some range
> > > > > of logical addresses to each domain.
> > > > >
> > > > > That means solving c) is the important problem here, and it
> > > > > shouldn't be so hard.  We can do this either with a single
> > > > > special domain as in the v5 patch series, or by generalizing it
> > > > > so that any I/O space mapping gets looked up through the device
> > > > > pointer of the bus master.
> > > >
> > > > I am not very on the "generalized" multi-domain solution...
> > > > Currently the IO accessors prototypes have an unsigned long addr
> > > > as input parameter. If we live in a multi-domain IO system
> > > > how can we distinguish inside the accessor which domain addr
> > > > belongs to?
> > >
> > > The easiest change compared to the v5 code would be to walk
> > > a linked list of 'struct extio_ops' structures rather than
> > > assuming there is only ever one of them. I think one of the
> > > earlier versions actually did this.
> >
> > Right but if my understanding is correct if we live in a multi-
> > domain I/O space world when you have an input addr in the I/O
> > accessors this addr can be duplicated (for example for the standard
> > PCI IO domain and for our special LPC domain).
> > So effectively even if you walk a linked list there is a problem
> > of disambiguation...am I right?
> 
> No, unlike the PCI memory space, the PIO addresses are not
> usually distinct, i.e. every PCI bus has its own 64K I/O
> addresses starting at zero. We linearize them into the
> Linux I/O space using the per-domain io_offset value.

I am going to summarize my understanding here below:

It seems to me that what is linearized is the virtual address
space associated to the IO address space. This address space
goes from PCI_IOBASE to (PCI_IOBASE + IO_SPACE_LIMIT).

The I/O accessors perform rd/wr operation on this address
space using a port IO token.

Each token map into a cpu physical address range
Each cpu physical address range maps to a bus address range
if the bus controller specifies a range property.

Devices under a bus controller specify the bus addresses that
they operate on in their reg property.

So each device can use the same bus addresses under two
separate bus controllers as long as the bus controller
use the range properties to map the same bus range to different
cpu address range. 

> 
> For the ISA/LPC spaces there are only 4k of addresses, they
> the bus addresses always overlap, but we can trivially
> figure out the bus address from Linux I/O port number
> by subtracting the start of the range.

Are you saying that our LPC controller should specify a
range property to map bus addresses into a cpu address range? 

> 
> > > Another option the IA64 approach mentioned in another subthread
> > > today, looking up the operations based on an index from the
> > > upper bits of the port number. If we do this, we probably
> > > want to do that for all PIO access and replace the entire
> > > virtual address remapping logic with that. I think Bjorn
> > > in the past argued in favor of such an approach, while I
> > > advocated the current scheme for simplicity based on how
> > > every I/O space these days is just memory mapped (which now
> > > turned out to be false, both on powerpc and arm64).
> >
> > This seems really complex...I am a bit worried that possibly
> > we end up in having the maintainers saying that it is not worth
> > to re-invent the world just for this special LPC device...
> 
> It would clearly be a rather invasive change, but the
> end-result isn't necessarily more complex than what we
> have today, as we'd kill off the crazy pci_pio_to_address()
> and pci_address_to_pio() hacks in address translation.

I have to look better into this...can you provide me a reference
to the Bjorn argument in favor of this approach?

> 
> > To be honest with you I would keep things simple for this
> > LPC and introduce more complex reworks later if more devices
> > need to be introduced.
> >
> > What if we stick on a single domain now where we introduce a
> > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> 
> I said having a single domain is fine, but I still don't
> like the idea of reserving low port numbers for this hack,
> it would mean that the numbers change for everyone else.

I don't get this much...I/O tokens that are passed to the I/O
accessors are not fixed anyway and they vary depending on the order
of adding ranges to io_range_list...so I don't see a big issue
with this...

> 
> > We define INDIRECT_MAX_IO as 0 in "include/linux/extio.h" and
> > we define INDIRECT_MAX_IO as 0x1000 in "arch/arm64/include/asm/io.h"
> >
> > So effectively this threshold can change according to the
> > architecture and so far we only define it for ARM64 as we need
> > it for ARM64...
> 
> I liked the idea of having it done in asm-generic/io.h (in an ifdef)
> and lib/*.c under an as someone suggested earlier. There is nothing
> ARM64 specific in the implementation.

Correct and ideally if the INDIRECT_MAX_IO approach was taken then we
should define INDIRECT_MAX_IO for any architecture that can support the
special LPC devices. We would define it for ARM64 just because LPC
is used in our case under ARM64; the idea was to leave other architecture
to define their own ones as needed...but probably this is wrong and
we should have defined this for all the architectures.

Many thanks

Gab

> 
> 	Arnd

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 16:18                                         ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-18 16:18 UTC (permalink / raw)
  To: linux-arm-kernel

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 18 November 2016 13:43
> To: linux-arm-kernel at lists.infradead.org
> Cc: Gabriele Paoloni; mark.rutland at arm.com; benh at kernel.crashing.org;
> catalin.marinas at arm.com; liviu.dudau at arm.com; Linuxarm;
> lorenzo.pieralisi at arm.com; xuwei (O); Jason Gunthorpe; linux-
> serial at vger.kernel.org; linux-pci at vger.kernel.org;
> devicetree at vger.kernel.org; minyard at acm.org; will.deacon at arm.com; John
> Garry; zourongrong at gmail.com; robh+dt at kernel.org; bhelgaas at go og
> le.com; kantyzc at 163.com; zhichang.yuan02 at gmail.com; Thomas Petazzoni;
> linux-kernel at vger.kernel.org; Yuanzhichang; olof at lixom.net
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni
> wrote:
> > > > > I think there is no need to change a) here, we have
> PCIBIOS_MIN_IO
> > > > > today and even if we don't need it, there is no obvious
> downside.
> > > > > I would also argue that we can ignore b) for the discussion of
> > > > > the HiSilicon LPC driver, we just need to assign some range
> > > > > of logical addresses to each domain.
> > > > >
> > > > > That means solving c) is the important problem here, and it
> > > > > shouldn't be so hard.  We can do this either with a single
> > > > > special domain as in the v5 patch series, or by generalizing it
> > > > > so that any I/O space mapping gets looked up through the device
> > > > > pointer of the bus master.
> > > >
> > > > I am not very on the "generalized" multi-domain solution...
> > > > Currently the IO accessors prototypes have an unsigned long addr
> > > > as input parameter. If we live in a multi-domain IO system
> > > > how can we distinguish inside the accessor which domain addr
> > > > belongs to?
> > >
> > > The easiest change compared to the v5 code would be to walk
> > > a linked list of 'struct extio_ops' structures rather than
> > > assuming there is only ever one of them. I think one of the
> > > earlier versions actually did this.
> >
> > Right but if my understanding is correct if we live in a multi-
> > domain I/O space world when you have an input addr in the I/O
> > accessors this addr can be duplicated (for example for the standard
> > PCI IO domain and for our special LPC domain).
> > So effectively even if you walk a linked list there is a problem
> > of disambiguation...am I right?
> 
> No, unlike the PCI memory space, the PIO addresses are not
> usually distinct, i.e. every PCI bus has its own 64K I/O
> addresses starting at zero. We linearize them into the
> Linux I/O space using the per-domain io_offset value.

I am going to summarize my understanding here below:

It seems to me that what is linearized is the virtual address
space associated to the IO address space. This address space
goes from PCI_IOBASE to (PCI_IOBASE + IO_SPACE_LIMIT).

The I/O accessors perform rd/wr operation on this address
space using a port IO token.

Each token map into a cpu physical address range
Each cpu physical address range maps to a bus address range
if the bus controller specifies a range property.

Devices under a bus controller specify the bus addresses that
they operate on in their reg property.

So each device can use the same bus addresses under two
separate bus controllers as long as the bus controller
use the range properties to map the same bus range to different
cpu address range. 

> 
> For the ISA/LPC spaces there are only 4k of addresses, they
> the bus addresses always overlap, but we can trivially
> figure out the bus address from Linux I/O port number
> by subtracting the start of the range.

Are you saying that our LPC controller should specify a
range property to map bus addresses into a cpu address range? 

> 
> > > Another option the IA64 approach mentioned in another subthread
> > > today, looking up the operations based on an index from the
> > > upper bits of the port number. If we do this, we probably
> > > want to do that for all PIO access and replace the entire
> > > virtual address remapping logic with that. I think Bjorn
> > > in the past argued in favor of such an approach, while I
> > > advocated the current scheme for simplicity based on how
> > > every I/O space these days is just memory mapped (which now
> > > turned out to be false, both on powerpc and arm64).
> >
> > This seems really complex...I am a bit worried that possibly
> > we end up in having the maintainers saying that it is not worth
> > to re-invent the world just for this special LPC device...
> 
> It would clearly be a rather invasive change, but the
> end-result isn't necessarily more complex than what we
> have today, as we'd kill off the crazy pci_pio_to_address()
> and pci_address_to_pio() hacks in address translation.

I have to look better into this...can you provide me a reference
to the Bjorn argument in favor of this approach?

> 
> > To be honest with you I would keep things simple for this
> > LPC and introduce more complex reworks later if more devices
> > need to be introduced.
> >
> > What if we stick on a single domain now where we introduce a
> > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> 
> I said having a single domain is fine, but I still don't
> like the idea of reserving low port numbers for this hack,
> it would mean that the numbers change for everyone else.

I don't get this much...I/O tokens that are passed to the I/O
accessors are not fixed anyway and they vary depending on the order
of adding ranges to io_range_list...so I don't see a big issue
with this...

> 
> > We define INDIRECT_MAX_IO as 0 in "include/linux/extio.h" and
> > we define INDIRECT_MAX_IO as 0x1000 in "arch/arm64/include/asm/io.h"
> >
> > So effectively this threshold can change according to the
> > architecture and so far we only define it for ARM64 as we need
> > it for ARM64...
> 
> I liked the idea of having it done in asm-generic/io.h (in an ifdef)
> and lib/*.c under an as someone suggested earlier. There is nothing
> ARM64 specific in the implementation.

Correct and ideally if the INDIRECT_MAX_IO approach was taken then we
should define INDIRECT_MAX_IO for any architecture that can support the
special LPC devices. We would define it for ARM64 just because LPC
is used in our case under ARM64; the idea was to leave other architecture
to define their own ones as needed...but probably this is wrong and
we should have defined this for all the architectures.

Many thanks

Gab

> 
> 	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-18 16:18                                         ` Gabriele Paoloni
  (?)
  (?)
@ 2016-11-18 16:34                                           ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 16:34 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: linux-arm-kernel, mark.rutland, benh, catalin.marinas,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, linux-serial, linux-pci, devicetree, minyard,
	will.deacon, John Garry, zourongrong, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02,
	Thomas Petazzoni, linux-kernel, Yuanzhichang, olof

On Friday, November 18, 2016 4:18:07 PM CET Gabriele Paoloni wrote:
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> > On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni wrote:
> > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni
> > > > The easiest change compared to the v5 code would be to walk
> > > > a linked list of 'struct extio_ops' structures rather than
> > > > assuming there is only ever one of them. I think one of the
> > > > earlier versions actually did this.
> > >
> > > Right but if my understanding is correct if we live in a multi-
> > > domain I/O space world when you have an input addr in the I/O
> > > accessors this addr can be duplicated (for example for the standard
> > > PCI IO domain and for our special LPC domain).
> > > So effectively even if you walk a linked list there is a problem
> > > of disambiguation...am I right?
> > 
> > No, unlike the PCI memory space, the PIO addresses are not
> > usually distinct, i.e. every PCI bus has its own 64K I/O
> > addresses starting at zero. We linearize them into the
> > Linux I/O space using the per-domain io_offset value.
> 
> I am going to summarize my understanding here below:
> 
> It seems to me that what is linearized is the virtual address
> space associated to the IO address space. This address space
> goes from PCI_IOBASE to (PCI_IOBASE + IO_SPACE_LIMIT).
> 
> The I/O accessors perform rd/wr operation on this address
> space using a port IO token.
> 
> Each token map into a cpu physical address range
> Each cpu physical address range maps to a bus address range
> if the bus controller specifies a range property.
> 
> Devices under a bus controller specify the bus addresses that
> they operate on in their reg property.
> 
> So each device can use the same bus addresses under two
> separate bus controllers as long as the bus controller
> use the range properties to map the same bus range to different
> cpu address range. 

Sounds all correct to me so far, yes.

> > For the ISA/LPC spaces there are only 4k of addresses, they
> > the bus addresses always overlap, but we can trivially
> > figure out the bus address from Linux I/O port number
> > by subtracting the start of the range.
> 
> Are you saying that our LPC controller should specify a
> range property to map bus addresses into a cpu address range? 

No. There is not CPU address associated with it, because it's
not memory mapped.

Instead, we need to associate a bus address with a logical
Linux port number, both in of_address_to_resource and
in inb()/outb().

> > > > Another option the IA64 approach mentioned in another subthread
> > > > today, looking up the operations based on an index from the
> > > > upper bits of the port number. If we do this, we probably
> > > > want to do that for all PIO access and replace the entire
> > > > virtual address remapping logic with that. I think Bjorn
> > > > in the past argued in favor of such an approach, while I
> > > > advocated the current scheme for simplicity based on how
> > > > every I/O space these days is just memory mapped (which now
> > > > turned out to be false, both on powerpc and arm64).
> > >
> > > This seems really complex...I am a bit worried that possibly
> > > we end up in having the maintainers saying that it is not worth
> > > to re-invent the world just for this special LPC device...
> > 
> > It would clearly be a rather invasive change, but the
> > end-result isn't necessarily more complex than what we
> > have today, as we'd kill off the crazy pci_pio_to_address()
> > and pci_address_to_pio() hacks in address translation.
> 
> I have to look better into this...can you provide me a reference
> to the Bjorn argument in favor of this approach?

The thread seems to have been pci: Introduce pci_register_io_range()
helper function, e.g. in https://lkml.org/lkml/2014/7/8/969

> > > To be honest with you I would keep things simple for this
> > > LPC and introduce more complex reworks later if more devices
> > > need to be introduced.
> > >
> > > What if we stick on a single domain now where we introduce a
> > > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> > 
> > I said having a single domain is fine, but I still don't
> > like the idea of reserving low port numbers for this hack,
> > it would mean that the numbers change for everyone else.
> 
> I don't get this much...I/O tokens that are passed to the I/O
> accessors are not fixed anyway and they vary depending on the order
> of adding ranges to io_range_list...so I don't see a big issue
> with this...

On machines with a legacy devices behind the PCI bridge,
there may still be a reason to have the low I/O port range
reserved for the primary bus, e.g. to get a VGA text console
to work.

On powerpc, this is called the "primary" PCI host, i.e. the
only one that is allowed to have an ISA bridge.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 16:34                                           ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 16:34 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	mark.rutland-5wv7dgnIgG8, benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r,
	catalin.marinas-5wv7dgnIgG8, liviu.dudau-5wv7dgnIgG8, Linuxarm,
	lorenzo.pieralisi-5wv7dgnIgG8, xuwei (O),
	Jason Gunthorpe, linux-serial-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, minyard-HInyCGIudOg,
	will.deacon-5wv7dgnIgG8, John Garry, zourongrong

On Friday, November 18, 2016 4:18:07 PM CET Gabriele Paoloni wrote:
> From: Arnd Bergmann [mailto:arnd-r2nGTMty4D4@public.gmane.org]
> > On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni wrote:
> > > From: Arnd Bergmann [mailto:arnd-r2nGTMty4D4@public.gmane.org]
> > > > On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni
> > > > The easiest change compared to the v5 code would be to walk
> > > > a linked list of 'struct extio_ops' structures rather than
> > > > assuming there is only ever one of them. I think one of the
> > > > earlier versions actually did this.
> > >
> > > Right but if my understanding is correct if we live in a multi-
> > > domain I/O space world when you have an input addr in the I/O
> > > accessors this addr can be duplicated (for example for the standard
> > > PCI IO domain and for our special LPC domain).
> > > So effectively even if you walk a linked list there is a problem
> > > of disambiguation...am I right?
> > 
> > No, unlike the PCI memory space, the PIO addresses are not
> > usually distinct, i.e. every PCI bus has its own 64K I/O
> > addresses starting at zero. We linearize them into the
> > Linux I/O space using the per-domain io_offset value.
> 
> I am going to summarize my understanding here below:
> 
> It seems to me that what is linearized is the virtual address
> space associated to the IO address space. This address space
> goes from PCI_IOBASE to (PCI_IOBASE + IO_SPACE_LIMIT).
> 
> The I/O accessors perform rd/wr operation on this address
> space using a port IO token.
> 
> Each token map into a cpu physical address range
> Each cpu physical address range maps to a bus address range
> if the bus controller specifies a range property.
> 
> Devices under a bus controller specify the bus addresses that
> they operate on in their reg property.
> 
> So each device can use the same bus addresses under two
> separate bus controllers as long as the bus controller
> use the range properties to map the same bus range to different
> cpu address range. 

Sounds all correct to me so far, yes.

> > For the ISA/LPC spaces there are only 4k of addresses, they
> > the bus addresses always overlap, but we can trivially
> > figure out the bus address from Linux I/O port number
> > by subtracting the start of the range.
> 
> Are you saying that our LPC controller should specify a
> range property to map bus addresses into a cpu address range? 

No. There is not CPU address associated with it, because it's
not memory mapped.

Instead, we need to associate a bus address with a logical
Linux port number, both in of_address_to_resource and
in inb()/outb().

> > > > Another option the IA64 approach mentioned in another subthread
> > > > today, looking up the operations based on an index from the
> > > > upper bits of the port number. If we do this, we probably
> > > > want to do that for all PIO access and replace the entire
> > > > virtual address remapping logic with that. I think Bjorn
> > > > in the past argued in favor of such an approach, while I
> > > > advocated the current scheme for simplicity based on how
> > > > every I/O space these days is just memory mapped (which now
> > > > turned out to be false, both on powerpc and arm64).
> > >
> > > This seems really complex...I am a bit worried that possibly
> > > we end up in having the maintainers saying that it is not worth
> > > to re-invent the world just for this special LPC device...
> > 
> > It would clearly be a rather invasive change, but the
> > end-result isn't necessarily more complex than what we
> > have today, as we'd kill off the crazy pci_pio_to_address()
> > and pci_address_to_pio() hacks in address translation.
> 
> I have to look better into this...can you provide me a reference
> to the Bjorn argument in favor of this approach?

The thread seems to have been pci: Introduce pci_register_io_range()
helper function, e.g. in https://lkml.org/lkml/2014/7/8/969

> > > To be honest with you I would keep things simple for this
> > > LPC and introduce more complex reworks later if more devices
> > > need to be introduced.
> > >
> > > What if we stick on a single domain now where we introduce a
> > > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> > 
> > I said having a single domain is fine, but I still don't
> > like the idea of reserving low port numbers for this hack,
> > it would mean that the numbers change for everyone else.
> 
> I don't get this much...I/O tokens that are passed to the I/O
> accessors are not fixed anyway and they vary depending on the order
> of adding ranges to io_range_list...so I don't see a big issue
> with this...

On machines with a legacy devices behind the PCI bridge,
there may still be a reason to have the low I/O port range
reserved for the primary bus, e.g. to get a VGA text console
to work.

On powerpc, this is called the "primary" PCI host, i.e. the
only one that is allowed to have an ISA bridge.

	Arnd
--
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] 286+ messages in thread

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 16:34                                           ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 16:34 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: linux-arm-kernel, mark.rutland, benh, catalin.marinas,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, linux-serial, linux-pci, devicetree, minyard,
	will.deacon, John Garry, zourongrong, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02,
	Thomas Petazzoni, linux-kernel, Yuanzhichang, olof

On Friday, November 18, 2016 4:18:07 PM CET Gabriele Paoloni wrote:
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> > On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni wrote:
> > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni
> > > > The easiest change compared to the v5 code would be to walk
> > > > a linked list of 'struct extio_ops' structures rather than
> > > > assuming there is only ever one of them. I think one of the
> > > > earlier versions actually did this.
> > >
> > > Right but if my understanding is correct if we live in a multi-
> > > domain I/O space world when you have an input addr in the I/O
> > > accessors this addr can be duplicated (for example for the standard
> > > PCI IO domain and for our special LPC domain).
> > > So effectively even if you walk a linked list there is a problem
> > > of disambiguation...am I right?
> > 
> > No, unlike the PCI memory space, the PIO addresses are not
> > usually distinct, i.e. every PCI bus has its own 64K I/O
> > addresses starting at zero. We linearize them into the
> > Linux I/O space using the per-domain io_offset value.
> 
> I am going to summarize my understanding here below:
> 
> It seems to me that what is linearized is the virtual address
> space associated to the IO address space. This address space
> goes from PCI_IOBASE to (PCI_IOBASE + IO_SPACE_LIMIT).
> 
> The I/O accessors perform rd/wr operation on this address
> space using a port IO token.
> 
> Each token map into a cpu physical address range
> Each cpu physical address range maps to a bus address range
> if the bus controller specifies a range property.
> 
> Devices under a bus controller specify the bus addresses that
> they operate on in their reg property.
> 
> So each device can use the same bus addresses under two
> separate bus controllers as long as the bus controller
> use the range properties to map the same bus range to different
> cpu address range. 

Sounds all correct to me so far, yes.

> > For the ISA/LPC spaces there are only 4k of addresses, they
> > the bus addresses always overlap, but we can trivially
> > figure out the bus address from Linux I/O port number
> > by subtracting the start of the range.
> 
> Are you saying that our LPC controller should specify a
> range property to map bus addresses into a cpu address range? 

No. There is not CPU address associated with it, because it's
not memory mapped.

Instead, we need to associate a bus address with a logical
Linux port number, both in of_address_to_resource and
in inb()/outb().

> > > > Another option the IA64 approach mentioned in another subthread
> > > > today, looking up the operations based on an index from the
> > > > upper bits of the port number. If we do this, we probably
> > > > want to do that for all PIO access and replace the entire
> > > > virtual address remapping logic with that. I think Bjorn
> > > > in the past argued in favor of such an approach, while I
> > > > advocated the current scheme for simplicity based on how
> > > > every I/O space these days is just memory mapped (which now
> > > > turned out to be false, both on powerpc and arm64).
> > >
> > > This seems really complex...I am a bit worried that possibly
> > > we end up in having the maintainers saying that it is not worth
> > > to re-invent the world just for this special LPC device...
> > 
> > It would clearly be a rather invasive change, but the
> > end-result isn't necessarily more complex than what we
> > have today, as we'd kill off the crazy pci_pio_to_address()
> > and pci_address_to_pio() hacks in address translation.
> 
> I have to look better into this...can you provide me a reference
> to the Bjorn argument in favor of this approach?

The thread seems to have been pci: Introduce pci_register_io_range()
helper function, e.g. in https://lkml.org/lkml/2014/7/8/969

> > > To be honest with you I would keep things simple for this
> > > LPC and introduce more complex reworks later if more devices
> > > need to be introduced.
> > >
> > > What if we stick on a single domain now where we introduce a
> > > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> > 
> > I said having a single domain is fine, but I still don't
> > like the idea of reserving low port numbers for this hack,
> > it would mean that the numbers change for everyone else.
> 
> I don't get this much...I/O tokens that are passed to the I/O
> accessors are not fixed anyway and they vary depending on the order
> of adding ranges to io_range_list...so I don't see a big issue
> with this...

On machines with a legacy devices behind the PCI bridge,
there may still be a reason to have the low I/O port range
reserved for the primary bus, e.g. to get a VGA text console
to work.

On powerpc, this is called the "primary" PCI host, i.e. the
only one that is allowed to have an ISA bridge.

	Arnd

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 16:34                                           ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-18 16:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday, November 18, 2016 4:18:07 PM CET Gabriele Paoloni wrote:
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> > On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni wrote:
> > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > > On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni
> > > > The easiest change compared to the v5 code would be to walk
> > > > a linked list of 'struct extio_ops' structures rather than
> > > > assuming there is only ever one of them. I think one of the
> > > > earlier versions actually did this.
> > >
> > > Right but if my understanding is correct if we live in a multi-
> > > domain I/O space world when you have an input addr in the I/O
> > > accessors this addr can be duplicated (for example for the standard
> > > PCI IO domain and for our special LPC domain).
> > > So effectively even if you walk a linked list there is a problem
> > > of disambiguation...am I right?
> > 
> > No, unlike the PCI memory space, the PIO addresses are not
> > usually distinct, i.e. every PCI bus has its own 64K I/O
> > addresses starting at zero. We linearize them into the
> > Linux I/O space using the per-domain io_offset value.
> 
> I am going to summarize my understanding here below:
> 
> It seems to me that what is linearized is the virtual address
> space associated to the IO address space. This address space
> goes from PCI_IOBASE to (PCI_IOBASE + IO_SPACE_LIMIT).
> 
> The I/O accessors perform rd/wr operation on this address
> space using a port IO token.
> 
> Each token map into a cpu physical address range
> Each cpu physical address range maps to a bus address range
> if the bus controller specifies a range property.
> 
> Devices under a bus controller specify the bus addresses that
> they operate on in their reg property.
> 
> So each device can use the same bus addresses under two
> separate bus controllers as long as the bus controller
> use the range properties to map the same bus range to different
> cpu address range. 

Sounds all correct to me so far, yes.

> > For the ISA/LPC spaces there are only 4k of addresses, they
> > the bus addresses always overlap, but we can trivially
> > figure out the bus address from Linux I/O port number
> > by subtracting the start of the range.
> 
> Are you saying that our LPC controller should specify a
> range property to map bus addresses into a cpu address range? 

No. There is not CPU address associated with it, because it's
not memory mapped.

Instead, we need to associate a bus address with a logical
Linux port number, both in of_address_to_resource and
in inb()/outb().

> > > > Another option the IA64 approach mentioned in another subthread
> > > > today, looking up the operations based on an index from the
> > > > upper bits of the port number. If we do this, we probably
> > > > want to do that for all PIO access and replace the entire
> > > > virtual address remapping logic with that. I think Bjorn
> > > > in the past argued in favor of such an approach, while I
> > > > advocated the current scheme for simplicity based on how
> > > > every I/O space these days is just memory mapped (which now
> > > > turned out to be false, both on powerpc and arm64).
> > >
> > > This seems really complex...I am a bit worried that possibly
> > > we end up in having the maintainers saying that it is not worth
> > > to re-invent the world just for this special LPC device...
> > 
> > It would clearly be a rather invasive change, but the
> > end-result isn't necessarily more complex than what we
> > have today, as we'd kill off the crazy pci_pio_to_address()
> > and pci_address_to_pio() hacks in address translation.
> 
> I have to look better into this...can you provide me a reference
> to the Bjorn argument in favor of this approach?

The thread seems to have been pci: Introduce pci_register_io_range()
helper function, e.g. in https://lkml.org/lkml/2014/7/8/969

> > > To be honest with you I would keep things simple for this
> > > LPC and introduce more complex reworks later if more devices
> > > need to be introduced.
> > >
> > > What if we stick on a single domain now where we introduce a
> > > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> > 
> > I said having a single domain is fine, but I still don't
> > like the idea of reserving low port numbers for this hack,
> > it would mean that the numbers change for everyone else.
> 
> I don't get this much...I/O tokens that are passed to the I/O
> accessors are not fixed anyway and they vary depending on the order
> of adding ranges to io_range_list...so I don't see a big issue
> with this...

On machines with a legacy devices behind the PCI bridge,
there may still be a reason to have the low I/O port range
reserved for the primary bus, e.g. to get a VGA text console
to work.

On powerpc, this is called the "primary" PCI host, i.e. the
only one that is allowed to have an ISA bridge.

	Arnd

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-18 16:34                                           ` Arnd Bergmann
  (?)
  (?)
@ 2016-11-18 17:03                                             ` Gabriele Paoloni
  -1 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-18 17:03 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, mark.rutland, benh, catalin.marinas,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, linux-serial, linux-pci, devicetree, minyard,
	will.deacon, John Garry, zourongrong, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02,
	T homas Petazzoni, linux-kernel, Yuanzhichang, olof

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 18 November 2016 16:35
> To: Gabriele Paoloni
> Cc: linux-arm-kernel@lists.infradead.org; mark.rutland@arm.com;
> benh@kernel.crashing.org; catalin.marinas@arm.com; liviu.dudau@arm.com;
> Linuxarm; lorenzo.pieralisi@arm.com; xuwei (O); Jason Gunthorpe; linux-
> serial@vger.kernel.org; linux-pci@vger.kernel.org;
> devicetree@vger.kernel.org; minyard@acm.org; will.deacon@arm.com; John
> Garry; zourongrong@gmail.com; robh+dt@kernel.org; bhelgaas@go og
> le.com; kantyzc@163.com; zhichang.yuan02@gmail.com; T homas Petazzoni;
> linux-kernel@vger.kernel.org; Yuanzhichang; olof@lixom.net
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 18, 2016 4:18:07 PM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni
> wrote:
> > > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > > On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni
> > > > > The easiest change compared to the v5 code would be to walk
> > > > > a linked list of 'struct extio_ops' structures rather than
> > > > > assuming there is only ever one of them. I think one of the
> > > > > earlier versions actually did this.
> > > >
> > > > Right but if my understanding is correct if we live in a multi-
> > > > domain I/O space world when you have an input addr in the I/O
> > > > accessors this addr can be duplicated (for example for the
> standard
> > > > PCI IO domain and for our special LPC domain).
> > > > So effectively even if you walk a linked list there is a problem
> > > > of disambiguation...am I right?
> > >
> > > No, unlike the PCI memory space, the PIO addresses are not
> > > usually distinct, i.e. every PCI bus has its own 64K I/O
> > > addresses starting at zero. We linearize them into the
> > > Linux I/O space using the per-domain io_offset value.
> >
> > I am going to summarize my understanding here below:
> >
> > It seems to me that what is linearized is the virtual address
> > space associated to the IO address space. This address space
> > goes from PCI_IOBASE to (PCI_IOBASE + IO_SPACE_LIMIT).
> >
> > The I/O accessors perform rd/wr operation on this address
> > space using a port IO token.
> >
> > Each token map into a cpu physical address range
> > Each cpu physical address range maps to a bus address range
> > if the bus controller specifies a range property.
> >
> > Devices under a bus controller specify the bus addresses that
> > they operate on in their reg property.
> >
> > So each device can use the same bus addresses under two
> > separate bus controllers as long as the bus controller
> > use the range properties to map the same bus range to different
> > cpu address range.
> 
> Sounds all correct to me so far, yes.
> 
> > > For the ISA/LPC spaces there are only 4k of addresses, they
> > > the bus addresses always overlap, but we can trivially
> > > figure out the bus address from Linux I/O port number
> > > by subtracting the start of the range.
> >
> > Are you saying that our LPC controller should specify a
> > range property to map bus addresses into a cpu address range?
> 
> No. There is not CPU address associated with it, because it's
> not memory mapped.
> 
> Instead, we need to associate a bus address with a logical
> Linux port number, both in of_address_to_resource and
> in inb()/outb().

I think this is effectively what we are doing so far with patch 2/3.
The problem with this patch is that we are carving out a "forbidden"
IO tokens range that goes from 0 to PCIBIOS_MIN_IO.

I think that the proper solution would be to have the LPC driver to
set the carveout threshold used in pci_register_io_range(), 
pci_pio_to_address(), pci_address_to_pio(), but this would impose
a probe dependency on the LPC itself that should be probed before
the PCI controller (or before any other devices calling these
functions...) 

> 
> > > > > Another option the IA64 approach mentioned in another subthread
> > > > > today, looking up the operations based on an index from the
> > > > > upper bits of the port number. If we do this, we probably
> > > > > want to do that for all PIO access and replace the entire
> > > > > virtual address remapping logic with that. I think Bjorn
> > > > > in the past argued in favor of such an approach, while I
> > > > > advocated the current scheme for simplicity based on how
> > > > > every I/O space these days is just memory mapped (which now
> > > > > turned out to be false, both on powerpc and arm64).
> > > >
> > > > This seems really complex...I am a bit worried that possibly
> > > > we end up in having the maintainers saying that it is not worth
> > > > to re-invent the world just for this special LPC device...
> > >
> > > It would clearly be a rather invasive change, but the
> > > end-result isn't necessarily more complex than what we
> > > have today, as we'd kill off the crazy pci_pio_to_address()
> > > and pci_address_to_pio() hacks in address translation.
> >
> > I have to look better into this...can you provide me a reference
> > to the Bjorn argument in favor of this approach?
> 
> The thread seems to have been pci: Introduce pci_register_io_range()
> helper function, e.g. in https://lkml.org/lkml/2014/7/8/969

Ok many thanks I am going to look at it

> 
> > > > To be honest with you I would keep things simple for this
> > > > LPC and introduce more complex reworks later if more devices
> > > > need to be introduced.
> > > >
> > > > What if we stick on a single domain now where we introduce a
> > > > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> > >
> > > I said having a single domain is fine, but I still don't
> > > like the idea of reserving low port numbers for this hack,
> > > it would mean that the numbers change for everyone else.
> >
> > I don't get this much...I/O tokens that are passed to the I/O
> > accessors are not fixed anyway and they vary depending on the order
> > of adding ranges to io_range_list...so I don't see a big issue
> > with this...
> 
> On machines with a legacy devices behind the PCI bridge,
> there may still be a reason to have the low I/O port range
> reserved for the primary bus, e.g. to get a VGA text console
> to work.
> 
> On powerpc, this is called the "primary" PCI host, i.e. the
> only one that is allowed to have an ISA bridge.

Yes but
1) isn't the PCI controller range property that defines how IO bus address
   map into physical CPU addresses?
2) How can you guarantee that the cpu range associated with this
   IO bus range is the first to be registered in pci_register_io_range()?
   ( i.e. are you saying that they are just relying on the fact that it is the
     only IO range in the system and by chance the IO tokens and corresponding
     bus addresses are the same? )

Thanks

Gab

> 
> 	Arnd

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 17:03                                             ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-18 17:03 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, mark.rutland, benh, catalin.marinas,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, linux-serial, linux-pci, devicetree, minyard,
	will.deacon, John Garry, zourongrong

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 18 November 2016 16:35
> To: Gabriele Paoloni
> Cc: linux-arm-kernel@lists.infradead.org; mark.rutland@arm.com;
> benh@kernel.crashing.org; catalin.marinas@arm.com; liviu.dudau@arm.com;
> Linuxarm; lorenzo.pieralisi@arm.com; xuwei (O); Jason Gunthorpe; linux-
> serial@vger.kernel.org; linux-pci@vger.kernel.org;
> devicetree@vger.kernel.org; minyard@acm.org; will.deacon@arm.com; John
> Garry; zourongrong@gmail.com; robh+dt@kernel.org; bhelgaas@go og
> le.com; kantyzc@163.com; zhichang.yuan02@gmail.com; T homas Petazzoni;
> linux-kernel@vger.kernel.org; Yuanzhichang; olof@lixom.net
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 18, 2016 4:18:07 PM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni
> wrote:
> > > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > > On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni
> > > > > The easiest change compared to the v5 code would be to walk
> > > > > a linked list of 'struct extio_ops' structures rather than
> > > > > assuming there is only ever one of them. I think one of the
> > > > > earlier versions actually did this.
> > > >
> > > > Right but if my understanding is correct if we live in a multi-
> > > > domain I/O space world when you have an input addr in the I/O
> > > > accessors this addr can be duplicated (for example for the
> standard
> > > > PCI IO domain and for our special LPC domain).
> > > > So effectively even if you walk a linked list there is a problem
> > > > of disambiguation...am I right?
> > >
> > > No, unlike the PCI memory space, the PIO addresses are not
> > > usually distinct, i.e. every PCI bus has its own 64K I/O
> > > addresses starting at zero. We linearize them into the
> > > Linux I/O space using the per-domain io_offset value.
> >
> > I am going to summarize my understanding here below:
> >
> > It seems to me that what is linearized is the virtual address
> > space associated to the IO address space. This address space
> > goes from PCI_IOBASE to (PCI_IOBASE + IO_SPACE_LIMIT).
> >
> > The I/O accessors perform rd/wr operation on this address
> > space using a port IO token.
> >
> > Each token map into a cpu physical address range
> > Each cpu physical address range maps to a bus address range
> > if the bus controller specifies a range property.
> >
> > Devices under a bus controller specify the bus addresses that
> > they operate on in their reg property.
> >
> > So each device can use the same bus addresses under two
> > separate bus controllers as long as the bus controller
> > use the range properties to map the same bus range to different
> > cpu address range.
> 
> Sounds all correct to me so far, yes.
> 
> > > For the ISA/LPC spaces there are only 4k of addresses, they
> > > the bus addresses always overlap, but we can trivially
> > > figure out the bus address from Linux I/O port number
> > > by subtracting the start of the range.
> >
> > Are you saying that our LPC controller should specify a
> > range property to map bus addresses into a cpu address range?
> 
> No. There is not CPU address associated with it, because it's
> not memory mapped.
> 
> Instead, we need to associate a bus address with a logical
> Linux port number, both in of_address_to_resource and
> in inb()/outb().

I think this is effectively what we are doing so far with patch 2/3.
The problem with this patch is that we are carving out a "forbidden"
IO tokens range that goes from 0 to PCIBIOS_MIN_IO.

I think that the proper solution would be to have the LPC driver to
set the carveout threshold used in pci_register_io_range(), 
pci_pio_to_address(), pci_address_to_pio(), but this would impose
a probe dependency on the LPC itself that should be probed before
the PCI controller (or before any other devices calling these
functions...) 

> 
> > > > > Another option the IA64 approach mentioned in another subthread
> > > > > today, looking up the operations based on an index from the
> > > > > upper bits of the port number. If we do this, we probably
> > > > > want to do that for all PIO access and replace the entire
> > > > > virtual address remapping logic with that. I think Bjorn
> > > > > in the past argued in favor of such an approach, while I
> > > > > advocated the current scheme for simplicity based on how
> > > > > every I/O space these days is just memory mapped (which now
> > > > > turned out to be false, both on powerpc and arm64).
> > > >
> > > > This seems really complex...I am a bit worried that possibly
> > > > we end up in having the maintainers saying that it is not worth
> > > > to re-invent the world just for this special LPC device...
> > >
> > > It would clearly be a rather invasive change, but the
> > > end-result isn't necessarily more complex than what we
> > > have today, as we'd kill off the crazy pci_pio_to_address()
> > > and pci_address_to_pio() hacks in address translation.
> >
> > I have to look better into this...can you provide me a reference
> > to the Bjorn argument in favor of this approach?
> 
> The thread seems to have been pci: Introduce pci_register_io_range()
> helper function, e.g. in https://lkml.org/lkml/2014/7/8/969

Ok many thanks I am going to look at it

> 
> > > > To be honest with you I would keep things simple for this
> > > > LPC and introduce more complex reworks later if more devices
> > > > need to be introduced.
> > > >
> > > > What if we stick on a single domain now where we introduce a
> > > > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> > >
> > > I said having a single domain is fine, but I still don't
> > > like the idea of reserving low port numbers for this hack,
> > > it would mean that the numbers change for everyone else.
> >
> > I don't get this much...I/O tokens that are passed to the I/O
> > accessors are not fixed anyway and they vary depending on the order
> > of adding ranges to io_range_list...so I don't see a big issue
> > with this...
> 
> On machines with a legacy devices behind the PCI bridge,
> there may still be a reason to have the low I/O port range
> reserved for the primary bus, e.g. to get a VGA text console
> to work.
> 
> On powerpc, this is called the "primary" PCI host, i.e. the
> only one that is allowed to have an ISA bridge.

Yes but
1) isn't the PCI controller range property that defines how IO bus address
   map into physical CPU addresses?
2) How can you guarantee that the cpu range associated with this
   IO bus range is the first to be registered in pci_register_io_range()?
   ( i.e. are you saying that they are just relying on the fact that it is the
     only IO range in the system and by chance the IO tokens and corresponding
     bus addresses are the same? )

Thanks

Gab

> 
> 	Arnd

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 17:03                                             ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-18 17:03 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, mark.rutland, benh, catalin.marinas,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, linux-serial, linux-pci, devicetree, minyard,
	will.deacon, John Garry, zourongrong, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02,
	T homas Petazzoni, linux-kernel, Yuanzhichang, olof

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 18 November 2016 16:35
> To: Gabriele Paoloni
> Cc: linux-arm-kernel@lists.infradead.org; mark.rutland@arm.com;
> benh@kernel.crashing.org; catalin.marinas@arm.com; liviu.dudau@arm.com;
> Linuxarm; lorenzo.pieralisi@arm.com; xuwei (O); Jason Gunthorpe; linux-
> serial@vger.kernel.org; linux-pci@vger.kernel.org;
> devicetree@vger.kernel.org; minyard@acm.org; will.deacon@arm.com; John
> Garry; zourongrong@gmail.com; robh+dt@kernel.org; bhelgaas@go og
> le.com; kantyzc@163.com; zhichang.yuan02@gmail.com; T homas Petazzoni;
> linux-kernel@vger.kernel.org; Yuanzhichang; olof@lixom.net
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 18, 2016 4:18:07 PM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni
> wrote:
> > > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > > On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni
> > > > > The easiest change compared to the v5 code would be to walk
> > > > > a linked list of 'struct extio_ops' structures rather than
> > > > > assuming there is only ever one of them. I think one of the
> > > > > earlier versions actually did this.
> > > >
> > > > Right but if my understanding is correct if we live in a multi-
> > > > domain I/O space world when you have an input addr in the I/O
> > > > accessors this addr can be duplicated (for example for the
> standard
> > > > PCI IO domain and for our special LPC domain).
> > > > So effectively even if you walk a linked list there is a problem
> > > > of disambiguation...am I right?
> > >
> > > No, unlike the PCI memory space, the PIO addresses are not
> > > usually distinct, i.e. every PCI bus has its own 64K I/O
> > > addresses starting at zero. We linearize them into the
> > > Linux I/O space using the per-domain io_offset value.
> >
> > I am going to summarize my understanding here below:
> >
> > It seems to me that what is linearized is the virtual address
> > space associated to the IO address space. This address space
> > goes from PCI_IOBASE to (PCI_IOBASE + IO_SPACE_LIMIT).
> >
> > The I/O accessors perform rd/wr operation on this address
> > space using a port IO token.
> >
> > Each token map into a cpu physical address range
> > Each cpu physical address range maps to a bus address range
> > if the bus controller specifies a range property.
> >
> > Devices under a bus controller specify the bus addresses that
> > they operate on in their reg property.
> >
> > So each device can use the same bus addresses under two
> > separate bus controllers as long as the bus controller
> > use the range properties to map the same bus range to different
> > cpu address range.
> 
> Sounds all correct to me so far, yes.
> 
> > > For the ISA/LPC spaces there are only 4k of addresses, they
> > > the bus addresses always overlap, but we can trivially
> > > figure out the bus address from Linux I/O port number
> > > by subtracting the start of the range.
> >
> > Are you saying that our LPC controller should specify a
> > range property to map bus addresses into a cpu address range?
> 
> No. There is not CPU address associated with it, because it's
> not memory mapped.
> 
> Instead, we need to associate a bus address with a logical
> Linux port number, both in of_address_to_resource and
> in inb()/outb().

I think this is effectively what we are doing so far with patch 2/3.
The problem with this patch is that we are carving out a "forbidden"
IO tokens range that goes from 0 to PCIBIOS_MIN_IO.

I think that the proper solution would be to have the LPC driver to
set the carveout threshold used in pci_register_io_range(), 
pci_pio_to_address(), pci_address_to_pio(), but this would impose
a probe dependency on the LPC itself that should be probed before
the PCI controller (or before any other devices calling these
functions...) 

> 
> > > > > Another option the IA64 approach mentioned in another subthread
> > > > > today, looking up the operations based on an index from the
> > > > > upper bits of the port number. If we do this, we probably
> > > > > want to do that for all PIO access and replace the entire
> > > > > virtual address remapping logic with that. I think Bjorn
> > > > > in the past argued in favor of such an approach, while I
> > > > > advocated the current scheme for simplicity based on how
> > > > > every I/O space these days is just memory mapped (which now
> > > > > turned out to be false, both on powerpc and arm64).
> > > >
> > > > This seems really complex...I am a bit worried that possibly
> > > > we end up in having the maintainers saying that it is not worth
> > > > to re-invent the world just for this special LPC device...
> > >
> > > It would clearly be a rather invasive change, but the
> > > end-result isn't necessarily more complex than what we
> > > have today, as we'd kill off the crazy pci_pio_to_address()
> > > and pci_address_to_pio() hacks in address translation.
> >
> > I have to look better into this...can you provide me a reference
> > to the Bjorn argument in favor of this approach?
> 
> The thread seems to have been pci: Introduce pci_register_io_range()
> helper function, e.g. in https://lkml.org/lkml/2014/7/8/969

Ok many thanks I am going to look at it

> 
> > > > To be honest with you I would keep things simple for this
> > > > LPC and introduce more complex reworks later if more devices
> > > > need to be introduced.
> > > >
> > > > What if we stick on a single domain now where we introduce a
> > > > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> > >
> > > I said having a single domain is fine, but I still don't
> > > like the idea of reserving low port numbers for this hack,
> > > it would mean that the numbers change for everyone else.
> >
> > I don't get this much...I/O tokens that are passed to the I/O
> > accessors are not fixed anyway and they vary depending on the order
> > of adding ranges to io_range_list...so I don't see a big issue
> > with this...
> 
> On machines with a legacy devices behind the PCI bridge,
> there may still be a reason to have the low I/O port range
> reserved for the primary bus, e.g. to get a VGA text console
> to work.
> 
> On powerpc, this is called the "primary" PCI host, i.e. the
> only one that is allowed to have an ISA bridge.

Yes but
1) isn't the PCI controller range property that defines how IO bus address
   map into physical CPU addresses?
2) How can you guarantee that the cpu range associated with this
   IO bus range is the first to be registered in pci_register_io_range()?
   ( i.e. are you saying that they are just relying on the fact that it is the
     only IO range in the system and by chance the IO tokens and corresponding
     bus addresses are the same? )

Thanks

Gab

> 
> 	Arnd

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-18 17:03                                             ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-18 17:03 UTC (permalink / raw)
  To: linux-arm-kernel

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 18 November 2016 16:35
> To: Gabriele Paoloni
> Cc: linux-arm-kernel at lists.infradead.org; mark.rutland at arm.com;
> benh at kernel.crashing.org; catalin.marinas at arm.com; liviu.dudau at arm.com;
> Linuxarm; lorenzo.pieralisi at arm.com; xuwei (O); Jason Gunthorpe; linux-
> serial at vger.kernel.org; linux-pci at vger.kernel.org;
> devicetree at vger.kernel.org; minyard at acm.org; will.deacon at arm.com; John
> Garry; zourongrong at gmail.com; robh+dt at kernel.org; bhelgaas at go og
> le.com; kantyzc at 163.com; zhichang.yuan02 at gmail.com; T homas Petazzoni;
> linux-kernel at vger.kernel.org; Yuanzhichang; olof at lixom.net
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 18, 2016 4:18:07 PM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni
> wrote:
> > > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > > > On Friday, November 18, 2016 12:07:28 PM CET Gabriele Paoloni
> > > > > The easiest change compared to the v5 code would be to walk
> > > > > a linked list of 'struct extio_ops' structures rather than
> > > > > assuming there is only ever one of them. I think one of the
> > > > > earlier versions actually did this.
> > > >
> > > > Right but if my understanding is correct if we live in a multi-
> > > > domain I/O space world when you have an input addr in the I/O
> > > > accessors this addr can be duplicated (for example for the
> standard
> > > > PCI IO domain and for our special LPC domain).
> > > > So effectively even if you walk a linked list there is a problem
> > > > of disambiguation...am I right?
> > >
> > > No, unlike the PCI memory space, the PIO addresses are not
> > > usually distinct, i.e. every PCI bus has its own 64K I/O
> > > addresses starting at zero. We linearize them into the
> > > Linux I/O space using the per-domain io_offset value.
> >
> > I am going to summarize my understanding here below:
> >
> > It seems to me that what is linearized is the virtual address
> > space associated to the IO address space. This address space
> > goes from PCI_IOBASE to (PCI_IOBASE + IO_SPACE_LIMIT).
> >
> > The I/O accessors perform rd/wr operation on this address
> > space using a port IO token.
> >
> > Each token map into a cpu physical address range
> > Each cpu physical address range maps to a bus address range
> > if the bus controller specifies a range property.
> >
> > Devices under a bus controller specify the bus addresses that
> > they operate on in their reg property.
> >
> > So each device can use the same bus addresses under two
> > separate bus controllers as long as the bus controller
> > use the range properties to map the same bus range to different
> > cpu address range.
> 
> Sounds all correct to me so far, yes.
> 
> > > For the ISA/LPC spaces there are only 4k of addresses, they
> > > the bus addresses always overlap, but we can trivially
> > > figure out the bus address from Linux I/O port number
> > > by subtracting the start of the range.
> >
> > Are you saying that our LPC controller should specify a
> > range property to map bus addresses into a cpu address range?
> 
> No. There is not CPU address associated with it, because it's
> not memory mapped.
> 
> Instead, we need to associate a bus address with a logical
> Linux port number, both in of_address_to_resource and
> in inb()/outb().

I think this is effectively what we are doing so far with patch 2/3.
The problem with this patch is that we are carving out a "forbidden"
IO tokens range that goes from 0 to PCIBIOS_MIN_IO.

I think that the proper solution would be to have the LPC driver to
set the carveout threshold used in pci_register_io_range(), 
pci_pio_to_address(), pci_address_to_pio(), but this would impose
a probe dependency on the LPC itself that should be probed before
the PCI controller (or before any other devices calling these
functions...) 

> 
> > > > > Another option the IA64 approach mentioned in another subthread
> > > > > today, looking up the operations based on an index from the
> > > > > upper bits of the port number. If we do this, we probably
> > > > > want to do that for all PIO access and replace the entire
> > > > > virtual address remapping logic with that. I think Bjorn
> > > > > in the past argued in favor of such an approach, while I
> > > > > advocated the current scheme for simplicity based on how
> > > > > every I/O space these days is just memory mapped (which now
> > > > > turned out to be false, both on powerpc and arm64).
> > > >
> > > > This seems really complex...I am a bit worried that possibly
> > > > we end up in having the maintainers saying that it is not worth
> > > > to re-invent the world just for this special LPC device...
> > >
> > > It would clearly be a rather invasive change, but the
> > > end-result isn't necessarily more complex than what we
> > > have today, as we'd kill off the crazy pci_pio_to_address()
> > > and pci_address_to_pio() hacks in address translation.
> >
> > I have to look better into this...can you provide me a reference
> > to the Bjorn argument in favor of this approach?
> 
> The thread seems to have been pci: Introduce pci_register_io_range()
> helper function, e.g. in https://lkml.org/lkml/2014/7/8/969

Ok many thanks I am going to look at it

> 
> > > > To be honest with you I would keep things simple for this
> > > > LPC and introduce more complex reworks later if more devices
> > > > need to be introduced.
> > > >
> > > > What if we stick on a single domain now where we introduce a
> > > > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> > >
> > > I said having a single domain is fine, but I still don't
> > > like the idea of reserving low port numbers for this hack,
> > > it would mean that the numbers change for everyone else.
> >
> > I don't get this much...I/O tokens that are passed to the I/O
> > accessors are not fixed anyway and they vary depending on the order
> > of adding ranges to io_range_list...so I don't see a big issue
> > with this...
> 
> On machines with a legacy devices behind the PCI bridge,
> there may still be a reason to have the low I/O port range
> reserved for the primary bus, e.g. to get a VGA text console
> to work.
> 
> On powerpc, this is called the "primary" PCI host, i.e. the
> only one that is allowed to have an ISA bridge.

Yes but
1) isn't the PCI controller range property that defines how IO bus address
   map into physical CPU addresses?
2) How can you guarantee that the cpu range associated with this
   IO bus range is the first to be registered in pci_register_io_range()?
   ( i.e. are you saying that they are just relying on the fact that it is the
     only IO range in the system and by chance the IO tokens and corresponding
     bus addresses are the same? )

Thanks

Gab

> 
> 	Arnd

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-11-08 23:16       ` Benjamin Herrenschmidt
  (?)
@ 2016-11-21 12:58         ` John Garry
  -1 siblings, 0 replies; 286+ messages in thread
From: John Garry @ 2016-11-21 12:58 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Mark Rutland, zhichang.yuan
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, olof, arnd,
	linux-arm-kernel, lorenzo.pieralisi, linux-kernel, linuxarm,
	devicetree, linux-pci, linux-serial, minyard, liviu.dudau,
	zourongrong, gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	marc.zyngier

On 08/11/2016 23:16, Benjamin Herrenschmidt wrote:
> On Tue, 2016-11-08 at 12:03 +0000, Mark Rutland wrote:
>> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>>>
>>> For arm64, there is no I/O space as other architectural platforms, such as
>>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>>> known port addresses are used to control the corresponding target devices, for
>>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>>> normal MMIO mode in using.
>>
>> This has nothing to do with arm64. Hardware with this kind of indirect
>> bus access could be integrated with a variety of CPU architectures. It
>> simply hasn't been, yet.
>
> On some ppc's we also use similar indirect access methods for IOs. We
> have a generic infrastructure for re-routing some memory or IO regions
> to hooks.
>
> On POWER8, our PCIe doesn't do IO at all, but we have an LPC bus behind
> firmware calls ;-) We use that infrastructure to plumb in the LPC bus.
>
Hi,

I would like to mention another topic on supporting LPC, and this is 
regard to eSPI support.
eSPI is seen as the successor for LPC, and some BMCs already support it.

I had a chat with Arnd on this, and the idea to model LPC as a SPI bus 
adpater (and also eSPI).

However it seems to me that most platforms will/should support eSPI as a 
transparent bridge, same as LPC on x86. So I don't think that this is 
much point in modelling LPC/eSPI as a bus.

So we shall continue with indriect-IO support...

Thanks,
John

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-21 12:58         ` John Garry
  0 siblings, 0 replies; 286+ messages in thread
From: John Garry @ 2016-11-21 12:58 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Mark Rutland, zhichang.yuan
  Cc: catalin.marinas, will.deacon, robh+dt, bhelgaas, olof, arnd,
	linux-arm-kernel, lorenzo.pieralisi, linux-kernel, linuxarm,
	devicetree, linux-pci, linux-serial, minyard, liviu.dudau,
	zourongrong, gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5,
	marc.zyngier

On 08/11/2016 23:16, Benjamin Herrenschmidt wrote:
> On Tue, 2016-11-08 at 12:03 +0000, Mark Rutland wrote:
>> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>>>
>>> For arm64, there is no I/O space as other architectural platforms, such as
>>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>>> known port addresses are used to control the corresponding target devices, for
>>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>>> normal MMIO mode in using.
>>
>> This has nothing to do with arm64. Hardware with this kind of indirect
>> bus access could be integrated with a variety of CPU architectures. It
>> simply hasn't been, yet.
>
> On some ppc's we also use similar indirect access methods for IOs. We
> have a generic infrastructure for re-routing some memory or IO regions
> to hooks.
>
> On POWER8, our PCIe doesn't do IO at all, but we have an LPC bus behind
> firmware calls ;-) We use that infrastructure to plumb in the LPC bus.
>
Hi,

I would like to mention another topic on supporting LPC, and this is 
regard to eSPI support.
eSPI is seen as the successor for LPC, and some BMCs already support it.

I had a chat with Arnd on this, and the idea to model LPC as a SPI bus 
adpater (and also eSPI).

However it seems to me that most platforms will/should support eSPI as a 
transparent bridge, same as LPC on x86. So I don't think that this is 
much point in modelling LPC/eSPI as a bus.

So we shall continue with indriect-IO support...

Thanks,
John

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-11-21 12:58         ` John Garry
  0 siblings, 0 replies; 286+ messages in thread
From: John Garry @ 2016-11-21 12:58 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/11/2016 23:16, Benjamin Herrenschmidt wrote:
> On Tue, 2016-11-08 at 12:03 +0000, Mark Rutland wrote:
>> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>>>
>>> For arm64, there is no I/O space as other architectural platforms, such as
>>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>>> known port addresses are used to control the corresponding target devices, for
>>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>>> normal MMIO mode in using.
>>
>> This has nothing to do with arm64. Hardware with this kind of indirect
>> bus access could be integrated with a variety of CPU architectures. It
>> simply hasn't been, yet.
>
> On some ppc's we also use similar indirect access methods for IOs. We
> have a generic infrastructure for re-routing some memory or IO regions
> to hooks.
>
> On POWER8, our PCIe doesn't do IO at all, but we have an LPC bus behind
> firmware calls ;-) We use that infrastructure to plumb in the LPC bus.
>
Hi,

I would like to mention another topic on supporting LPC, and this is 
regard to eSPI support.
eSPI is seen as the successor for LPC, and some BMCs already support it.

I had a chat with Arnd on this, and the idea to model LPC as a SPI bus 
adpater (and also eSPI).

However it seems to me that most platforms will/should support eSPI as a 
transparent bridge, same as LPC on x86. So I don't think that this is 
much point in modelling LPC/eSPI as a bus.

So we shall continue with indriect-IO support...

Thanks,
John

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-18 17:03                                             ` Gabriele Paoloni
  (?)
  (?)
@ 2016-11-23 14:16                                               ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-23 14:16 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: linux-arm-kernel, mark.rutland, benh, catalin.marinas,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, linux-serial, linux-pci, devicetree, minyard,
	will.deacon, John Garry, zourongrong, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02,
	T homas Petazzoni, linux-kernel, Yuanzhichang, olof

On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
> > On Friday, November 18, 2016 4:18:07 PM CET Gabriele Paoloni wrote:
> > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni
> > wrote:
> > > > For the ISA/LPC spaces there are only 4k of addresses, they
> > > > the bus addresses always overlap, but we can trivially
> > > > figure out the bus address from Linux I/O port number
> > > > by subtracting the start of the range.
> > >
> > > Are you saying that our LPC controller should specify a
> > > range property to map bus addresses into a cpu address range?
> > 
> > No. There is not CPU address associated with it, because it's
> > not memory mapped.
> > 
> > Instead, we need to associate a bus address with a logical
> > Linux port number, both in of_address_to_resource and
> > in inb()/outb().
> 
> I think this is effectively what we are doing so far with patch 2/3.
> The problem with this patch is that we are carving out a "forbidden"
> IO tokens range that goes from 0 to PCIBIOS_MIN_IO.
> 
> I think that the proper solution would be to have the LPC driver to
> set the carveout threshold used in pci_register_io_range(), 
> pci_pio_to_address(), pci_address_to_pio(), but this would impose
> a probe dependency on the LPC itself that should be probed before
> the PCI controller (or before any other devices calling these
> functions...)

Why do you think the order matters? My point was that we should
be able to register any region of logical port numbers for any
bus here.


> > > > > To be honest with you I would keep things simple for this
> > > > > LPC and introduce more complex reworks later if more devices
> > > > > need to be introduced.
> > > > >
> > > > > What if we stick on a single domain now where we introduce a
> > > > > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> > > >
> > > > I said having a single domain is fine, but I still don't
> > > > like the idea of reserving low port numbers for this hack,
> > > > it would mean that the numbers change for everyone else.
> > >
> > > I don't get this much...I/O tokens that are passed to the I/O
> > > accessors are not fixed anyway and they vary depending on the order
> > > of adding ranges to io_range_list...so I don't see a big issue
> > > with this...
> > 
> > On machines with a legacy devices behind the PCI bridge,
> > there may still be a reason to have the low I/O port range
> > reserved for the primary bus, e.g. to get a VGA text console
> > to work.
> > 
> > On powerpc, this is called the "primary" PCI host, i.e. the
> > only one that is allowed to have an ISA bridge.
> 
> Yes but
> 1) isn't the PCI controller range property that defines how IO bus address
>    map into physical CPU addresses?

Correct, but the DT knows nothing about logical port numbers in Linux.

> 2) How can you guarantee that the cpu range associated with this
>    IO bus range is the first to be registered in pci_register_io_range()?
>    ( i.e. are you saying that they are just relying on the fact that it is the
>      only IO range in the system and by chance the IO tokens and corresponding
>      bus addresses are the same? )

To clarify: the special properties of having the first 0x1000 logical
port numbers go to a particular physical bus are very obscure. I think
it's more important to not change the behavior for existing systems
that might rely on it than for new systems that have no such legacy.

The ipmi and uart drivers in particular will get the port numbers filled
in their platform device from the DT bus scanning, so they don't care
at all about having the same numeric value for port numbers on the bus
and logical numbers, but other drivers might rely on particular ports
to be mapped on a specific PCI host, especially when those drivers
are  used only on systems that don't have more than one PCI domain.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-23 14:16                                               ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-23 14:16 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: linux-arm-kernel, mark.rutland, benh, catalin.marinas,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, linux-serial, linux-pci, devicetree, minyard,
	will.deacon, John Garry, zourongrong

On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
> > On Friday, November 18, 2016 4:18:07 PM CET Gabriele Paoloni wrote:
> > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni
> > wrote:
> > > > For the ISA/LPC spaces there are only 4k of addresses, they
> > > > the bus addresses always overlap, but we can trivially
> > > > figure out the bus address from Linux I/O port number
> > > > by subtracting the start of the range.
> > >
> > > Are you saying that our LPC controller should specify a
> > > range property to map bus addresses into a cpu address range?
> > 
> > No. There is not CPU address associated with it, because it's
> > not memory mapped.
> > 
> > Instead, we need to associate a bus address with a logical
> > Linux port number, both in of_address_to_resource and
> > in inb()/outb().
> 
> I think this is effectively what we are doing so far with patch 2/3.
> The problem with this patch is that we are carving out a "forbidden"
> IO tokens range that goes from 0 to PCIBIOS_MIN_IO.
> 
> I think that the proper solution would be to have the LPC driver to
> set the carveout threshold used in pci_register_io_range(), 
> pci_pio_to_address(), pci_address_to_pio(), but this would impose
> a probe dependency on the LPC itself that should be probed before
> the PCI controller (or before any other devices calling these
> functions...)

Why do you think the order matters? My point was that we should
be able to register any region of logical port numbers for any
bus here.


> > > > > To be honest with you I would keep things simple for this
> > > > > LPC and introduce more complex reworks later if more devices
> > > > > need to be introduced.
> > > > >
> > > > > What if we stick on a single domain now where we introduce a
> > > > > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> > > >
> > > > I said having a single domain is fine, but I still don't
> > > > like the idea of reserving low port numbers for this hack,
> > > > it would mean that the numbers change for everyone else.
> > >
> > > I don't get this much...I/O tokens that are passed to the I/O
> > > accessors are not fixed anyway and they vary depending on the order
> > > of adding ranges to io_range_list...so I don't see a big issue
> > > with this...
> > 
> > On machines with a legacy devices behind the PCI bridge,
> > there may still be a reason to have the low I/O port range
> > reserved for the primary bus, e.g. to get a VGA text console
> > to work.
> > 
> > On powerpc, this is called the "primary" PCI host, i.e. the
> > only one that is allowed to have an ISA bridge.
> 
> Yes but
> 1) isn't the PCI controller range property that defines how IO bus address
>    map into physical CPU addresses?

Correct, but the DT knows nothing about logical port numbers in Linux.

> 2) How can you guarantee that the cpu range associated with this
>    IO bus range is the first to be registered in pci_register_io_range()?
>    ( i.e. are you saying that they are just relying on the fact that it is the
>      only IO range in the system and by chance the IO tokens and corresponding
>      bus addresses are the same? )

To clarify: the special properties of having the first 0x1000 logical
port numbers go to a particular physical bus are very obscure. I think
it's more important to not change the behavior for existing systems
that might rely on it than for new systems that have no such legacy.

The ipmi and uart drivers in particular will get the port numbers filled
in their platform device from the DT bus scanning, so they don't care
at all about having the same numeric value for port numbers on the bus
and logical numbers, but other drivers might rely on particular ports
to be mapped on a specific PCI host, especially when those drivers
are  used only on systems that don't have more than one PCI domain.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-23 14:16                                               ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-23 14:16 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: mark.rutland, catalin.marinas, linux-pci, liviu.dudau, Linuxarm,
	lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, T homas Petazzoni, linux-serial, benh,
	devicetree, minyard, will.deacon, John Garry, olof, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02,
	linux-arm-kernel, linux-kernel, Yuanzhichang, zourongrong

On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
> > On Friday, November 18, 2016 4:18:07 PM CET Gabriele Paoloni wrote:
> > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni
> > wrote:
> > > > For the ISA/LPC spaces there are only 4k of addresses, they
> > > > the bus addresses always overlap, but we can trivially
> > > > figure out the bus address from Linux I/O port number
> > > > by subtracting the start of the range.
> > >
> > > Are you saying that our LPC controller should specify a
> > > range property to map bus addresses into a cpu address range?
> > 
> > No. There is not CPU address associated with it, because it's
> > not memory mapped.
> > 
> > Instead, we need to associate a bus address with a logical
> > Linux port number, both in of_address_to_resource and
> > in inb()/outb().
> 
> I think this is effectively what we are doing so far with patch 2/3.
> The problem with this patch is that we are carving out a "forbidden"
> IO tokens range that goes from 0 to PCIBIOS_MIN_IO.
> 
> I think that the proper solution would be to have the LPC driver to
> set the carveout threshold used in pci_register_io_range(), 
> pci_pio_to_address(), pci_address_to_pio(), but this would impose
> a probe dependency on the LPC itself that should be probed before
> the PCI controller (or before any other devices calling these
> functions...)

Why do you think the order matters? My point was that we should
be able to register any region of logical port numbers for any
bus here.


> > > > > To be honest with you I would keep things simple for this
> > > > > LPC and introduce more complex reworks later if more devices
> > > > > need to be introduced.
> > > > >
> > > > > What if we stick on a single domain now where we introduce a
> > > > > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> > > >
> > > > I said having a single domain is fine, but I still don't
> > > > like the idea of reserving low port numbers for this hack,
> > > > it would mean that the numbers change for everyone else.
> > >
> > > I don't get this much...I/O tokens that are passed to the I/O
> > > accessors are not fixed anyway and they vary depending on the order
> > > of adding ranges to io_range_list...so I don't see a big issue
> > > with this...
> > 
> > On machines with a legacy devices behind the PCI bridge,
> > there may still be a reason to have the low I/O port range
> > reserved for the primary bus, e.g. to get a VGA text console
> > to work.
> > 
> > On powerpc, this is called the "primary" PCI host, i.e. the
> > only one that is allowed to have an ISA bridge.
> 
> Yes but
> 1) isn't the PCI controller range property that defines how IO bus address
>    map into physical CPU addresses?

Correct, but the DT knows nothing about logical port numbers in Linux.

> 2) How can you guarantee that the cpu range associated with this
>    IO bus range is the first to be registered in pci_register_io_range()?
>    ( i.e. are you saying that they are just relying on the fact that it is the
>      only IO range in the system and by chance the IO tokens and corresponding
>      bus addresses are the same? )

To clarify: the special properties of having the first 0x1000 logical
port numbers go to a particular physical bus are very obscure. I think
it's more important to not change the behavior for existing systems
that might rely on it than for new systems that have no such legacy.

The ipmi and uart drivers in particular will get the port numbers filled
in their platform device from the DT bus scanning, so they don't care
at all about having the same numeric value for port numbers on the bus
and logical numbers, but other drivers might rely on particular ports
to be mapped on a specific PCI host, especially when those drivers
are  used only on systems that don't have more than one PCI domain.

	Arnd

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-23 14:16                                               ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-23 14:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
> > On Friday, November 18, 2016 4:18:07 PM CET Gabriele Paoloni wrote:
> > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > > On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni
> > wrote:
> > > > For the ISA/LPC spaces there are only 4k of addresses, they
> > > > the bus addresses always overlap, but we can trivially
> > > > figure out the bus address from Linux I/O port number
> > > > by subtracting the start of the range.
> > >
> > > Are you saying that our LPC controller should specify a
> > > range property to map bus addresses into a cpu address range?
> > 
> > No. There is not CPU address associated with it, because it's
> > not memory mapped.
> > 
> > Instead, we need to associate a bus address with a logical
> > Linux port number, both in of_address_to_resource and
> > in inb()/outb().
> 
> I think this is effectively what we are doing so far with patch 2/3.
> The problem with this patch is that we are carving out a "forbidden"
> IO tokens range that goes from 0 to PCIBIOS_MIN_IO.
> 
> I think that the proper solution would be to have the LPC driver to
> set the carveout threshold used in pci_register_io_range(), 
> pci_pio_to_address(), pci_address_to_pio(), but this would impose
> a probe dependency on the LPC itself that should be probed before
> the PCI controller (or before any other devices calling these
> functions...)

Why do you think the order matters? My point was that we should
be able to register any region of logical port numbers for any
bus here.


> > > > > To be honest with you I would keep things simple for this
> > > > > LPC and introduce more complex reworks later if more devices
> > > > > need to be introduced.
> > > > >
> > > > > What if we stick on a single domain now where we introduce a
> > > > > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> > > >
> > > > I said having a single domain is fine, but I still don't
> > > > like the idea of reserving low port numbers for this hack,
> > > > it would mean that the numbers change for everyone else.
> > >
> > > I don't get this much...I/O tokens that are passed to the I/O
> > > accessors are not fixed anyway and they vary depending on the order
> > > of adding ranges to io_range_list...so I don't see a big issue
> > > with this...
> > 
> > On machines with a legacy devices behind the PCI bridge,
> > there may still be a reason to have the low I/O port range
> > reserved for the primary bus, e.g. to get a VGA text console
> > to work.
> > 
> > On powerpc, this is called the "primary" PCI host, i.e. the
> > only one that is allowed to have an ISA bridge.
> 
> Yes but
> 1) isn't the PCI controller range property that defines how IO bus address
>    map into physical CPU addresses?

Correct, but the DT knows nothing about logical port numbers in Linux.

> 2) How can you guarantee that the cpu range associated with this
>    IO bus range is the first to be registered in pci_register_io_range()?
>    ( i.e. are you saying that they are just relying on the fact that it is the
>      only IO range in the system and by chance the IO tokens and corresponding
>      bus addresses are the same? )

To clarify: the special properties of having the first 0x1000 logical
port numbers go to a particular physical bus are very obscure. I think
it's more important to not change the behavior for existing systems
that might rely on it than for new systems that have no such legacy.

The ipmi and uart drivers in particular will get the port numbers filled
in their platform device from the DT bus scanning, so they don't care
at all about having the same numeric value for port numbers on the bus
and logical numbers, but other drivers might rely on particular ports
to be mapped on a specific PCI host, especially when those drivers
are  used only on systems that don't have more than one PCI domain.

	Arnd

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-23 14:16                                               ` Arnd Bergmann
  (?)
  (?)
@ 2016-11-23 15:22                                                 ` Gabriele Paoloni
  -1 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-23 15:22 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, mark.rutland, benh, catalin.marinas,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, linux-serial, linux-pci, devicetree, minyard,
	will.deacon, John Garry, zourongrong, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02,
	T homas Petazzoni, linux-kernel, Yuanzhichang, olof

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 23 November 2016 14:16
> To: Gabriele Paoloni
> Cc: linux-arm-kernel@lists.infradead.org; mark.rutland@arm.com;
> benh@kernel.crashing.org; catalin.marinas@arm.com; liviu.dudau@arm.com;
> Linuxarm; lorenzo.pieralisi@arm.com; xuwei (O); Jason Gunthorpe; linux-
> serial@vger.kernel.org; linux-pci@vger.kernel.org;
> devicetree@vger.kernel.org; minyard@acm.org; will.deacon@arm.com; John
> Garry; zourongrong@gmail.com; robh+dt@kernel.org; bhelgaas@go og
> le.com; kantyzc@163.com; zhichang.yuan02@gmail.com; T homas Petazzoni;
> linux-kernel@vger.kernel.org; Yuanzhichang; olof@lixom.net
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
> > > On Friday, November 18, 2016 4:18:07 PM CET Gabriele Paoloni wrote:
> > > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > > On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni
> > > wrote:
> > > > > For the ISA/LPC spaces there are only 4k of addresses, they
> > > > > the bus addresses always overlap, but we can trivially
> > > > > figure out the bus address from Linux I/O port number
> > > > > by subtracting the start of the range.
> > > >
> > > > Are you saying that our LPC controller should specify a
> > > > range property to map bus addresses into a cpu address range?
> > >
> > > No. There is not CPU address associated with it, because it's
> > > not memory mapped.
> > >
> > > Instead, we need to associate a bus address with a logical
> > > Linux port number, both in of_address_to_resource and
> > > in inb()/outb().
> >
> > I think this is effectively what we are doing so far with patch 2/3.
> > The problem with this patch is that we are carving out a "forbidden"
> > IO tokens range that goes from 0 to PCIBIOS_MIN_IO.
> >
> > I think that the proper solution would be to have the LPC driver to
> > set the carveout threshold used in pci_register_io_range(),
> > pci_pio_to_address(), pci_address_to_pio(), but this would impose
> > a probe dependency on the LPC itself that should be probed before
> > the PCI controller (or before any other devices calling these
> > functions...)
> 
> Why do you think the order matters? My point was that we should
> be able to register any region of logical port numbers for any
> bus here.

Maybe I have not followed well so let's roll back to your previous
comment...

"we need to associate a bus address with a logical Linux port number,
both in of_address_to_resource and in inb()/outb()"

Actually of_address_to_resource() returns the port number to used
in inb/outb(); inb() and outb() add the port number to PCI_IOBASE
to rd/wr to the right virtual address.

Our LPC cannot operate on the virtual address and it operates on
a bus address range that for LPC is also equal to the cpu address
range and goes from 0 to 0x1000.

Now as I understand it is risky and not appropriate to reserve
the logical port numbers from 0 to 0x1000 or to whatever other
upper bound because existing systems may rely on these port numbers
retrieved by __of_address_to_resource().

In this scenario I think the best thing to do would be
in the probe function of the LPC driver:
1) call pci_register_io_range() passing [0, 0x1000] (that is the
   range for LPC)
2) retrieve the logical port numbers associated to the LPC range
   by calling pci_address_to_pio() for 0 and 0x1000 and assign
   them to extio_ops_node->start and extio_ops_node->end
3) implement the LPC accessors to operate on the logical ports
   associated to the LPC range (in practice in the accessors
   implementation we will call pci_pio_to_address to retrieve
   the cpu address to operate on)

What do you think?

Thanks

Gab


> 
>
> > > > > > To be honest with you I would keep things simple for this
> > > > > > LPC and introduce more complex reworks later if more devices
> > > > > > need to be introduced.
> > > > > >
> > > > > > What if we stick on a single domain now where we introduce a
> > > > > > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> > > > >
> > > > > I said having a single domain is fine, but I still don't
> > > > > like the idea of reserving low port numbers for this hack,
> > > > > it would mean that the numbers change for everyone else.
> > > >
> > > > I don't get this much...I/O tokens that are passed to the I/O
> > > > accessors are not fixed anyway and they vary depending on the
> order
> > > > of adding ranges to io_range_list...so I don't see a big issue
> > > > with this...
> > >
> > > On machines with a legacy devices behind the PCI bridge,
> > > there may still be a reason to have the low I/O port range
> > > reserved for the primary bus, e.g. to get a VGA text console
> > > to work.
> > >
> > > On powerpc, this is called the "primary" PCI host, i.e. the
> > > only one that is allowed to have an ISA bridge.
> >
> > Yes but
> > 1) isn't the PCI controller range property that defines how IO bus
> address
> >    map into physical CPU addresses?
> 
> Correct, but the DT knows nothing about logical port numbers in Linux.
> 
> > 2) How can you guarantee that the cpu range associated with this
> >    IO bus range is the first to be registered in
> pci_register_io_range()?
> >    ( i.e. are you saying that they are just relying on the fact that
> it is the
> >      only IO range in the system and by chance the IO tokens and
> corresponding
> >      bus addresses are the same? )
> 
> To clarify: the special properties of having the first 0x1000 logical
> port numbers go to a particular physical bus are very obscure. I think
> it's more important to not change the behavior for existing systems
> that might rely on it than for new systems that have no such legacy.
> 
> The ipmi and uart drivers in particular will get the port numbers
> filled
> in their platform device from the DT bus scanning, so they don't care
> at all about having the same numeric value for port numbers on the bus
> and logical numbers, but other drivers might rely on particular ports
> to be mapped on a specific PCI host, especially when those drivers
> are  used only on systems that don't have more than one PCI domain.
> 
> 	Arnd

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-23 15:22                                                 ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-23 15:22 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: mark.rutland, catalin.marinas, linux-pci, liviu.dudau, Linuxarm,
	lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, T homas Petazzoni, linux-serial, benh,
	devicetree, minyard, will.deacon, John Garry, olof, robh+dt,
	bhelgaas@go og le.com, kantyzc@163.com

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 23 November 2016 14:16
> To: Gabriele Paoloni
> Cc: linux-arm-kernel@lists.infradead.org; mark.rutland@arm.com;
> benh@kernel.crashing.org; catalin.marinas@arm.com; liviu.dudau@arm.com;
> Linuxarm; lorenzo.pieralisi@arm.com; xuwei (O); Jason Gunthorpe; linux-
> serial@vger.kernel.org; linux-pci@vger.kernel.org;
> devicetree@vger.kernel.org; minyard@acm.org; will.deacon@arm.com; John
> Garry; zourongrong@gmail.com; robh+dt@kernel.org; bhelgaas@go og
> le.com; kantyzc@163.com; zhichang.yuan02@gmail.com; T homas Petazzoni;
> linux-kernel@vger.kernel.org; Yuanzhichang; olof@lixom.net
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
> > > On Friday, November 18, 2016 4:18:07 PM CET Gabriele Paoloni wrote:
> > > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > > On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni
> > > wrote:
> > > > > For the ISA/LPC spaces there are only 4k of addresses, they
> > > > > the bus addresses always overlap, but we can trivially
> > > > > figure out the bus address from Linux I/O port number
> > > > > by subtracting the start of the range.
> > > >
> > > > Are you saying that our LPC controller should specify a
> > > > range property to map bus addresses into a cpu address range?
> > >
> > > No. There is not CPU address associated with it, because it's
> > > not memory mapped.
> > >
> > > Instead, we need to associate a bus address with a logical
> > > Linux port number, both in of_address_to_resource and
> > > in inb()/outb().
> >
> > I think this is effectively what we are doing so far with patch 2/3.
> > The problem with this patch is that we are carving out a "forbidden"
> > IO tokens range that goes from 0 to PCIBIOS_MIN_IO.
> >
> > I think that the proper solution would be to have the LPC driver to
> > set the carveout threshold used in pci_register_io_range(),
> > pci_pio_to_address(), pci_address_to_pio(), but this would impose
> > a probe dependency on the LPC itself that should be probed before
> > the PCI controller (or before any other devices calling these
> > functions...)
> 
> Why do you think the order matters? My point was that we should
> be able to register any region of logical port numbers for any
> bus here.

Maybe I have not followed well so let's roll back to your previous
comment...

"we need to associate a bus address with a logical Linux port number,
both in of_address_to_resource and in inb()/outb()"

Actually of_address_to_resource() returns the port number to used
in inb/outb(); inb() and outb() add the port number to PCI_IOBASE
to rd/wr to the right virtual address.

Our LPC cannot operate on the virtual address and it operates on
a bus address range that for LPC is also equal to the cpu address
range and goes from 0 to 0x1000.

Now as I understand it is risky and not appropriate to reserve
the logical port numbers from 0 to 0x1000 or to whatever other
upper bound because existing systems may rely on these port numbers
retrieved by __of_address_to_resource().

In this scenario I think the best thing to do would be
in the probe function of the LPC driver:
1) call pci_register_io_range() passing [0, 0x1000] (that is the
   range for LPC)
2) retrieve the logical port numbers associated to the LPC range
   by calling pci_address_to_pio() for 0 and 0x1000 and assign
   them to extio_ops_node->start and extio_ops_node->end
3) implement the LPC accessors to operate on the logical ports
   associated to the LPC range (in practice in the accessors
   implementation we will call pci_pio_to_address to retrieve
   the cpu address to operate on)

What do you think?

Thanks

Gab


> 
>
> > > > > > To be honest with you I would keep things simple for this
> > > > > > LPC and introduce more complex reworks later if more devices
> > > > > > need to be introduced.
> > > > > >
> > > > > > What if we stick on a single domain now where we introduce a
> > > > > > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> > > > >
> > > > > I said having a single domain is fine, but I still don't
> > > > > like the idea of reserving low port numbers for this hack,
> > > > > it would mean that the numbers change for everyone else.
> > > >
> > > > I don't get this much...I/O tokens that are passed to the I/O
> > > > accessors are not fixed anyway and they vary depending on the
> order
> > > > of adding ranges to io_range_list...so I don't see a big issue
> > > > with this...
> > >
> > > On machines with a legacy devices behind the PCI bridge,
> > > there may still be a reason to have the low I/O port range
> > > reserved for the primary bus, e.g. to get a VGA text console
> > > to work.
> > >
> > > On powerpc, this is called the "primary" PCI host, i.e. the
> > > only one that is allowed to have an ISA bridge.
> >
> > Yes but
> > 1) isn't the PCI controller range property that defines how IO bus
> address
> >    map into physical CPU addresses?
> 
> Correct, but the DT knows nothing about logical port numbers in Linux.
> 
> > 2) How can you guarantee that the cpu range associated with this
> >    IO bus range is the first to be registered in
> pci_register_io_range()?
> >    ( i.e. are you saying that they are just relying on the fact that
> it is the
> >      only IO range in the system and by chance the IO tokens and
> corresponding
> >      bus addresses are the same? )
> 
> To clarify: the special properties of having the first 0x1000 logical
> port numbers go to a particular physical bus are very obscure. I think
> it's more important to not change the behavior for existing systems
> that might rely on it than for new systems that have no such legacy.
> 
> The ipmi and uart drivers in particular will get the port numbers
> filled
> in their platform device from the DT bus scanning, so they don't care
> at all about having the same numeric value for port numbers on the bus
> and logical numbers, but other drivers might rely on particular ports
> to be mapped on a specific PCI host, especially when those drivers
> are  used only on systems that don't have more than one PCI domain.
> 
> 	Arnd

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-23 15:22                                                 ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-23 15:22 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, mark.rutland, benh, catalin.marinas,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, linux-serial, linux-pci, devicetree, minyard,
	will.deacon, John Garry, zourongrong, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02,
	T homas Petazzoni, linux-kernel, Yuanzhichang, olof

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 23 November 2016 14:16
> To: Gabriele Paoloni
> Cc: linux-arm-kernel@lists.infradead.org; mark.rutland@arm.com;
> benh@kernel.crashing.org; catalin.marinas@arm.com; liviu.dudau@arm.com;
> Linuxarm; lorenzo.pieralisi@arm.com; xuwei (O); Jason Gunthorpe; linux-
> serial@vger.kernel.org; linux-pci@vger.kernel.org;
> devicetree@vger.kernel.org; minyard@acm.org; will.deacon@arm.com; John
> Garry; zourongrong@gmail.com; robh+dt@kernel.org; bhelgaas@go og
> le.com; kantyzc@163.com; zhichang.yuan02@gmail.com; T homas Petazzoni;
> linux-kernel@vger.kernel.org; Yuanzhichang; olof@lixom.net
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
> > > On Friday, November 18, 2016 4:18:07 PM CET Gabriele Paoloni wrote:
> > > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > > On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni
> > > wrote:
> > > > > For the ISA/LPC spaces there are only 4k of addresses, they
> > > > > the bus addresses always overlap, but we can trivially
> > > > > figure out the bus address from Linux I/O port number
> > > > > by subtracting the start of the range.
> > > >
> > > > Are you saying that our LPC controller should specify a
> > > > range property to map bus addresses into a cpu address range?
> > >
> > > No. There is not CPU address associated with it, because it's
> > > not memory mapped.
> > >
> > > Instead, we need to associate a bus address with a logical
> > > Linux port number, both in of_address_to_resource and
> > > in inb()/outb().
> >
> > I think this is effectively what we are doing so far with patch 2/3.
> > The problem with this patch is that we are carving out a "forbidden"
> > IO tokens range that goes from 0 to PCIBIOS_MIN_IO.
> >
> > I think that the proper solution would be to have the LPC driver to
> > set the carveout threshold used in pci_register_io_range(),
> > pci_pio_to_address(), pci_address_to_pio(), but this would impose
> > a probe dependency on the LPC itself that should be probed before
> > the PCI controller (or before any other devices calling these
> > functions...)
> 
> Why do you think the order matters? My point was that we should
> be able to register any region of logical port numbers for any
> bus here.

Maybe I have not followed well so let's roll back to your previous
comment...

"we need to associate a bus address with a logical Linux port number,
both in of_address_to_resource and in inb()/outb()"

Actually of_address_to_resource() returns the port number to used
in inb/outb(); inb() and outb() add the port number to PCI_IOBASE
to rd/wr to the right virtual address.

Our LPC cannot operate on the virtual address and it operates on
a bus address range that for LPC is also equal to the cpu address
range and goes from 0 to 0x1000.

Now as I understand it is risky and not appropriate to reserve
the logical port numbers from 0 to 0x1000 or to whatever other
upper bound because existing systems may rely on these port numbers
retrieved by __of_address_to_resource().

In this scenario I think the best thing to do would be
in the probe function of the LPC driver:
1) call pci_register_io_range() passing [0, 0x1000] (that is the
   range for LPC)
2) retrieve the logical port numbers associated to the LPC range
   by calling pci_address_to_pio() for 0 and 0x1000 and assign
   them to extio_ops_node->start and extio_ops_node->end
3) implement the LPC accessors to operate on the logical ports
   associated to the LPC range (in practice in the accessors
   implementation we will call pci_pio_to_address to retrieve
   the cpu address to operate on)

What do you think?

Thanks

Gab


> 
>
> > > > > > To be honest with you I would keep things simple for this
> > > > > > LPC and introduce more complex reworks later if more devices
> > > > > > need to be introduced.
> > > > > >
> > > > > > What if we stick on a single domain now where we introduce a
> > > > > > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> > > > >
> > > > > I said having a single domain is fine, but I still don't
> > > > > like the idea of reserving low port numbers for this hack,
> > > > > it would mean that the numbers change for everyone else.
> > > >
> > > > I don't get this much...I/O tokens that are passed to the I/O
> > > > accessors are not fixed anyway and they vary depending on the
> order
> > > > of adding ranges to io_range_list...so I don't see a big issue
> > > > with this...
> > >
> > > On machines with a legacy devices behind the PCI bridge,
> > > there may still be a reason to have the low I/O port range
> > > reserved for the primary bus, e.g. to get a VGA text console
> > > to work.
> > >
> > > On powerpc, this is called the "primary" PCI host, i.e. the
> > > only one that is allowed to have an ISA bridge.
> >
> > Yes but
> > 1) isn't the PCI controller range property that defines how IO bus
> address
> >    map into physical CPU addresses?
> 
> Correct, but the DT knows nothing about logical port numbers in Linux.
> 
> > 2) How can you guarantee that the cpu range associated with this
> >    IO bus range is the first to be registered in
> pci_register_io_range()?
> >    ( i.e. are you saying that they are just relying on the fact that
> it is the
> >      only IO range in the system and by chance the IO tokens and
> corresponding
> >      bus addresses are the same? )
> 
> To clarify: the special properties of having the first 0x1000 logical
> port numbers go to a particular physical bus are very obscure. I think
> it's more important to not change the behavior for existing systems
> that might rely on it than for new systems that have no such legacy.
> 
> The ipmi and uart drivers in particular will get the port numbers
> filled
> in their platform device from the DT bus scanning, so they don't care
> at all about having the same numeric value for port numbers on the bus
> and logical numbers, but other drivers might rely on particular ports
> to be mapped on a specific PCI host, especially when those drivers
> are  used only on systems that don't have more than one PCI domain.
> 
> 	Arnd

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-23 15:22                                                 ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-23 15:22 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 23 November 2016 14:16
> To: Gabriele Paoloni
> Cc: linux-arm-kernel at lists.infradead.org; mark.rutland at arm.com;
> benh at kernel.crashing.org; catalin.marinas at arm.com; liviu.dudau at arm.com;
> Linuxarm; lorenzo.pieralisi at arm.com; xuwei (O); Jason Gunthorpe; linux-
> serial at vger.kernel.org; linux-pci at vger.kernel.org;
> devicetree at vger.kernel.org; minyard at acm.org; will.deacon at arm.com; John
> Garry; zourongrong at gmail.com; robh+dt at kernel.org; bhelgaas at go og
> le.com; kantyzc at 163.com; zhichang.yuan02 at gmail.com; T homas Petazzoni;
> linux-kernel at vger.kernel.org; Yuanzhichang; olof at lixom.net
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
> > > On Friday, November 18, 2016 4:18:07 PM CET Gabriele Paoloni wrote:
> > > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > > > On Friday, November 18, 2016 12:53:08 PM CET Gabriele Paoloni
> > > wrote:
> > > > > For the ISA/LPC spaces there are only 4k of addresses, they
> > > > > the bus addresses always overlap, but we can trivially
> > > > > figure out the bus address from Linux I/O port number
> > > > > by subtracting the start of the range.
> > > >
> > > > Are you saying that our LPC controller should specify a
> > > > range property to map bus addresses into a cpu address range?
> > >
> > > No. There is not CPU address associated with it, because it's
> > > not memory mapped.
> > >
> > > Instead, we need to associate a bus address with a logical
> > > Linux port number, both in of_address_to_resource and
> > > in inb()/outb().
> >
> > I think this is effectively what we are doing so far with patch 2/3.
> > The problem with this patch is that we are carving out a "forbidden"
> > IO tokens range that goes from 0 to PCIBIOS_MIN_IO.
> >
> > I think that the proper solution would be to have the LPC driver to
> > set the carveout threshold used in pci_register_io_range(),
> > pci_pio_to_address(), pci_address_to_pio(), but this would impose
> > a probe dependency on the LPC itself that should be probed before
> > the PCI controller (or before any other devices calling these
> > functions...)
> 
> Why do you think the order matters? My point was that we should
> be able to register any region of logical port numbers for any
> bus here.

Maybe I have not followed well so let's roll back to your previous
comment...

"we need to associate a bus address with a logical Linux port number,
both in of_address_to_resource and in inb()/outb()"

Actually of_address_to_resource() returns the port number to used
in inb/outb(); inb() and outb() add the port number to PCI_IOBASE
to rd/wr to the right virtual address.

Our LPC cannot operate on the virtual address and it operates on
a bus address range that for LPC is also equal to the cpu address
range and goes from 0 to 0x1000.

Now as I understand it is risky and not appropriate to reserve
the logical port numbers from 0 to 0x1000 or to whatever other
upper bound because existing systems may rely on these port numbers
retrieved by __of_address_to_resource().

In this scenario I think the best thing to do would be
in the probe function of the LPC driver:
1) call pci_register_io_range() passing [0, 0x1000] (that is the
   range for LPC)
2) retrieve the logical port numbers associated to the LPC range
   by calling pci_address_to_pio() for 0 and 0x1000 and assign
   them to extio_ops_node->start and extio_ops_node->end
3) implement the LPC accessors to operate on the logical ports
   associated to the LPC range (in practice in the accessors
   implementation we will call pci_pio_to_address to retrieve
   the cpu address to operate on)

What do you think?

Thanks

Gab


> 
>
> > > > > > To be honest with you I would keep things simple for this
> > > > > > LPC and introduce more complex reworks later if more devices
> > > > > > need to be introduced.
> > > > > >
> > > > > > What if we stick on a single domain now where we introduce a
> > > > > > reserved threshold for the IO space (say INDIRECT_MAX_IO).
> > > > >
> > > > > I said having a single domain is fine, but I still don't
> > > > > like the idea of reserving low port numbers for this hack,
> > > > > it would mean that the numbers change for everyone else.
> > > >
> > > > I don't get this much...I/O tokens that are passed to the I/O
> > > > accessors are not fixed anyway and they vary depending on the
> order
> > > > of adding ranges to io_range_list...so I don't see a big issue
> > > > with this...
> > >
> > > On machines with a legacy devices behind the PCI bridge,
> > > there may still be a reason to have the low I/O port range
> > > reserved for the primary bus, e.g. to get a VGA text console
> > > to work.
> > >
> > > On powerpc, this is called the "primary" PCI host, i.e. the
> > > only one that is allowed to have an ISA bridge.
> >
> > Yes but
> > 1) isn't the PCI controller range property that defines how IO bus
> address
> >    map into physical CPU addresses?
> 
> Correct, but the DT knows nothing about logical port numbers in Linux.
> 
> > 2) How can you guarantee that the cpu range associated with this
> >    IO bus range is the first to be registered in
> pci_register_io_range()?
> >    ( i.e. are you saying that they are just relying on the fact that
> it is the
> >      only IO range in the system and by chance the IO tokens and
> corresponding
> >      bus addresses are the same? )
> 
> To clarify: the special properties of having the first 0x1000 logical
> port numbers go to a particular physical bus are very obscure. I think
> it's more important to not change the behavior for existing systems
> that might rely on it than for new systems that have no such legacy.
> 
> The ipmi and uart drivers in particular will get the port numbers
> filled
> in their platform device from the DT bus scanning, so they don't care
> at all about having the same numeric value for port numbers on the bus
> and logical numbers, but other drivers might rely on particular ports
> to be mapped on a specific PCI host, especially when those drivers
> are  used only on systems that don't have more than one PCI domain.
> 
> 	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-23 15:22                                                 ` Gabriele Paoloni
  (?)
  (?)
@ 2016-11-23 17:07                                                   ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-23 17:07 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: linux-arm-kernel, mark.rutland, benh, catalin.marinas,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, linux-serial, linux-pci, devicetree, minyard,
	will.deacon, John Garry, zourongrong, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02,
	T homas Petazzoni, linux-kernel, Yuanzhichang, olof

On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni wrote:
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:

> > > I think this is effectively what we are doing so far with patch 2/3.
> > > The problem with this patch is that we are carving out a "forbidden"
> > > IO tokens range that goes from 0 to PCIBIOS_MIN_IO.
> > >
> > > I think that the proper solution would be to have the LPC driver to
> > > set the carveout threshold used in pci_register_io_range(),
> > > pci_pio_to_address(), pci_address_to_pio(), but this would impose
> > > a probe dependency on the LPC itself that should be probed before
> > > the PCI controller (or before any other devices calling these
> > > functions...)
> > 
> > Why do you think the order matters? My point was that we should
> > be able to register any region of logical port numbers for any
> > bus here.
> 
> Maybe I have not followed well so let's roll back to your previous
> comment...
> 
> "we need to associate a bus address with a logical Linux port number,
> both in of_address_to_resource and in inb()/outb()"
> 
> Actually of_address_to_resource() returns the port number to used
> in inb/outb(); inb() and outb() add the port number to PCI_IOBASE
> to rd/wr to the right virtual address.

Correct.

> Our LPC cannot operate on the virtual address and it operates on
> a bus address range that for LPC is also equal to the cpu address
> range and goes from 0 to 0x1000.

There is no "cpu address" here, otherwise this is correct.

> Now as I understand it is risky and not appropriate to reserve
> the logical port numbers from 0 to 0x1000 or to whatever other
> upper bound because existing systems may rely on these port numbers
> retrieved by __of_address_to_resource().

Right again.

> In this scenario I think the best thing to do would be
> in the probe function of the LPC driver:
> 1) call pci_register_io_range() passing [0, 0x1000] (that is the
>    range for LPC)

pci_register_io_range() takes a physical address, not a port number,
so that would not be appropriate as you say above. We can however
add a variant that reserves a range of port numbers in io_range_list
for an indirect access method.

> 2) retrieve the logical port numbers associated to the LPC range
>    by calling pci_address_to_pio() for 0 and 0x1000 and assign
>    them to extio_ops_node->start and extio_ops_node->end

Again, calling pci_address_to_pio() doesn't seem right here, because
we don't have a phys_addr_t address

> 3) implement the LPC accessors to operate on the logical ports
>    associated to the LPC range (in practice in the accessors
>    implementation we will call pci_pio_to_address to retrieve
>    the cpu address to operate on)

Please don't proliferate the use of
pci_pio_to_address/pci_address_to_pio here, computing the physical
address from the logical address is trivial, you just need to
subtract the start of the range that you already use when matching
the port number range.

The only thing we need here is to make of_address_to_resource()
return the correct logical port number that was registered for
a given host device when asked to translate an address that
does not have a CPU address associated with it.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-23 17:07                                                   ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-23 17:07 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	mark.rutland-5wv7dgnIgG8, benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r,
	catalin.marinas-5wv7dgnIgG8, liviu.dudau-5wv7dgnIgG8, Linuxarm,
	lorenzo.pieralisi-5wv7dgnIgG8, xuwei (O),
	Jason Gunthorpe, linux-serial-u79uwXL29TY76Z2rM5mHXA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, minyard-HInyCGIudOg,
	will.deacon-5wv7dgnIgG8, John Garry, zourongrong

On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni wrote:
> From: Arnd Bergmann [mailto:arnd-r2nGTMty4D4@public.gmane.org]
> > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:

> > > I think this is effectively what we are doing so far with patch 2/3.
> > > The problem with this patch is that we are carving out a "forbidden"
> > > IO tokens range that goes from 0 to PCIBIOS_MIN_IO.
> > >
> > > I think that the proper solution would be to have the LPC driver to
> > > set the carveout threshold used in pci_register_io_range(),
> > > pci_pio_to_address(), pci_address_to_pio(), but this would impose
> > > a probe dependency on the LPC itself that should be probed before
> > > the PCI controller (or before any other devices calling these
> > > functions...)
> > 
> > Why do you think the order matters? My point was that we should
> > be able to register any region of logical port numbers for any
> > bus here.
> 
> Maybe I have not followed well so let's roll back to your previous
> comment...
> 
> "we need to associate a bus address with a logical Linux port number,
> both in of_address_to_resource and in inb()/outb()"
> 
> Actually of_address_to_resource() returns the port number to used
> in inb/outb(); inb() and outb() add the port number to PCI_IOBASE
> to rd/wr to the right virtual address.

Correct.

> Our LPC cannot operate on the virtual address and it operates on
> a bus address range that for LPC is also equal to the cpu address
> range and goes from 0 to 0x1000.

There is no "cpu address" here, otherwise this is correct.

> Now as I understand it is risky and not appropriate to reserve
> the logical port numbers from 0 to 0x1000 or to whatever other
> upper bound because existing systems may rely on these port numbers
> retrieved by __of_address_to_resource().

Right again.

> In this scenario I think the best thing to do would be
> in the probe function of the LPC driver:
> 1) call pci_register_io_range() passing [0, 0x1000] (that is the
>    range for LPC)

pci_register_io_range() takes a physical address, not a port number,
so that would not be appropriate as you say above. We can however
add a variant that reserves a range of port numbers in io_range_list
for an indirect access method.

> 2) retrieve the logical port numbers associated to the LPC range
>    by calling pci_address_to_pio() for 0 and 0x1000 and assign
>    them to extio_ops_node->start and extio_ops_node->end

Again, calling pci_address_to_pio() doesn't seem right here, because
we don't have a phys_addr_t address

> 3) implement the LPC accessors to operate on the logical ports
>    associated to the LPC range (in practice in the accessors
>    implementation we will call pci_pio_to_address to retrieve
>    the cpu address to operate on)

Please don't proliferate the use of
pci_pio_to_address/pci_address_to_pio here, computing the physical
address from the logical address is trivial, you just need to
subtract the start of the range that you already use when matching
the port number range.

The only thing we need here is to make of_address_to_resource()
return the correct logical port number that was registered for
a given host device when asked to translate an address that
does not have a CPU address associated with it.

	Arnd
--
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] 286+ messages in thread

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-23 17:07                                                   ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-23 17:07 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: linux-arm-kernel, mark.rutland, benh, catalin.marinas,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, linux-serial, linux-pci, devicetree, minyard,
	will.deacon, John Garry, zourongrong, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02,
	T homas Petazzoni, linux-kernel, Yuanzhichang, olof

On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni wrote:
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:

> > > I think this is effectively what we are doing so far with patch 2/3.
> > > The problem with this patch is that we are carving out a "forbidden"
> > > IO tokens range that goes from 0 to PCIBIOS_MIN_IO.
> > >
> > > I think that the proper solution would be to have the LPC driver to
> > > set the carveout threshold used in pci_register_io_range(),
> > > pci_pio_to_address(), pci_address_to_pio(), but this would impose
> > > a probe dependency on the LPC itself that should be probed before
> > > the PCI controller (or before any other devices calling these
> > > functions...)
> > 
> > Why do you think the order matters? My point was that we should
> > be able to register any region of logical port numbers for any
> > bus here.
> 
> Maybe I have not followed well so let's roll back to your previous
> comment...
> 
> "we need to associate a bus address with a logical Linux port number,
> both in of_address_to_resource and in inb()/outb()"
> 
> Actually of_address_to_resource() returns the port number to used
> in inb/outb(); inb() and outb() add the port number to PCI_IOBASE
> to rd/wr to the right virtual address.

Correct.

> Our LPC cannot operate on the virtual address and it operates on
> a bus address range that for LPC is also equal to the cpu address
> range and goes from 0 to 0x1000.

There is no "cpu address" here, otherwise this is correct.

> Now as I understand it is risky and not appropriate to reserve
> the logical port numbers from 0 to 0x1000 or to whatever other
> upper bound because existing systems may rely on these port numbers
> retrieved by __of_address_to_resource().

Right again.

> In this scenario I think the best thing to do would be
> in the probe function of the LPC driver:
> 1) call pci_register_io_range() passing [0, 0x1000] (that is the
>    range for LPC)

pci_register_io_range() takes a physical address, not a port number,
so that would not be appropriate as you say above. We can however
add a variant that reserves a range of port numbers in io_range_list
for an indirect access method.

> 2) retrieve the logical port numbers associated to the LPC range
>    by calling pci_address_to_pio() for 0 and 0x1000 and assign
>    them to extio_ops_node->start and extio_ops_node->end

Again, calling pci_address_to_pio() doesn't seem right here, because
we don't have a phys_addr_t address

> 3) implement the LPC accessors to operate on the logical ports
>    associated to the LPC range (in practice in the accessors
>    implementation we will call pci_pio_to_address to retrieve
>    the cpu address to operate on)

Please don't proliferate the use of
pci_pio_to_address/pci_address_to_pio here, computing the physical
address from the logical address is trivial, you just need to
subtract the start of the range that you already use when matching
the port number range.

The only thing we need here is to make of_address_to_resource()
return the correct logical port number that was registered for
a given host device when asked to translate an address that
does not have a CPU address associated with it.

	Arnd

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-23 17:07                                                   ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-23 17:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni wrote:
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:

> > > I think this is effectively what we are doing so far with patch 2/3.
> > > The problem with this patch is that we are carving out a "forbidden"
> > > IO tokens range that goes from 0 to PCIBIOS_MIN_IO.
> > >
> > > I think that the proper solution would be to have the LPC driver to
> > > set the carveout threshold used in pci_register_io_range(),
> > > pci_pio_to_address(), pci_address_to_pio(), but this would impose
> > > a probe dependency on the LPC itself that should be probed before
> > > the PCI controller (or before any other devices calling these
> > > functions...)
> > 
> > Why do you think the order matters? My point was that we should
> > be able to register any region of logical port numbers for any
> > bus here.
> 
> Maybe I have not followed well so let's roll back to your previous
> comment...
> 
> "we need to associate a bus address with a logical Linux port number,
> both in of_address_to_resource and in inb()/outb()"
> 
> Actually of_address_to_resource() returns the port number to used
> in inb/outb(); inb() and outb() add the port number to PCI_IOBASE
> to rd/wr to the right virtual address.

Correct.

> Our LPC cannot operate on the virtual address and it operates on
> a bus address range that for LPC is also equal to the cpu address
> range and goes from 0 to 0x1000.

There is no "cpu address" here, otherwise this is correct.

> Now as I understand it is risky and not appropriate to reserve
> the logical port numbers from 0 to 0x1000 or to whatever other
> upper bound because existing systems may rely on these port numbers
> retrieved by __of_address_to_resource().

Right again.

> In this scenario I think the best thing to do would be
> in the probe function of the LPC driver:
> 1) call pci_register_io_range() passing [0, 0x1000] (that is the
>    range for LPC)

pci_register_io_range() takes a physical address, not a port number,
so that would not be appropriate as you say above. We can however
add a variant that reserves a range of port numbers in io_range_list
for an indirect access method.

> 2) retrieve the logical port numbers associated to the LPC range
>    by calling pci_address_to_pio() for 0 and 0x1000 and assign
>    them to extio_ops_node->start and extio_ops_node->end

Again, calling pci_address_to_pio() doesn't seem right here, because
we don't have a phys_addr_t address

> 3) implement the LPC accessors to operate on the logical ports
>    associated to the LPC range (in practice in the accessors
>    implementation we will call pci_pio_to_address to retrieve
>    the cpu address to operate on)

Please don't proliferate the use of
pci_pio_to_address/pci_address_to_pio here, computing the physical
address from the logical address is trivial, you just need to
subtract the start of the range that you already use when matching
the port number range.

The only thing we need here is to make of_address_to_resource()
return the correct logical port number that was registered for
a given host device when asked to translate an address that
does not have a CPU address associated with it.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-23 17:07                                                   ` Arnd Bergmann
  (?)
@ 2016-11-23 23:23                                                     ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-23 23:23 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Gabriele Paoloni, mark.rutland, catalin.marinas, linux-pci,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, T homas Petazzoni, linux-serial, benh,
	devicetree, minyard, will.deacon, John Garry, olof, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02, linux-kernel,
	Yuanzhichang, zourongrong

On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
>
> Please don't proliferate the use of
> pci_pio_to_address/pci_address_to_pio here, computing the physical
> address from the logical address is trivial, you just need to
> subtract the start of the range that you already use when matching
> the port number range.
> 
> The only thing we need here is to make of_address_to_resource()
> return the correct logical port number that was registered for
> a given host device when asked to translate an address that
> does not have a CPU address associated with it.

Ok, I admit this was a little harder than I expected, but see below
for a rough outline of how I think it can be done.

This makes it possible to translate bus specific I/O port numbers
from device nodes into Linux port numbers, and gives a way to register
them. We could take this further and completely remove pci_pio_to_address
and pci_address_to_pio if we make the I/O port translation always
go through the io_range list, looking up up the hostbridge by fwnode,
but we don't have to do that now.

The patch is completely untested and probably buggy, it just seemed
easier to put out a prototype than to keep going in circles with the
discussion.

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

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index bf601d4df8cf..6cadf0501bb0 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 *node,
+					struct resource_entry *entry)
 {
 #ifdef PCI_IOBASE
 	struct resource *res = entry->res;
@@ -739,11 +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))
-		goto err;
-
-	port = pci_address_to_pio(cpu_addr);
-	if (port == (unsigned long)-1)
+	if (pci_register_io_range(node, cpu_addr, length, &port))
 		goto err;
 
 	res->start = port;
@@ -781,7 +778,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/block/nbd.c b/drivers/block/nbd.c
index a50025a3777f..df96955a43f8 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -760,8 +760,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
 		set_bit(NBD_RUNNING, &nbd->runtime_flags);
 		blk_mq_update_nr_hw_queues(&nbd->tag_set, nbd->num_connections);
 		args = kcalloc(num_connections, sizeof(*args), GFP_KERNEL);
-		if (!args)
+		if (!args) {
+			error = -ENOMEM;
 			goto out_err;
+		}
 		nbd->task_recv = current;
 		mutex_unlock(&nbd->config_lock);
 
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 02b2903fe9d2..5decaba96eed 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -2,6 +2,7 @@
 #define pr_fmt(fmt)	"OF: " fmt
 
 #include <linux/device.h>
+#include <linux/fwnode.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
@@ -323,14 +324,9 @@ 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, &port);
 		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 {
 		if ((sizeof(resource_size_t) < 8) &&
@@ -479,7 +475,7 @@ static int of_empty_ranges_quirk(struct device_node *np)
 	return false;
 }
 
-static int of_translate_one(struct device_node *parent, struct of_bus *bus,
+static u64 of_translate_one(struct device_node *parent, struct of_bus *bus,
 			    struct of_bus *pbus, __be32 *addr,
 			    int na, int ns, int pna, const char *rprop)
 {
@@ -507,7 +503,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
 	ranges = of_get_property(parent, rprop, &rlen);
 	if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
 		pr_debug("no ranges; cannot translate\n");
-		return 1;
+		return OF_BAD_ADDR;
 	}
 	if (ranges == NULL || rlen == 0) {
 		offset = of_read_number(addr, na);
@@ -528,7 +524,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
 	}
 	if (offset == OF_BAD_ADDR) {
 		pr_debug("not found !\n");
-		return 1;
+		return offset;
 	}
 	memcpy(addr, ranges + na, 4 * pna);
 
@@ -537,7 +533,10 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
 	pr_debug("with offset: %llx\n", (unsigned long long)offset);
 
 	/* Translate it into parent bus space */
-	return pbus->translate(addr, offset, pna);
+	if (pbus->translate(addr, offset, pna))
+		return OF_BAD_ADDR;
+
+	return offset;
 }
 
 /*
@@ -549,9 +548,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 lacks a tranlation, 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;
@@ -564,6 +568,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)
@@ -600,8 +605,9 @@ static u64 __of_translate_address(struct device_node *dev,
 		pbus = of_match_bus(parent);
 		pbus->count_cells(dev, &pna, &pns);
 		if (!OF_CHECK_COUNTS(pna, pns)) {
-			pr_err("Bad cell count for %s\n",
-			       of_node_full_name(dev));
+			pr_debug("Bad cell count for %s\n",
+				 of_node_full_name(dev));
+			*host = of_node_get(parent);
 			break;
 		}
 
@@ -609,7 +615,9 @@ static u64 __of_translate_address(struct device_node *dev,
 		    pbus->name, pna, pns, of_node_full_name(parent));
 
 		/* Apply bus translation */
-		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
+		result = of_translate_one(dev, bus, pbus, addr, na, ns,
+					  pna, rprop);
+		if (result == OF_BAD_ADDR)
 			break;
 
 		/* Complete the move up one level */
@@ -628,13 +636,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);
 
@@ -676,29 +703,48 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
 }
 EXPORT_SYMBOL(of_get_address);
 
+extern unsigned long extio_translate(struct fwnode_handle *node, unsigned long offset);
+
+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 = extio_translate(&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;
 
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index eda6a7cf0e54..320ab9fbf6af 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3249,6 +3249,7 @@ EXPORT_SYMBOL(pci_request_regions_exclusive);
 #ifdef PCI_IOBASE
 struct io_range {
 	struct list_head list;
+	struct fwnode_handle *node;
 	phys_addr_t start;
 	resource_size_t size;
 };
@@ -3257,11 +3258,14 @@ static LIST_HEAD(io_range_list);
 static DEFINE_SPINLOCK(io_range_lock);
 #endif
 
+#define IO_RANGE_IOEXT (resource_size_t)(-1ull)
+
 /*
  * 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 __weak pci_register_io_range(struct fwnode_handle *node, phys_addr_t addr,
+				 resource_size_t size, unsigned long *port)
 {
 	int err = 0;
 
@@ -3272,7 +3276,12 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
 	/* 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) {
+		if (node == range->node)
+			goto end_register;
+
+		if (addr != IO_RANGE_IOEXT &&
+		    addr >= range->start &&
+		    addr + size <= range->start + size) {
 			/* range already registered, bail out */
 			goto end_register;
 		}
@@ -3298,6 +3307,7 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
 		goto end_register;
 	}
 
+	range->node = node;
 	range->start = addr;
 	range->size = size;
 
@@ -3305,11 +3315,26 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
 
 end_register:
 	spin_unlock(&io_range_lock);
+
+	*port = allocated_size;
+#else
+	/*
+	 * powerpc and microblaze have their own registration,
+	 * just look up the value here
+	 */
+	*port = pci_address_to_pio(addr);
 #endif
 
 	return err;
 }
 
+#ifdef CONFIG_IOEXT
+int ioext_register_io_range
+{
+	return pci_register_io_range(node, IO_RANGE_IOEXT, size, port);
+}
+#endif
+
 phys_addr_t pci_pio_to_address(unsigned long pio)
 {
 	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 6bd94a803e8f..b7a8fa3da3ca 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1192,7 +1192,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 *node, phys_addr_t addr,
+			  resource_size_t size, unsigned long *port);
 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);

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-23 23:23                                                     ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-23 23:23 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: mark.rutland, Gabriele Paoloni, benh, liviu.dudau, Linuxarm,
	lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, T homas Petazzoni, linux-serial,
	catalin.marinas, devicetree, minyard, will.deacon, John Garry,
	zourongrong, robh+dt, bhelgaas@go og le.com, kantyzc

On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
>
> Please don't proliferate the use of
> pci_pio_to_address/pci_address_to_pio here, computing the physical
> address from the logical address is trivial, you just need to
> subtract the start of the range that you already use when matching
> the port number range.
> 
> The only thing we need here is to make of_address_to_resource()
> return the correct logical port number that was registered for
> a given host device when asked to translate an address that
> does not have a CPU address associated with it.

Ok, I admit this was a little harder than I expected, but see below
for a rough outline of how I think it can be done.

This makes it possible to translate bus specific I/O port numbers
from device nodes into Linux port numbers, and gives a way to register
them. We could take this further and completely remove pci_pio_to_address
and pci_address_to_pio if we make the I/O port translation always
go through the io_range list, looking up up the hostbridge by fwnode,
but we don't have to do that now.

The patch is completely untested and probably buggy, it just seemed
easier to put out a prototype than to keep going in circles with the
discussion.

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

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index bf601d4df8cf..6cadf0501bb0 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 *node,
+					struct resource_entry *entry)
 {
 #ifdef PCI_IOBASE
 	struct resource *res = entry->res;
@@ -739,11 +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))
-		goto err;
-
-	port = pci_address_to_pio(cpu_addr);
-	if (port == (unsigned long)-1)
+	if (pci_register_io_range(node, cpu_addr, length, &port))
 		goto err;
 
 	res->start = port;
@@ -781,7 +778,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/block/nbd.c b/drivers/block/nbd.c
index a50025a3777f..df96955a43f8 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -760,8 +760,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
 		set_bit(NBD_RUNNING, &nbd->runtime_flags);
 		blk_mq_update_nr_hw_queues(&nbd->tag_set, nbd->num_connections);
 		args = kcalloc(num_connections, sizeof(*args), GFP_KERNEL);
-		if (!args)
+		if (!args) {
+			error = -ENOMEM;
 			goto out_err;
+		}
 		nbd->task_recv = current;
 		mutex_unlock(&nbd->config_lock);
 
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 02b2903fe9d2..5decaba96eed 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -2,6 +2,7 @@
 #define pr_fmt(fmt)	"OF: " fmt
 
 #include <linux/device.h>
+#include <linux/fwnode.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
@@ -323,14 +324,9 @@ 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, &port);
 		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 {
 		if ((sizeof(resource_size_t) < 8) &&
@@ -479,7 +475,7 @@ static int of_empty_ranges_quirk(struct device_node *np)
 	return false;
 }
 
-static int of_translate_one(struct device_node *parent, struct of_bus *bus,
+static u64 of_translate_one(struct device_node *parent, struct of_bus *bus,
 			    struct of_bus *pbus, __be32 *addr,
 			    int na, int ns, int pna, const char *rprop)
 {
@@ -507,7 +503,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
 	ranges = of_get_property(parent, rprop, &rlen);
 	if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
 		pr_debug("no ranges; cannot translate\n");
-		return 1;
+		return OF_BAD_ADDR;
 	}
 	if (ranges == NULL || rlen == 0) {
 		offset = of_read_number(addr, na);
@@ -528,7 +524,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
 	}
 	if (offset == OF_BAD_ADDR) {
 		pr_debug("not found !\n");
-		return 1;
+		return offset;
 	}
 	memcpy(addr, ranges + na, 4 * pna);
 
@@ -537,7 +533,10 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
 	pr_debug("with offset: %llx\n", (unsigned long long)offset);
 
 	/* Translate it into parent bus space */
-	return pbus->translate(addr, offset, pna);
+	if (pbus->translate(addr, offset, pna))
+		return OF_BAD_ADDR;
+
+	return offset;
 }
 
 /*
@@ -549,9 +548,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 lacks a tranlation, 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;
@@ -564,6 +568,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)
@@ -600,8 +605,9 @@ static u64 __of_translate_address(struct device_node *dev,
 		pbus = of_match_bus(parent);
 		pbus->count_cells(dev, &pna, &pns);
 		if (!OF_CHECK_COUNTS(pna, pns)) {
-			pr_err("Bad cell count for %s\n",
-			       of_node_full_name(dev));
+			pr_debug("Bad cell count for %s\n",
+				 of_node_full_name(dev));
+			*host = of_node_get(parent);
 			break;
 		}
 
@@ -609,7 +615,9 @@ static u64 __of_translate_address(struct device_node *dev,
 		    pbus->name, pna, pns, of_node_full_name(parent));
 
 		/* Apply bus translation */
-		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
+		result = of_translate_one(dev, bus, pbus, addr, na, ns,
+					  pna, rprop);
+		if (result == OF_BAD_ADDR)
 			break;
 
 		/* Complete the move up one level */
@@ -628,13 +636,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);
 
@@ -676,29 +703,48 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
 }
 EXPORT_SYMBOL(of_get_address);
 
+extern unsigned long extio_translate(struct fwnode_handle *node, unsigned long offset);
+
+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 = extio_translate(&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;
 
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index eda6a7cf0e54..320ab9fbf6af 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3249,6 +3249,7 @@ EXPORT_SYMBOL(pci_request_regions_exclusive);
 #ifdef PCI_IOBASE
 struct io_range {
 	struct list_head list;
+	struct fwnode_handle *node;
 	phys_addr_t start;
 	resource_size_t size;
 };
@@ -3257,11 +3258,14 @@ static LIST_HEAD(io_range_list);
 static DEFINE_SPINLOCK(io_range_lock);
 #endif
 
+#define IO_RANGE_IOEXT (resource_size_t)(-1ull)
+
 /*
  * 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 __weak pci_register_io_range(struct fwnode_handle *node, phys_addr_t addr,
+				 resource_size_t size, unsigned long *port)
 {
 	int err = 0;
 
@@ -3272,7 +3276,12 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
 	/* 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) {
+		if (node == range->node)
+			goto end_register;
+
+		if (addr != IO_RANGE_IOEXT &&
+		    addr >= range->start &&
+		    addr + size <= range->start + size) {
 			/* range already registered, bail out */
 			goto end_register;
 		}
@@ -3298,6 +3307,7 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
 		goto end_register;
 	}
 
+	range->node = node;
 	range->start = addr;
 	range->size = size;
 
@@ -3305,11 +3315,26 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
 
 end_register:
 	spin_unlock(&io_range_lock);
+
+	*port = allocated_size;
+#else
+	/*
+	 * powerpc and microblaze have their own registration,
+	 * just look up the value here
+	 */
+	*port = pci_address_to_pio(addr);
 #endif
 
 	return err;
 }
 
+#ifdef CONFIG_IOEXT
+int ioext_register_io_range
+{
+	return pci_register_io_range(node, IO_RANGE_IOEXT, size, port);
+}
+#endif
+
 phys_addr_t pci_pio_to_address(unsigned long pio)
 {
 	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 6bd94a803e8f..b7a8fa3da3ca 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1192,7 +1192,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 *node, phys_addr_t addr,
+			  resource_size_t size, unsigned long *port);
 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);

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-23 23:23                                                     ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-23 23:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
>
> Please don't proliferate the use of
> pci_pio_to_address/pci_address_to_pio here, computing the physical
> address from the logical address is trivial, you just need to
> subtract the start of the range that you already use when matching
> the port number range.
> 
> The only thing we need here is to make of_address_to_resource()
> return the correct logical port number that was registered for
> a given host device when asked to translate an address that
> does not have a CPU address associated with it.

Ok, I admit this was a little harder than I expected, but see below
for a rough outline of how I think it can be done.

This makes it possible to translate bus specific I/O port numbers
from device nodes into Linux port numbers, and gives a way to register
them. We could take this further and completely remove pci_pio_to_address
and pci_address_to_pio if we make the I/O port translation always
go through the io_range list, looking up up the hostbridge by fwnode,
but we don't have to do that now.

The patch is completely untested and probably buggy, it just seemed
easier to put out a prototype than to keep going in circles with the
discussion.

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

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index bf601d4df8cf..6cadf0501bb0 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 *node,
+					struct resource_entry *entry)
 {
 #ifdef PCI_IOBASE
 	struct resource *res = entry->res;
@@ -739,11 +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))
-		goto err;
-
-	port = pci_address_to_pio(cpu_addr);
-	if (port == (unsigned long)-1)
+	if (pci_register_io_range(node, cpu_addr, length, &port))
 		goto err;
 
 	res->start = port;
@@ -781,7 +778,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/block/nbd.c b/drivers/block/nbd.c
index a50025a3777f..df96955a43f8 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -760,8 +760,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
 		set_bit(NBD_RUNNING, &nbd->runtime_flags);
 		blk_mq_update_nr_hw_queues(&nbd->tag_set, nbd->num_connections);
 		args = kcalloc(num_connections, sizeof(*args), GFP_KERNEL);
-		if (!args)
+		if (!args) {
+			error = -ENOMEM;
 			goto out_err;
+		}
 		nbd->task_recv = current;
 		mutex_unlock(&nbd->config_lock);
 
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 02b2903fe9d2..5decaba96eed 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -2,6 +2,7 @@
 #define pr_fmt(fmt)	"OF: " fmt
 
 #include <linux/device.h>
+#include <linux/fwnode.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
@@ -323,14 +324,9 @@ 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, &port);
 		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 {
 		if ((sizeof(resource_size_t) < 8) &&
@@ -479,7 +475,7 @@ static int of_empty_ranges_quirk(struct device_node *np)
 	return false;
 }
 
-static int of_translate_one(struct device_node *parent, struct of_bus *bus,
+static u64 of_translate_one(struct device_node *parent, struct of_bus *bus,
 			    struct of_bus *pbus, __be32 *addr,
 			    int na, int ns, int pna, const char *rprop)
 {
@@ -507,7 +503,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
 	ranges = of_get_property(parent, rprop, &rlen);
 	if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
 		pr_debug("no ranges; cannot translate\n");
-		return 1;
+		return OF_BAD_ADDR;
 	}
 	if (ranges == NULL || rlen == 0) {
 		offset = of_read_number(addr, na);
@@ -528,7 +524,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
 	}
 	if (offset == OF_BAD_ADDR) {
 		pr_debug("not found !\n");
-		return 1;
+		return offset;
 	}
 	memcpy(addr, ranges + na, 4 * pna);
 
@@ -537,7 +533,10 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
 	pr_debug("with offset: %llx\n", (unsigned long long)offset);
 
 	/* Translate it into parent bus space */
-	return pbus->translate(addr, offset, pna);
+	if (pbus->translate(addr, offset, pna))
+		return OF_BAD_ADDR;
+
+	return offset;
 }
 
 /*
@@ -549,9 +548,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 lacks a tranlation, 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;
@@ -564,6 +568,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)
@@ -600,8 +605,9 @@ static u64 __of_translate_address(struct device_node *dev,
 		pbus = of_match_bus(parent);
 		pbus->count_cells(dev, &pna, &pns);
 		if (!OF_CHECK_COUNTS(pna, pns)) {
-			pr_err("Bad cell count for %s\n",
-			       of_node_full_name(dev));
+			pr_debug("Bad cell count for %s\n",
+				 of_node_full_name(dev));
+			*host = of_node_get(parent);
 			break;
 		}
 
@@ -609,7 +615,9 @@ static u64 __of_translate_address(struct device_node *dev,
 		    pbus->name, pna, pns, of_node_full_name(parent));
 
 		/* Apply bus translation */
-		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
+		result = of_translate_one(dev, bus, pbus, addr, na, ns,
+					  pna, rprop);
+		if (result == OF_BAD_ADDR)
 			break;
 
 		/* Complete the move up one level */
@@ -628,13 +636,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);
 
@@ -676,29 +703,48 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
 }
 EXPORT_SYMBOL(of_get_address);
 
+extern unsigned long extio_translate(struct fwnode_handle *node, unsigned long offset);
+
+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 = extio_translate(&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;
 
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index eda6a7cf0e54..320ab9fbf6af 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3249,6 +3249,7 @@ EXPORT_SYMBOL(pci_request_regions_exclusive);
 #ifdef PCI_IOBASE
 struct io_range {
 	struct list_head list;
+	struct fwnode_handle *node;
 	phys_addr_t start;
 	resource_size_t size;
 };
@@ -3257,11 +3258,14 @@ static LIST_HEAD(io_range_list);
 static DEFINE_SPINLOCK(io_range_lock);
 #endif
 
+#define IO_RANGE_IOEXT (resource_size_t)(-1ull)
+
 /*
  * 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 __weak pci_register_io_range(struct fwnode_handle *node, phys_addr_t addr,
+				 resource_size_t size, unsigned long *port)
 {
 	int err = 0;
 
@@ -3272,7 +3276,12 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
 	/* 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) {
+		if (node == range->node)
+			goto end_register;
+
+		if (addr != IO_RANGE_IOEXT &&
+		    addr >= range->start &&
+		    addr + size <= range->start + size) {
 			/* range already registered, bail out */
 			goto end_register;
 		}
@@ -3298,6 +3307,7 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
 		goto end_register;
 	}
 
+	range->node = node;
 	range->start = addr;
 	range->size = size;
 
@@ -3305,11 +3315,26 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
 
 end_register:
 	spin_unlock(&io_range_lock);
+
+	*port = allocated_size;
+#else
+	/*
+	 * powerpc and microblaze have their own registration,
+	 * just look up the value here
+	 */
+	*port = pci_address_to_pio(addr);
 #endif
 
 	return err;
 }
 
+#ifdef CONFIG_IOEXT
+int ioext_register_io_range
+{
+	return pci_register_io_range(node, IO_RANGE_IOEXT, size, port);
+}
+#endif
+
 phys_addr_t pci_pio_to_address(unsigned long pio)
 {
 	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 6bd94a803e8f..b7a8fa3da3ca 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1192,7 +1192,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 *node, phys_addr_t addr,
+			  resource_size_t size, unsigned long *port);
 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);

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-23 23:23                                                     ` Arnd Bergmann
  (?)
@ 2016-11-24  9:12                                                       ` zhichang.yuan
  -1 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-24  9:12 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: Gabriele Paoloni, mark.rutland, catalin.marinas, linux-pci,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, T homas Petazzoni, linux-serial, benh,
	devicetree, minyard, will.deacon, John Garry, olof, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02, linux-kernel,
	zourongrong

Hi, Arnd,

Thanks you very much!

To understand your idea more clear, I have some questions on your patch sketch.
Please check it below.


On 2016/11/24 7:23, Arnd Bergmann wrote:
> On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
>> On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni wrote:
>>> From: Arnd Bergmann [mailto:arnd@arndb.de]
>>>> On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
>>
>> Please don't proliferate the use of
>> pci_pio_to_address/pci_address_to_pio here, computing the physical
>> address from the logical address is trivial, you just need to
>> subtract the start of the range that you already use when matching
>> the port number range.
>>
>> The only thing we need here is to make of_address_to_resource()
>> return the correct logical port number that was registered for
>> a given host device when asked to translate an address that
>> does not have a CPU address associated with it.
> 
> Ok, I admit this was a little harder than I expected, but see below
> for a rough outline of how I think it can be done.
> 
> This makes it possible to translate bus specific I/O port numbers
> from device nodes into Linux port numbers, and gives a way to register
> them. We could take this further and completely remove pci_pio_to_address
> and pci_address_to_pio if we make the I/O port translation always
> go through the io_range list, looking up up the hostbridge by fwnode,
> but we don't have to do that now.
> 
> The patch is completely untested and probably buggy, it just seemed
> easier to put out a prototype than to keep going in circles with the
> discussion.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> 
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> index bf601d4df8cf..6cadf0501bb0 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 *node,
> +					struct resource_entry *entry)
>  {
>  #ifdef PCI_IOBASE
>  	struct resource *res = entry->res;
> @@ -739,11 +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))
> -		goto err;
> -
> -	port = pci_address_to_pio(cpu_addr);
> -	if (port == (unsigned long)-1)
> +	if (pci_register_io_range(node, cpu_addr, length, &port))
>  		goto err;
>  
>  	res->start = port;
> @@ -781,7 +778,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);

I think those changes in pci_root.c is only to match the new definition of
pci_register_io_range() and work for PCI I/O. It doesn't make sense for LPC, is
it right?


> diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
> index a50025a3777f..df96955a43f8 100644
> --- a/drivers/block/nbd.c
> +++ b/drivers/block/nbd.c
> @@ -760,8 +760,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
>  		set_bit(NBD_RUNNING, &nbd->runtime_flags);
>  		blk_mq_update_nr_hw_queues(&nbd->tag_set, nbd->num_connections);
>  		args = kcalloc(num_connections, sizeof(*args), GFP_KERNEL);
> -		if (!args)
> +		if (!args) {
> +			error = -ENOMEM;
>  			goto out_err;
> +		}
>  		nbd->task_recv = current;
>  		mutex_unlock(&nbd->config_lock);
>  
I think change here is none of the business.:)

> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903fe9d2..5decaba96eed 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -2,6 +2,7 @@
>  #define pr_fmt(fmt)	"OF: " fmt
>  
>  #include <linux/device.h>
> +#include <linux/fwnode.h>
>  #include <linux/io.h>
>  #include <linux/ioport.h>
>  #include <linux/module.h>
> @@ -323,14 +324,9 @@ 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, &port);
>  		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 {
>  		if ((sizeof(resource_size_t) < 8) &&
> @@ -479,7 +475,7 @@ static int of_empty_ranges_quirk(struct device_node *np)
>  	return false;
>  }
>  
> -static int of_translate_one(struct device_node *parent, struct of_bus *bus,
> +static u64 of_translate_one(struct device_node *parent, struct of_bus *bus,
>  			    struct of_bus *pbus, __be32 *addr,
>  			    int na, int ns, int pna, const char *rprop)
>  {
> @@ -507,7 +503,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>  	ranges = of_get_property(parent, rprop, &rlen);
>  	if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
>  		pr_debug("no ranges; cannot translate\n");
> -		return 1;
> +		return OF_BAD_ADDR;
>  	}
>  	if (ranges == NULL || rlen == 0) {
>  		offset = of_read_number(addr, na);
> @@ -528,7 +524,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>  	}
>  	if (offset == OF_BAD_ADDR) {
>  		pr_debug("not found !\n");
> -		return 1;
> +		return offset;
>  	}
>  	memcpy(addr, ranges + na, 4 * pna);
>  
> @@ -537,7 +533,10 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>  	pr_debug("with offset: %llx\n", (unsigned long long)offset);
>  
>  	/* Translate it into parent bus space */
> -	return pbus->translate(addr, offset, pna);
> +	if (pbus->translate(addr, offset, pna))
> +		return OF_BAD_ADDR;
> +
> +	return offset;
>  }
>  
>  /*
> @@ -549,9 +548,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 lacks a tranlation, 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;
> @@ -564,6 +568,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)
> @@ -600,8 +605,9 @@ static u64 __of_translate_address(struct device_node *dev,
>  		pbus = of_match_bus(parent);
>  		pbus->count_cells(dev, &pna, &pns);
>  		if (!OF_CHECK_COUNTS(pna, pns)) {
> -			pr_err("Bad cell count for %s\n",
> -			       of_node_full_name(dev));
> +			pr_debug("Bad cell count for %s\n",
> +				 of_node_full_name(dev));
> +			*host = of_node_get(parent);
>  			break;
>  		}
I don't think here is the right place to fill *host. I think you want to return
the parent where the of_translate_one() failed for the 'ranges' property
missing. So, I think this seems better:

if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop)) {
			*host = of_node_get(dev);
			break;
}

>  
> @@ -609,7 +615,9 @@ static u64 __of_translate_address(struct device_node *dev,
>  		    pbus->name, pna, pns, of_node_full_name(parent));
>  
>  		/* Apply bus translation */
> -		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
> +		result = of_translate_one(dev, bus, pbus, addr, na, ns,
> +					  pna, rprop);
> +		if (result == OF_BAD_ADDR)
>  			break;
>  
>  		/* Complete the move up one level */
> @@ -628,13 +636,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);
>  
> @@ -676,29 +703,48 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
>  }
>  EXPORT_SYMBOL(of_get_address);
>  
> +extern unsigned long extio_translate(struct fwnode_handle *node, unsigned long offset);
> +
> +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 = extio_translate(&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;
>  
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index eda6a7cf0e54..320ab9fbf6af 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -3249,6 +3249,7 @@ EXPORT_SYMBOL(pci_request_regions_exclusive);
>  #ifdef PCI_IOBASE
>  struct io_range {
>  	struct list_head list;
> +	struct fwnode_handle *node;
>  	phys_addr_t start;
>  	resource_size_t size;
>  };
> @@ -3257,11 +3258,14 @@ static LIST_HEAD(io_range_list);
>  static DEFINE_SPINLOCK(io_range_lock);
>  #endif
>  
> +#define IO_RANGE_IOEXT (resource_size_t)(-1ull)
> +
>  /*
>   * 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 __weak pci_register_io_range(struct fwnode_handle *node, phys_addr_t addr,
> +				 resource_size_t size, unsigned long *port)
>  {
>  	int err = 0;
>  
> @@ -3272,7 +3276,12 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
>  	/* 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) {
> +		if (node == range->node)
> +			goto end_register;
> +
I don't think it is safe to only check the node had been registered. For
PCI/PCIE, there is only one I/O windows in bridge, it seems ok. But for non-pci
devices, such as ISA/LPC, I wonder it is possible there are several disjoint I/O
'ranges' entries...

What parameters are necessary for linux PIO allocation?
1) For those bus devices which have no MMIO( that is to say, indirectIO is
using),  I think 'addr' is not needed, but 'size' is mandatory;

I am thinking for our LPC, as there is no cpu address, we should not input
'addr' for the io range register. With 'size' as parameter, we implement a new
io range register function where can assign an unique linux PIO for this
register calling. The output linux PIO can allocate from a sub-range of whole
I/O space of [0, IO_SPACE_LIMIT]. This sub-range is specific for indirectIO, I
want to define a new macro, such as EXTIO_LIMIT, to represent the upper limit of
indirect IO space.

#if defined(CONFIG_PCI) && defined(CONFIG_INDIRECT_PIO)
#define EXTIO_LIMIT	PCIBIOS_MIN_IO
#elif defined(CONFIG_INDIRECT_PIO)
#define EXTIO_LIMIT	0x1000
#else
#define EXTIO_LIMIT 	0x00
#end

We should do some checkings to ensure EXTIO_LIMIT < IO_SPACE_LIMIT.

Then when someone call pci_register_io_range() or a new function for the linux
PIO register, we can allocate linux PIO from [0, EXTIO_LIMIT) for indirectIO
bus, from [EXTIO_LIMIT, IO_SPACE_LIMIT] for MMIO;

But there are issues confused me yet. For example, how to know the IO size for
the indirectIO bus? You known, there is no 'ranges' property for those buses....



2) For PCI MMIO, I think 'addr' is needed

As for the current pci_register_io_range()/pci_address_to_pio(), I have two doubts:

2.1) If there are multiple PCI host bridges which support I/O transaction, I
wonder whether the first host bridge can access the downstream devices with bus
I/O address in [0, PCIBIOS_MIN_IO)

for the first host bridge, pci_address_to_pio() will return a linux PIO range
start from 0.
But when calling __pci_assign_resource() to allocate the linux PIO for PCI/PCIE
devices/buses which are just children of first host bus, it can not allocate
linux PIO less than PCIBIOS_MIN_IO, which means kernel can not called in/out()
with port less than PCIBIOS_MIN_IO. But we had ioremap [PCI_IOBASE + 0,
PCI_IOBASE + size) to [pci_ioadd, pci_ioadd + size) before.


static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
		int resno, resource_size_t size, resource_size_t align)
{
	struct resource *res = dev->resource + resno;
	resource_size_t min;
	int ret;

	min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;


and in the later function:

static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
		resource_size_t size, resource_size_t align,
		resource_size_t min, unsigned long type_mask,
		resource_size_t (*alignf)(void *,

....
	pci_bus_for_each_resource(bus, r, i) {
		resource_size_t min_used = min;
....
		if (avail.start)
			min_used = avail.start;

		max = avail.end;

		/* Ok, try it out.. */
		ret = allocate_resource(r, res, size, min_used, max,
					align, alignf, alignf_data);

After allocate_resource(), a IO resource is allocated, but whose 'start' is not
less than min_used.( since avail.start is 0, min_used will keep the 'min'
without change to avail.start; Should be PCIBIOS_MIN_IO).

2.2) Is it possible the return linux PIO isn't page-aligned?

When calling pci_remap_iospace(const struct resource *res, phys_addr_t
phys_addr), if res->start is not page-aligned, it seems that
ioremap_page_range() will meet some issues for duplication iorempa for same
virtual page.

of-course, if we always configure the I/O ranges size as page-aligned, it will
be OK.

I found PowerPC will ensure the 'vaddress' and the 'size' are page-aligned
before ioremap, do we need to improve the current handling in
pci_register_io_range/pci_address_to_pio?


Thanks,
Zhichang
> +		if (addr != IO_RANGE_IOEXT &&
> +		    addr >= range->start &&
> +		    addr + size <= range->start + size) {
>  			/* range already registered, bail out */
>  			goto end_register;
>  		}
> @@ -3298,6 +3307,7 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
>  		goto end_register;
>  	}
>  
> +	range->node = node;
>  	range->start = addr;
>  	range->size = size;
>  
> @@ -3305,11 +3315,26 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
>  
>  end_register:
>  	spin_unlock(&io_range_lock);
> +
> +	*port = allocated_size;
> +#else
> +	/*
> +	 * powerpc and microblaze have their own registration,
> +	 * just look up the value here
> +	 */
> +	*port = pci_address_to_pio(addr);
>  #endif
>  
>  	return err;
>  }
>  
> +#ifdef CONFIG_IOEXT
> +int ioext_register_io_range
> +{
> +	return pci_register_io_range(node, IO_RANGE_IOEXT, size, port);
> +}
> +#endif
> +
>  phys_addr_t pci_pio_to_address(unsigned long pio)
>  {
>  	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 6bd94a803e8f..b7a8fa3da3ca 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1192,7 +1192,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 *node, phys_addr_t addr,
> +			  resource_size_t size, unsigned long *port);
>  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);
> 
> 
> .
> 

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-24  9:12                                                       ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-24  9:12 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: Gabriele Paoloni, mark.rutland, catalin.marinas, linux-pci,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, T homas Petazzoni, linux-serial, benh,
	devicetree, minyard, will.deacon, John Garry

Hi, Arnd,

Thanks you very much!

To understand your idea more clear, I have some questions on your patch sketch.
Please check it below.


On 2016/11/24 7:23, Arnd Bergmann wrote:
> On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
>> On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni wrote:
>>> From: Arnd Bergmann [mailto:arnd@arndb.de]
>>>> On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
>>
>> Please don't proliferate the use of
>> pci_pio_to_address/pci_address_to_pio here, computing the physical
>> address from the logical address is trivial, you just need to
>> subtract the start of the range that you already use when matching
>> the port number range.
>>
>> The only thing we need here is to make of_address_to_resource()
>> return the correct logical port number that was registered for
>> a given host device when asked to translate an address that
>> does not have a CPU address associated with it.
> 
> Ok, I admit this was a little harder than I expected, but see below
> for a rough outline of how I think it can be done.
> 
> This makes it possible to translate bus specific I/O port numbers
> from device nodes into Linux port numbers, and gives a way to register
> them. We could take this further and completely remove pci_pio_to_address
> and pci_address_to_pio if we make the I/O port translation always
> go through the io_range list, looking up up the hostbridge by fwnode,
> but we don't have to do that now.
> 
> The patch is completely untested and probably buggy, it just seemed
> easier to put out a prototype than to keep going in circles with the
> discussion.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> 
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> index bf601d4df8cf..6cadf0501bb0 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 *node,
> +					struct resource_entry *entry)
>  {
>  #ifdef PCI_IOBASE
>  	struct resource *res = entry->res;
> @@ -739,11 +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))
> -		goto err;
> -
> -	port = pci_address_to_pio(cpu_addr);
> -	if (port == (unsigned long)-1)
> +	if (pci_register_io_range(node, cpu_addr, length, &port))
>  		goto err;
>  
>  	res->start = port;
> @@ -781,7 +778,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);

I think those changes in pci_root.c is only to match the new definition of
pci_register_io_range() and work for PCI I/O. It doesn't make sense for LPC, is
it right?


> diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
> index a50025a3777f..df96955a43f8 100644
> --- a/drivers/block/nbd.c
> +++ b/drivers/block/nbd.c
> @@ -760,8 +760,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
>  		set_bit(NBD_RUNNING, &nbd->runtime_flags);
>  		blk_mq_update_nr_hw_queues(&nbd->tag_set, nbd->num_connections);
>  		args = kcalloc(num_connections, sizeof(*args), GFP_KERNEL);
> -		if (!args)
> +		if (!args) {
> +			error = -ENOMEM;
>  			goto out_err;
> +		}
>  		nbd->task_recv = current;
>  		mutex_unlock(&nbd->config_lock);
>  
I think change here is none of the business.:)

> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903fe9d2..5decaba96eed 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -2,6 +2,7 @@
>  #define pr_fmt(fmt)	"OF: " fmt
>  
>  #include <linux/device.h>
> +#include <linux/fwnode.h>
>  #include <linux/io.h>
>  #include <linux/ioport.h>
>  #include <linux/module.h>
> @@ -323,14 +324,9 @@ 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, &port);
>  		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 {
>  		if ((sizeof(resource_size_t) < 8) &&
> @@ -479,7 +475,7 @@ static int of_empty_ranges_quirk(struct device_node *np)
>  	return false;
>  }
>  
> -static int of_translate_one(struct device_node *parent, struct of_bus *bus,
> +static u64 of_translate_one(struct device_node *parent, struct of_bus *bus,
>  			    struct of_bus *pbus, __be32 *addr,
>  			    int na, int ns, int pna, const char *rprop)
>  {
> @@ -507,7 +503,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>  	ranges = of_get_property(parent, rprop, &rlen);
>  	if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
>  		pr_debug("no ranges; cannot translate\n");
> -		return 1;
> +		return OF_BAD_ADDR;
>  	}
>  	if (ranges == NULL || rlen == 0) {
>  		offset = of_read_number(addr, na);
> @@ -528,7 +524,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>  	}
>  	if (offset == OF_BAD_ADDR) {
>  		pr_debug("not found !\n");
> -		return 1;
> +		return offset;
>  	}
>  	memcpy(addr, ranges + na, 4 * pna);
>  
> @@ -537,7 +533,10 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>  	pr_debug("with offset: %llx\n", (unsigned long long)offset);
>  
>  	/* Translate it into parent bus space */
> -	return pbus->translate(addr, offset, pna);
> +	if (pbus->translate(addr, offset, pna))
> +		return OF_BAD_ADDR;
> +
> +	return offset;
>  }
>  
>  /*
> @@ -549,9 +548,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 lacks a tranlation, 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;
> @@ -564,6 +568,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)
> @@ -600,8 +605,9 @@ static u64 __of_translate_address(struct device_node *dev,
>  		pbus = of_match_bus(parent);
>  		pbus->count_cells(dev, &pna, &pns);
>  		if (!OF_CHECK_COUNTS(pna, pns)) {
> -			pr_err("Bad cell count for %s\n",
> -			       of_node_full_name(dev));
> +			pr_debug("Bad cell count for %s\n",
> +				 of_node_full_name(dev));
> +			*host = of_node_get(parent);
>  			break;
>  		}
I don't think here is the right place to fill *host. I think you want to return
the parent where the of_translate_one() failed for the 'ranges' property
missing. So, I think this seems better:

if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop)) {
			*host = of_node_get(dev);
			break;
}

>  
> @@ -609,7 +615,9 @@ static u64 __of_translate_address(struct device_node *dev,
>  		    pbus->name, pna, pns, of_node_full_name(parent));
>  
>  		/* Apply bus translation */
> -		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
> +		result = of_translate_one(dev, bus, pbus, addr, na, ns,
> +					  pna, rprop);
> +		if (result == OF_BAD_ADDR)
>  			break;
>  
>  		/* Complete the move up one level */
> @@ -628,13 +636,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);
>  
> @@ -676,29 +703,48 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
>  }
>  EXPORT_SYMBOL(of_get_address);
>  
> +extern unsigned long extio_translate(struct fwnode_handle *node, unsigned long offset);
> +
> +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 = extio_translate(&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;
>  
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index eda6a7cf0e54..320ab9fbf6af 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -3249,6 +3249,7 @@ EXPORT_SYMBOL(pci_request_regions_exclusive);
>  #ifdef PCI_IOBASE
>  struct io_range {
>  	struct list_head list;
> +	struct fwnode_handle *node;
>  	phys_addr_t start;
>  	resource_size_t size;
>  };
> @@ -3257,11 +3258,14 @@ static LIST_HEAD(io_range_list);
>  static DEFINE_SPINLOCK(io_range_lock);
>  #endif
>  
> +#define IO_RANGE_IOEXT (resource_size_t)(-1ull)
> +
>  /*
>   * 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 __weak pci_register_io_range(struct fwnode_handle *node, phys_addr_t addr,
> +				 resource_size_t size, unsigned long *port)
>  {
>  	int err = 0;
>  
> @@ -3272,7 +3276,12 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
>  	/* 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) {
> +		if (node == range->node)
> +			goto end_register;
> +
I don't think it is safe to only check the node had been registered. For
PCI/PCIE, there is only one I/O windows in bridge, it seems ok. But for non-pci
devices, such as ISA/LPC, I wonder it is possible there are several disjoint I/O
'ranges' entries...

What parameters are necessary for linux PIO allocation?
1) For those bus devices which have no MMIO( that is to say, indirectIO is
using),  I think 'addr' is not needed, but 'size' is mandatory;

I am thinking for our LPC, as there is no cpu address, we should not input
'addr' for the io range register. With 'size' as parameter, we implement a new
io range register function where can assign an unique linux PIO for this
register calling. The output linux PIO can allocate from a sub-range of whole
I/O space of [0, IO_SPACE_LIMIT]. This sub-range is specific for indirectIO, I
want to define a new macro, such as EXTIO_LIMIT, to represent the upper limit of
indirect IO space.

#if defined(CONFIG_PCI) && defined(CONFIG_INDIRECT_PIO)
#define EXTIO_LIMIT	PCIBIOS_MIN_IO
#elif defined(CONFIG_INDIRECT_PIO)
#define EXTIO_LIMIT	0x1000
#else
#define EXTIO_LIMIT 	0x00
#end

We should do some checkings to ensure EXTIO_LIMIT < IO_SPACE_LIMIT.

Then when someone call pci_register_io_range() or a new function for the linux
PIO register, we can allocate linux PIO from [0, EXTIO_LIMIT) for indirectIO
bus, from [EXTIO_LIMIT, IO_SPACE_LIMIT] for MMIO;

But there are issues confused me yet. For example, how to know the IO size for
the indirectIO bus? You known, there is no 'ranges' property for those buses....



2) For PCI MMIO, I think 'addr' is needed

As for the current pci_register_io_range()/pci_address_to_pio(), I have two doubts:

2.1) If there are multiple PCI host bridges which support I/O transaction, I
wonder whether the first host bridge can access the downstream devices with bus
I/O address in [0, PCIBIOS_MIN_IO)

for the first host bridge, pci_address_to_pio() will return a linux PIO range
start from 0.
But when calling __pci_assign_resource() to allocate the linux PIO for PCI/PCIE
devices/buses which are just children of first host bus, it can not allocate
linux PIO less than PCIBIOS_MIN_IO, which means kernel can not called in/out()
with port less than PCIBIOS_MIN_IO. But we had ioremap [PCI_IOBASE + 0,
PCI_IOBASE + size) to [pci_ioadd, pci_ioadd + size) before.


static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
		int resno, resource_size_t size, resource_size_t align)
{
	struct resource *res = dev->resource + resno;
	resource_size_t min;
	int ret;

	min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;


and in the later function:

static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
		resource_size_t size, resource_size_t align,
		resource_size_t min, unsigned long type_mask,
		resource_size_t (*alignf)(void *,

....
	pci_bus_for_each_resource(bus, r, i) {
		resource_size_t min_used = min;
....
		if (avail.start)
			min_used = avail.start;

		max = avail.end;

		/* Ok, try it out.. */
		ret = allocate_resource(r, res, size, min_used, max,
					align, alignf, alignf_data);

After allocate_resource(), a IO resource is allocated, but whose 'start' is not
less than min_used.( since avail.start is 0, min_used will keep the 'min'
without change to avail.start; Should be PCIBIOS_MIN_IO).

2.2) Is it possible the return linux PIO isn't page-aligned?

When calling pci_remap_iospace(const struct resource *res, phys_addr_t
phys_addr), if res->start is not page-aligned, it seems that
ioremap_page_range() will meet some issues for duplication iorempa for same
virtual page.

of-course, if we always configure the I/O ranges size as page-aligned, it will
be OK.

I found PowerPC will ensure the 'vaddress' and the 'size' are page-aligned
before ioremap, do we need to improve the current handling in
pci_register_io_range/pci_address_to_pio?


Thanks,
Zhichang
> +		if (addr != IO_RANGE_IOEXT &&
> +		    addr >= range->start &&
> +		    addr + size <= range->start + size) {
>  			/* range already registered, bail out */
>  			goto end_register;
>  		}
> @@ -3298,6 +3307,7 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
>  		goto end_register;
>  	}
>  
> +	range->node = node;
>  	range->start = addr;
>  	range->size = size;
>  
> @@ -3305,11 +3315,26 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
>  
>  end_register:
>  	spin_unlock(&io_range_lock);
> +
> +	*port = allocated_size;
> +#else
> +	/*
> +	 * powerpc and microblaze have their own registration,
> +	 * just look up the value here
> +	 */
> +	*port = pci_address_to_pio(addr);
>  #endif
>  
>  	return err;
>  }
>  
> +#ifdef CONFIG_IOEXT
> +int ioext_register_io_range
> +{
> +	return pci_register_io_range(node, IO_RANGE_IOEXT, size, port);
> +}
> +#endif
> +
>  phys_addr_t pci_pio_to_address(unsigned long pio)
>  {
>  	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 6bd94a803e8f..b7a8fa3da3ca 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1192,7 +1192,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 *node, phys_addr_t addr,
> +			  resource_size_t size, unsigned long *port);
>  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);
> 
> 
> .
> 

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-24  9:12                                                       ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-11-24  9:12 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, Arnd,

Thanks you very much!

To understand your idea more clear, I have some questions on your patch sketch.
Please check it below.


On 2016/11/24 7:23, Arnd Bergmann wrote:
> On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
>> On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni wrote:
>>> From: Arnd Bergmann [mailto:arnd at arndb.de]
>>>> On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
>>
>> Please don't proliferate the use of
>> pci_pio_to_address/pci_address_to_pio here, computing the physical
>> address from the logical address is trivial, you just need to
>> subtract the start of the range that you already use when matching
>> the port number range.
>>
>> The only thing we need here is to make of_address_to_resource()
>> return the correct logical port number that was registered for
>> a given host device when asked to translate an address that
>> does not have a CPU address associated with it.
> 
> Ok, I admit this was a little harder than I expected, but see below
> for a rough outline of how I think it can be done.
> 
> This makes it possible to translate bus specific I/O port numbers
> from device nodes into Linux port numbers, and gives a way to register
> them. We could take this further and completely remove pci_pio_to_address
> and pci_address_to_pio if we make the I/O port translation always
> go through the io_range list, looking up up the hostbridge by fwnode,
> but we don't have to do that now.
> 
> The patch is completely untested and probably buggy, it just seemed
> easier to put out a prototype than to keep going in circles with the
> discussion.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> 
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> index bf601d4df8cf..6cadf0501bb0 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 *node,
> +					struct resource_entry *entry)
>  {
>  #ifdef PCI_IOBASE
>  	struct resource *res = entry->res;
> @@ -739,11 +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))
> -		goto err;
> -
> -	port = pci_address_to_pio(cpu_addr);
> -	if (port == (unsigned long)-1)
> +	if (pci_register_io_range(node, cpu_addr, length, &port))
>  		goto err;
>  
>  	res->start = port;
> @@ -781,7 +778,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);

I think those changes in pci_root.c is only to match the new definition of
pci_register_io_range() and work for PCI I/O. It doesn't make sense for LPC, is
it right?


> diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
> index a50025a3777f..df96955a43f8 100644
> --- a/drivers/block/nbd.c
> +++ b/drivers/block/nbd.c
> @@ -760,8 +760,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
>  		set_bit(NBD_RUNNING, &nbd->runtime_flags);
>  		blk_mq_update_nr_hw_queues(&nbd->tag_set, nbd->num_connections);
>  		args = kcalloc(num_connections, sizeof(*args), GFP_KERNEL);
> -		if (!args)
> +		if (!args) {
> +			error = -ENOMEM;
>  			goto out_err;
> +		}
>  		nbd->task_recv = current;
>  		mutex_unlock(&nbd->config_lock);
>  
I think change here is none of the business.:)

> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903fe9d2..5decaba96eed 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -2,6 +2,7 @@
>  #define pr_fmt(fmt)	"OF: " fmt
>  
>  #include <linux/device.h>
> +#include <linux/fwnode.h>
>  #include <linux/io.h>
>  #include <linux/ioport.h>
>  #include <linux/module.h>
> @@ -323,14 +324,9 @@ 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, &port);
>  		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 {
>  		if ((sizeof(resource_size_t) < 8) &&
> @@ -479,7 +475,7 @@ static int of_empty_ranges_quirk(struct device_node *np)
>  	return false;
>  }
>  
> -static int of_translate_one(struct device_node *parent, struct of_bus *bus,
> +static u64 of_translate_one(struct device_node *parent, struct of_bus *bus,
>  			    struct of_bus *pbus, __be32 *addr,
>  			    int na, int ns, int pna, const char *rprop)
>  {
> @@ -507,7 +503,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>  	ranges = of_get_property(parent, rprop, &rlen);
>  	if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
>  		pr_debug("no ranges; cannot translate\n");
> -		return 1;
> +		return OF_BAD_ADDR;
>  	}
>  	if (ranges == NULL || rlen == 0) {
>  		offset = of_read_number(addr, na);
> @@ -528,7 +524,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>  	}
>  	if (offset == OF_BAD_ADDR) {
>  		pr_debug("not found !\n");
> -		return 1;
> +		return offset;
>  	}
>  	memcpy(addr, ranges + na, 4 * pna);
>  
> @@ -537,7 +533,10 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
>  	pr_debug("with offset: %llx\n", (unsigned long long)offset);
>  
>  	/* Translate it into parent bus space */
> -	return pbus->translate(addr, offset, pna);
> +	if (pbus->translate(addr, offset, pna))
> +		return OF_BAD_ADDR;
> +
> +	return offset;
>  }
>  
>  /*
> @@ -549,9 +548,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 lacks a tranlation, 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;
> @@ -564,6 +568,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)
> @@ -600,8 +605,9 @@ static u64 __of_translate_address(struct device_node *dev,
>  		pbus = of_match_bus(parent);
>  		pbus->count_cells(dev, &pna, &pns);
>  		if (!OF_CHECK_COUNTS(pna, pns)) {
> -			pr_err("Bad cell count for %s\n",
> -			       of_node_full_name(dev));
> +			pr_debug("Bad cell count for %s\n",
> +				 of_node_full_name(dev));
> +			*host = of_node_get(parent);
>  			break;
>  		}
I don't think here is the right place to fill *host. I think you want to return
the parent where the of_translate_one() failed for the 'ranges' property
missing. So, I think this seems better:

if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop)) {
			*host = of_node_get(dev);
			break;
}

>  
> @@ -609,7 +615,9 @@ static u64 __of_translate_address(struct device_node *dev,
>  		    pbus->name, pna, pns, of_node_full_name(parent));
>  
>  		/* Apply bus translation */
> -		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
> +		result = of_translate_one(dev, bus, pbus, addr, na, ns,
> +					  pna, rprop);
> +		if (result == OF_BAD_ADDR)
>  			break;
>  
>  		/* Complete the move up one level */
> @@ -628,13 +636,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);
>  
> @@ -676,29 +703,48 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
>  }
>  EXPORT_SYMBOL(of_get_address);
>  
> +extern unsigned long extio_translate(struct fwnode_handle *node, unsigned long offset);
> +
> +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 = extio_translate(&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;
>  
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index eda6a7cf0e54..320ab9fbf6af 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -3249,6 +3249,7 @@ EXPORT_SYMBOL(pci_request_regions_exclusive);
>  #ifdef PCI_IOBASE
>  struct io_range {
>  	struct list_head list;
> +	struct fwnode_handle *node;
>  	phys_addr_t start;
>  	resource_size_t size;
>  };
> @@ -3257,11 +3258,14 @@ static LIST_HEAD(io_range_list);
>  static DEFINE_SPINLOCK(io_range_lock);
>  #endif
>  
> +#define IO_RANGE_IOEXT (resource_size_t)(-1ull)
> +
>  /*
>   * 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 __weak pci_register_io_range(struct fwnode_handle *node, phys_addr_t addr,
> +				 resource_size_t size, unsigned long *port)
>  {
>  	int err = 0;
>  
> @@ -3272,7 +3276,12 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
>  	/* 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) {
> +		if (node == range->node)
> +			goto end_register;
> +
I don't think it is safe to only check the node had been registered. For
PCI/PCIE, there is only one I/O windows in bridge, it seems ok. But for non-pci
devices, such as ISA/LPC, I wonder it is possible there are several disjoint I/O
'ranges' entries...

What parameters are necessary for linux PIO allocation?
1) For those bus devices which have no MMIO( that is to say, indirectIO is
using),  I think 'addr' is not needed, but 'size' is mandatory;

I am thinking for our LPC, as there is no cpu address, we should not input
'addr' for the io range register. With 'size' as parameter, we implement a new
io range register function where can assign an unique linux PIO for this
register calling. The output linux PIO can allocate from a sub-range of whole
I/O space of [0, IO_SPACE_LIMIT]. This sub-range is specific for indirectIO, I
want to define a new macro, such as EXTIO_LIMIT, to represent the upper limit of
indirect IO space.

#if defined(CONFIG_PCI) && defined(CONFIG_INDIRECT_PIO)
#define EXTIO_LIMIT	PCIBIOS_MIN_IO
#elif defined(CONFIG_INDIRECT_PIO)
#define EXTIO_LIMIT	0x1000
#else
#define EXTIO_LIMIT 	0x00
#end

We should do some checkings to ensure EXTIO_LIMIT < IO_SPACE_LIMIT.

Then when someone call pci_register_io_range() or a new function for the linux
PIO register, we can allocate linux PIO from [0, EXTIO_LIMIT) for indirectIO
bus, from [EXTIO_LIMIT, IO_SPACE_LIMIT] for MMIO;

But there are issues confused me yet. For example, how to know the IO size for
the indirectIO bus? You known, there is no 'ranges' property for those buses....



2) For PCI MMIO, I think 'addr' is needed

As for the current pci_register_io_range()/pci_address_to_pio(), I have two doubts:

2.1) If there are multiple PCI host bridges which support I/O transaction, I
wonder whether the first host bridge can access the downstream devices with bus
I/O address in [0, PCIBIOS_MIN_IO)

for the first host bridge, pci_address_to_pio() will return a linux PIO range
start from 0.
But when calling __pci_assign_resource() to allocate the linux PIO for PCI/PCIE
devices/buses which are just children of first host bus, it can not allocate
linux PIO less than PCIBIOS_MIN_IO, which means kernel can not called in/out()
with port less than PCIBIOS_MIN_IO. But we had ioremap [PCI_IOBASE + 0,
PCI_IOBASE + size) to [pci_ioadd, pci_ioadd + size) before.


static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
		int resno, resource_size_t size, resource_size_t align)
{
	struct resource *res = dev->resource + resno;
	resource_size_t min;
	int ret;

	min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;


and in the later function:

static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
		resource_size_t size, resource_size_t align,
		resource_size_t min, unsigned long type_mask,
		resource_size_t (*alignf)(void *,

....
	pci_bus_for_each_resource(bus, r, i) {
		resource_size_t min_used = min;
....
		if (avail.start)
			min_used = avail.start;

		max = avail.end;

		/* Ok, try it out.. */
		ret = allocate_resource(r, res, size, min_used, max,
					align, alignf, alignf_data);

After allocate_resource(), a IO resource is allocated, but whose 'start' is not
less than min_used.( since avail.start is 0, min_used will keep the 'min'
without change to avail.start; Should be PCIBIOS_MIN_IO).

2.2) Is it possible the return linux PIO isn't page-aligned?

When calling pci_remap_iospace(const struct resource *res, phys_addr_t
phys_addr), if res->start is not page-aligned, it seems that
ioremap_page_range() will meet some issues for duplication iorempa for same
virtual page.

of-course, if we always configure the I/O ranges size as page-aligned, it will
be OK.

I found PowerPC will ensure the 'vaddress' and the 'size' are page-aligned
before ioremap, do we need to improve the current handling in
pci_register_io_range/pci_address_to_pio?


Thanks,
Zhichang
> +		if (addr != IO_RANGE_IOEXT &&
> +		    addr >= range->start &&
> +		    addr + size <= range->start + size) {
>  			/* range already registered, bail out */
>  			goto end_register;
>  		}
> @@ -3298,6 +3307,7 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
>  		goto end_register;
>  	}
>  
> +	range->node = node;
>  	range->start = addr;
>  	range->size = size;
>  
> @@ -3305,11 +3315,26 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
>  
>  end_register:
>  	spin_unlock(&io_range_lock);
> +
> +	*port = allocated_size;
> +#else
> +	/*
> +	 * powerpc and microblaze have their own registration,
> +	 * just look up the value here
> +	 */
> +	*port = pci_address_to_pio(addr);
>  #endif
>  
>  	return err;
>  }
>  
> +#ifdef CONFIG_IOEXT
> +int ioext_register_io_range
> +{
> +	return pci_register_io_range(node, IO_RANGE_IOEXT, size, port);
> +}
> +#endif
> +
>  phys_addr_t pci_pio_to_address(unsigned long pio)
>  {
>  	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 6bd94a803e8f..b7a8fa3da3ca 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1192,7 +1192,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 *node, phys_addr_t addr,
> +			  resource_size_t size, unsigned long *port);
>  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);
> 
> 
> .
> 

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-24  9:12                                                       ` zhichang.yuan
  (?)
  (?)
@ 2016-11-24 10:24                                                         ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-24 10:24 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: linux-arm-kernel, Gabriele Paoloni, mark.rutland,
	catalin.marinas, linux-pci, liviu.dudau, Linuxarm,
	lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, T homas Petazzoni, linux-serial, benh,
	devicetree, minyard, will.deacon, John Garry, olof, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02, linux-kernel,
	zourongrong

On Thursday, November 24, 2016 5:12:49 PM CET zhichang.yuan wrote:
> On 2016/11/24 7:23, Arnd Bergmann wrote:
> > On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> >> On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni wrote:
> >>> From: Arnd Bergmann [mailto:arnd@arndb.de]
> >>>> On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
> >>
> > @@ -781,7 +778,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);
> 
> I think those changes in pci_root.c is only to match the new definition of
> pci_register_io_range() and work for PCI I/O. It doesn't make sense for LPC, is
> it right?

Right, we wouldn't call acpi_pci_probe_root_resources() for LPC,
the change is just that we always pass the fwnode pointer to allow
matching based on that for any I/O space that does not have a
physical memory address associated with it.

I tried to keep this part general, so in theory that allows us to
have more than one I/O space without a CPU mapping, even though
we don't strictly need that for supporting your LPC controller.

> > diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
> > index a50025a3777f..df96955a43f8 100644
> > --- a/drivers/block/nbd.c
> > +++ b/drivers/block/nbd.c
> > @@ -760,8 +760,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
> >  		set_bit(NBD_RUNNING, &nbd->runtime_flags);
> >  		blk_mq_update_nr_hw_queues(&nbd->tag_set, nbd->num_connections);
> >  		args = kcalloc(num_connections, sizeof(*args), GFP_KERNEL);
> > -		if (!args)
> > +		if (!args) {
> > +			error = -ENOMEM;
> >  			goto out_err;
> > +		}
> >  		nbd->task_recv = current;
> >  		mutex_unlock(&nbd->config_lock);
> >  
> I think change here is none of the business.:)

Right, sorry about that, I forgot to commit this bugfix before looking
at the I/O space stuff.

> > +	*host = NULL;
> >  	/* Get parent & match bus type */
> >  	parent = of_get_parent(dev);
> >  	if (parent == NULL)
> > @@ -600,8 +605,9 @@ static u64 __of_translate_address(struct device_node *dev,
> >  		pbus = of_match_bus(parent);
> >  		pbus->count_cells(dev, &pna, &pns);
> >  		if (!OF_CHECK_COUNTS(pna, pns)) {
> > -			pr_err("Bad cell count for %s\n",
> > -			       of_node_full_name(dev));
> > +			pr_debug("Bad cell count for %s\n",
> > +				 of_node_full_name(dev));
> > +			*host = of_node_get(parent);
> >  			break;
> >  		}
> I don't think here is the right place to fill *host. I think you want to return
> the parent where the of_translate_one() failed for the 'ranges' property
> missing. So, I think this seems better:
> 
> if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop)) {
> 			*host = of_node_get(dev);
> 			break;
> }

You are right, I got the wrong place. The parent node will have 
a #address-cells but won't have ranges for the I/O space.

> > @@ -3272,7 +3276,12 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
> >  	/* 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) {
> > +		if (node == range->node)
> > +			goto end_register;
> > +
> I don't think it is safe to only check the node had been registered. For
> PCI/PCIE, there is only one I/O windows in bridge, it seems ok. But for non-pci
> devices, such as ISA/LPC, I wonder it is possible there are several disjoint I/O
> 'ranges' entries...

I think this part is completely safe, I can't imagine why you'd
have more than one range of I/O ports that have valid translations.

Do you have a specific example in mind where that would not be
the case, or are you just worried about the principle in general?

> What parameters are necessary for linux PIO allocation?
> 1) For those bus devices which have no MMIO( that is to say, indirectIO is
> using),  I think 'addr' is not needed, but 'size' is mandatory;

Agreed.

> I am thinking for our LPC, as there is no cpu address, we should not input
> 'addr' for the io range register. With 'size' as parameter, we implement a new
> io range register function where can assign an unique linux PIO for this
> register calling. The output linux PIO can allocate from a sub-range of whole
> I/O space of [0, IO_SPACE_LIMIT]. This sub-range is specific for indirectIO, I
> want to define a new macro, such as EXTIO_LIMIT, to represent the upper limit of
> indirect IO space.
> 
> #if defined(CONFIG_PCI) && defined(CONFIG_INDIRECT_PIO)
> #define EXTIO_LIMIT	PCIBIOS_MIN_IO
> #elif defined(CONFIG_INDIRECT_PIO)
> #define EXTIO_LIMIT	0x1000
> #else
> #define EXTIO_LIMIT 	0x00
> #end
> 
> We should do some checkings to ensure EXTIO_LIMIT < IO_SPACE_LIMIT.

I think we don't need to limit the EXTIO range at all. For your
specific case of LPC, we know it is limited, but my prototype
patch leaves this part generic enough to also allow using it
for a PCI host with indirect I/O space, and that can have a larger
size.

> Then when someone call pci_register_io_range() or a new function for the linux
> PIO register, we can allocate linux PIO from [0, EXTIO_LIMIT) for indirectIO
> bus, from [EXTIO_LIMIT, IO_SPACE_LIMIT] for MMIO;
> 
> But there are issues confused me yet. For example, how to know the IO size for
> the indirectIO bus? You known, there is no 'ranges' property for those buses....

Good point. We normally call pci_register_io_range() from
of_pci_range_to_resource and its ACPI equivalent.

When there is no ranges, we obviously won't call it, but there is
also no size associated with it. I think this is ok because
the host driver would already know the size based on the hardware
register layout, and it can just register that directly.

> 2) For PCI MMIO, I think 'addr' is needed

So far I assumed it was, but actually we can perhaps remove
the address if we manage to kill off pci_address_to_pio()
and pci_pio_to_address.

> As for the current pci_register_io_range()/pci_address_to_pio(), I have two doubts:
> 
> 2.1) If there are multiple PCI host bridges which support I/O transaction, I
> wonder whether the first host bridge can access the downstream devices with bus
> I/O address in [0, PCIBIOS_MIN_IO)
> 
> for the first host bridge, pci_address_to_pio() will return a linux PIO range
> start from 0.
> But when calling __pci_assign_resource() to allocate the linux PIO for PCI/PCIE
> devices/buses which are just children of first host bus, it can not allocate
> linux PIO less than PCIBIOS_MIN_IO, which means kernel can not called in/out()
> with port less than PCIBIOS_MIN_IO. But we had ioremap [PCI_IOBASE + 0,
> PCI_IOBASE + size) to [pci_ioadd, pci_ioadd + size) before.
> 
> 
> static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
> 		int resno, resource_size_t size, resource_size_t align)
> {
> 	struct resource *res = dev->resource + resno;
> 	resource_size_t min;
> 	int ret;
> 
> 	min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
> 
> 
> and in the later function:
> 
> static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
> 		resource_size_t size, resource_size_t align,
> 		resource_size_t min, unsigned long type_mask,
> 		resource_size_t (*alignf)(void *,
> 
> ....
> 	pci_bus_for_each_resource(bus, r, i) {
> 		resource_size_t min_used = min;
> ....
> 		if (avail.start)
> 			min_used = avail.start;
> 
> 		max = avail.end;
> 
> 		/* Ok, try it out.. */
> 		ret = allocate_resource(r, res, size, min_used, max,
> 					align, alignf, alignf_data);
> 
> After allocate_resource(), a IO resource is allocated, but whose 'start' is not
> less than min_used.( since avail.start is 0, min_used will keep the 'min'
> without change to avail.start; Should be PCIBIOS_MIN_IO).

I'm not completely sure I'm following here. Generally speaking, addresses
below PCIBIOS_MIN_IO are intended for PCI-ISA bridges and PCI devices with
hardcoded port numbers for ISA compatibility, while __pci_assign_resource
is meant to do dynamic assignment of I/O resources above PCIBIOS_MIN_IO
so it does not conflict with the legacy ISA ports.

Does that address your concern?

> 2.2) Is it possible the return linux PIO isn't page-aligned?
> 
> When calling pci_remap_iospace(const struct resource *res, phys_addr_t
> phys_addr), if res->start is not page-aligned, it seems that
> ioremap_page_range() will meet some issues for duplication iorempa for same
> virtual page.
> 
> of-course, if we always configure the I/O ranges size as page-aligned, it will
> be OK.
> 
> I found PowerPC will ensure the 'vaddress' and the 'size' are page-aligned
> before ioremap, do we need to improve the current handling in
> pci_register_io_range/pci_address_to_pio?

I think it would be a good idea to enforce page-alignment here, even
though everything could still work if it's not page-aligned.

The requirement for ioremap_page_range() is that the offset within
a page must be the same for the virtual and physical addresses.

Adding page-alignment to pci_register_io_range() could be an enhancement
that we can do independent of the other patches.

Thanks a lot for your detailed analysis and feedback.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-24 10:24                                                         ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-24 10:24 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: mark.rutland, Gabriele Paoloni, benh, liviu.dudau, Linuxarm,
	lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, T homas Petazzoni, linux-serial,
	catalin.marinas, devicetree, minyard, will.deacon, John Garry,
	zourongrong, robh+dt, bhelgaas@go og le.com, kantyzc

On Thursday, November 24, 2016 5:12:49 PM CET zhichang.yuan wrote:
> On 2016/11/24 7:23, Arnd Bergmann wrote:
> > On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> >> On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni wrote:
> >>> From: Arnd Bergmann [mailto:arnd@arndb.de]
> >>>> On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
> >>
> > @@ -781,7 +778,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);
> 
> I think those changes in pci_root.c is only to match the new definition of
> pci_register_io_range() and work for PCI I/O. It doesn't make sense for LPC, is
> it right?

Right, we wouldn't call acpi_pci_probe_root_resources() for LPC,
the change is just that we always pass the fwnode pointer to allow
matching based on that for any I/O space that does not have a
physical memory address associated with it.

I tried to keep this part general, so in theory that allows us to
have more than one I/O space without a CPU mapping, even though
we don't strictly need that for supporting your LPC controller.

> > diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
> > index a50025a3777f..df96955a43f8 100644
> > --- a/drivers/block/nbd.c
> > +++ b/drivers/block/nbd.c
> > @@ -760,8 +760,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
> >  		set_bit(NBD_RUNNING, &nbd->runtime_flags);
> >  		blk_mq_update_nr_hw_queues(&nbd->tag_set, nbd->num_connections);
> >  		args = kcalloc(num_connections, sizeof(*args), GFP_KERNEL);
> > -		if (!args)
> > +		if (!args) {
> > +			error = -ENOMEM;
> >  			goto out_err;
> > +		}
> >  		nbd->task_recv = current;
> >  		mutex_unlock(&nbd->config_lock);
> >  
> I think change here is none of the business.:)

Right, sorry about that, I forgot to commit this bugfix before looking
at the I/O space stuff.

> > +	*host = NULL;
> >  	/* Get parent & match bus type */
> >  	parent = of_get_parent(dev);
> >  	if (parent == NULL)
> > @@ -600,8 +605,9 @@ static u64 __of_translate_address(struct device_node *dev,
> >  		pbus = of_match_bus(parent);
> >  		pbus->count_cells(dev, &pna, &pns);
> >  		if (!OF_CHECK_COUNTS(pna, pns)) {
> > -			pr_err("Bad cell count for %s\n",
> > -			       of_node_full_name(dev));
> > +			pr_debug("Bad cell count for %s\n",
> > +				 of_node_full_name(dev));
> > +			*host = of_node_get(parent);
> >  			break;
> >  		}
> I don't think here is the right place to fill *host. I think you want to return
> the parent where the of_translate_one() failed for the 'ranges' property
> missing. So, I think this seems better:
> 
> if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop)) {
> 			*host = of_node_get(dev);
> 			break;
> }

You are right, I got the wrong place. The parent node will have 
a #address-cells but won't have ranges for the I/O space.

> > @@ -3272,7 +3276,12 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
> >  	/* 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) {
> > +		if (node == range->node)
> > +			goto end_register;
> > +
> I don't think it is safe to only check the node had been registered. For
> PCI/PCIE, there is only one I/O windows in bridge, it seems ok. But for non-pci
> devices, such as ISA/LPC, I wonder it is possible there are several disjoint I/O
> 'ranges' entries...

I think this part is completely safe, I can't imagine why you'd
have more than one range of I/O ports that have valid translations.

Do you have a specific example in mind where that would not be
the case, or are you just worried about the principle in general?

> What parameters are necessary for linux PIO allocation?
> 1) For those bus devices which have no MMIO( that is to say, indirectIO is
> using),  I think 'addr' is not needed, but 'size' is mandatory;

Agreed.

> I am thinking for our LPC, as there is no cpu address, we should not input
> 'addr' for the io range register. With 'size' as parameter, we implement a new
> io range register function where can assign an unique linux PIO for this
> register calling. The output linux PIO can allocate from a sub-range of whole
> I/O space of [0, IO_SPACE_LIMIT]. This sub-range is specific for indirectIO, I
> want to define a new macro, such as EXTIO_LIMIT, to represent the upper limit of
> indirect IO space.
> 
> #if defined(CONFIG_PCI) && defined(CONFIG_INDIRECT_PIO)
> #define EXTIO_LIMIT	PCIBIOS_MIN_IO
> #elif defined(CONFIG_INDIRECT_PIO)
> #define EXTIO_LIMIT	0x1000
> #else
> #define EXTIO_LIMIT 	0x00
> #end
> 
> We should do some checkings to ensure EXTIO_LIMIT < IO_SPACE_LIMIT.

I think we don't need to limit the EXTIO range at all. For your
specific case of LPC, we know it is limited, but my prototype
patch leaves this part generic enough to also allow using it
for a PCI host with indirect I/O space, and that can have a larger
size.

> Then when someone call pci_register_io_range() or a new function for the linux
> PIO register, we can allocate linux PIO from [0, EXTIO_LIMIT) for indirectIO
> bus, from [EXTIO_LIMIT, IO_SPACE_LIMIT] for MMIO;
> 
> But there are issues confused me yet. For example, how to know the IO size for
> the indirectIO bus? You known, there is no 'ranges' property for those buses....

Good point. We normally call pci_register_io_range() from
of_pci_range_to_resource and its ACPI equivalent.

When there is no ranges, we obviously won't call it, but there is
also no size associated with it. I think this is ok because
the host driver would already know the size based on the hardware
register layout, and it can just register that directly.

> 2) For PCI MMIO, I think 'addr' is needed

So far I assumed it was, but actually we can perhaps remove
the address if we manage to kill off pci_address_to_pio()
and pci_pio_to_address.

> As for the current pci_register_io_range()/pci_address_to_pio(), I have two doubts:
> 
> 2.1) If there are multiple PCI host bridges which support I/O transaction, I
> wonder whether the first host bridge can access the downstream devices with bus
> I/O address in [0, PCIBIOS_MIN_IO)
> 
> for the first host bridge, pci_address_to_pio() will return a linux PIO range
> start from 0.
> But when calling __pci_assign_resource() to allocate the linux PIO for PCI/PCIE
> devices/buses which are just children of first host bus, it can not allocate
> linux PIO less than PCIBIOS_MIN_IO, which means kernel can not called in/out()
> with port less than PCIBIOS_MIN_IO. But we had ioremap [PCI_IOBASE + 0,
> PCI_IOBASE + size) to [pci_ioadd, pci_ioadd + size) before.
> 
> 
> static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
> 		int resno, resource_size_t size, resource_size_t align)
> {
> 	struct resource *res = dev->resource + resno;
> 	resource_size_t min;
> 	int ret;
> 
> 	min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
> 
> 
> and in the later function:
> 
> static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
> 		resource_size_t size, resource_size_t align,
> 		resource_size_t min, unsigned long type_mask,
> 		resource_size_t (*alignf)(void *,
> 
> ....
> 	pci_bus_for_each_resource(bus, r, i) {
> 		resource_size_t min_used = min;
> ....
> 		if (avail.start)
> 			min_used = avail.start;
> 
> 		max = avail.end;
> 
> 		/* Ok, try it out.. */
> 		ret = allocate_resource(r, res, size, min_used, max,
> 					align, alignf, alignf_data);
> 
> After allocate_resource(), a IO resource is allocated, but whose 'start' is not
> less than min_used.( since avail.start is 0, min_used will keep the 'min'
> without change to avail.start; Should be PCIBIOS_MIN_IO).

I'm not completely sure I'm following here. Generally speaking, addresses
below PCIBIOS_MIN_IO are intended for PCI-ISA bridges and PCI devices with
hardcoded port numbers for ISA compatibility, while __pci_assign_resource
is meant to do dynamic assignment of I/O resources above PCIBIOS_MIN_IO
so it does not conflict with the legacy ISA ports.

Does that address your concern?

> 2.2) Is it possible the return linux PIO isn't page-aligned?
> 
> When calling pci_remap_iospace(const struct resource *res, phys_addr_t
> phys_addr), if res->start is not page-aligned, it seems that
> ioremap_page_range() will meet some issues for duplication iorempa for same
> virtual page.
> 
> of-course, if we always configure the I/O ranges size as page-aligned, it will
> be OK.
> 
> I found PowerPC will ensure the 'vaddress' and the 'size' are page-aligned
> before ioremap, do we need to improve the current handling in
> pci_register_io_range/pci_address_to_pio?

I think it would be a good idea to enforce page-alignment here, even
though everything could still work if it's not page-aligned.

The requirement for ioremap_page_range() is that the offset within
a page must be the same for the virtual and physical addresses.

Adding page-alignment to pci_register_io_range() could be an enhancement
that we can do independent of the other patches.

Thanks a lot for your detailed analysis and feedback.

	Arnd

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-24 10:24                                                         ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-24 10:24 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: mark.rutland, Gabriele Paoloni, benh, liviu.dudau, Linuxarm,
	lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, T homas Petazzoni, linux-serial,
	catalin.marinas, devicetree, minyard, will.deacon, John Garry,
	zourongrong, robh+dt, bhelgaas@go og le.com, kantyzc,
	zhichang.yuan02, linux-arm-kernel, linux-pci, linux-kernel, olof

On Thursday, November 24, 2016 5:12:49 PM CET zhichang.yuan wrote:
> On 2016/11/24 7:23, Arnd Bergmann wrote:
> > On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> >> On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni wrote:
> >>> From: Arnd Bergmann [mailto:arnd@arndb.de]
> >>>> On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
> >>
> > @@ -781,7 +778,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);
> 
> I think those changes in pci_root.c is only to match the new definition of
> pci_register_io_range() and work for PCI I/O. It doesn't make sense for LPC, is
> it right?

Right, we wouldn't call acpi_pci_probe_root_resources() for LPC,
the change is just that we always pass the fwnode pointer to allow
matching based on that for any I/O space that does not have a
physical memory address associated with it.

I tried to keep this part general, so in theory that allows us to
have more than one I/O space without a CPU mapping, even though
we don't strictly need that for supporting your LPC controller.

> > diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
> > index a50025a3777f..df96955a43f8 100644
> > --- a/drivers/block/nbd.c
> > +++ b/drivers/block/nbd.c
> > @@ -760,8 +760,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
> >  		set_bit(NBD_RUNNING, &nbd->runtime_flags);
> >  		blk_mq_update_nr_hw_queues(&nbd->tag_set, nbd->num_connections);
> >  		args = kcalloc(num_connections, sizeof(*args), GFP_KERNEL);
> > -		if (!args)
> > +		if (!args) {
> > +			error = -ENOMEM;
> >  			goto out_err;
> > +		}
> >  		nbd->task_recv = current;
> >  		mutex_unlock(&nbd->config_lock);
> >  
> I think change here is none of the business.:)

Right, sorry about that, I forgot to commit this bugfix before looking
at the I/O space stuff.

> > +	*host = NULL;
> >  	/* Get parent & match bus type */
> >  	parent = of_get_parent(dev);
> >  	if (parent == NULL)
> > @@ -600,8 +605,9 @@ static u64 __of_translate_address(struct device_node *dev,
> >  		pbus = of_match_bus(parent);
> >  		pbus->count_cells(dev, &pna, &pns);
> >  		if (!OF_CHECK_COUNTS(pna, pns)) {
> > -			pr_err("Bad cell count for %s\n",
> > -			       of_node_full_name(dev));
> > +			pr_debug("Bad cell count for %s\n",
> > +				 of_node_full_name(dev));
> > +			*host = of_node_get(parent);
> >  			break;
> >  		}
> I don't think here is the right place to fill *host. I think you want to return
> the parent where the of_translate_one() failed for the 'ranges' property
> missing. So, I think this seems better:
> 
> if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop)) {
> 			*host = of_node_get(dev);
> 			break;
> }

You are right, I got the wrong place. The parent node will have 
a #address-cells but won't have ranges for the I/O space.

> > @@ -3272,7 +3276,12 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
> >  	/* 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) {
> > +		if (node == range->node)
> > +			goto end_register;
> > +
> I don't think it is safe to only check the node had been registered. For
> PCI/PCIE, there is only one I/O windows in bridge, it seems ok. But for non-pci
> devices, such as ISA/LPC, I wonder it is possible there are several disjoint I/O
> 'ranges' entries...

I think this part is completely safe, I can't imagine why you'd
have more than one range of I/O ports that have valid translations.

Do you have a specific example in mind where that would not be
the case, or are you just worried about the principle in general?

> What parameters are necessary for linux PIO allocation?
> 1) For those bus devices which have no MMIO( that is to say, indirectIO is
> using),  I think 'addr' is not needed, but 'size' is mandatory;

Agreed.

> I am thinking for our LPC, as there is no cpu address, we should not input
> 'addr' for the io range register. With 'size' as parameter, we implement a new
> io range register function where can assign an unique linux PIO for this
> register calling. The output linux PIO can allocate from a sub-range of whole
> I/O space of [0, IO_SPACE_LIMIT]. This sub-range is specific for indirectIO, I
> want to define a new macro, such as EXTIO_LIMIT, to represent the upper limit of
> indirect IO space.
> 
> #if defined(CONFIG_PCI) && defined(CONFIG_INDIRECT_PIO)
> #define EXTIO_LIMIT	PCIBIOS_MIN_IO
> #elif defined(CONFIG_INDIRECT_PIO)
> #define EXTIO_LIMIT	0x1000
> #else
> #define EXTIO_LIMIT 	0x00
> #end
> 
> We should do some checkings to ensure EXTIO_LIMIT < IO_SPACE_LIMIT.

I think we don't need to limit the EXTIO range at all. For your
specific case of LPC, we know it is limited, but my prototype
patch leaves this part generic enough to also allow using it
for a PCI host with indirect I/O space, and that can have a larger
size.

> Then when someone call pci_register_io_range() or a new function for the linux
> PIO register, we can allocate linux PIO from [0, EXTIO_LIMIT) for indirectIO
> bus, from [EXTIO_LIMIT, IO_SPACE_LIMIT] for MMIO;
> 
> But there are issues confused me yet. For example, how to know the IO size for
> the indirectIO bus? You known, there is no 'ranges' property for those buses....

Good point. We normally call pci_register_io_range() from
of_pci_range_to_resource and its ACPI equivalent.

When there is no ranges, we obviously won't call it, but there is
also no size associated with it. I think this is ok because
the host driver would already know the size based on the hardware
register layout, and it can just register that directly.

> 2) For PCI MMIO, I think 'addr' is needed

So far I assumed it was, but actually we can perhaps remove
the address if we manage to kill off pci_address_to_pio()
and pci_pio_to_address.

> As for the current pci_register_io_range()/pci_address_to_pio(), I have two doubts:
> 
> 2.1) If there are multiple PCI host bridges which support I/O transaction, I
> wonder whether the first host bridge can access the downstream devices with bus
> I/O address in [0, PCIBIOS_MIN_IO)
> 
> for the first host bridge, pci_address_to_pio() will return a linux PIO range
> start from 0.
> But when calling __pci_assign_resource() to allocate the linux PIO for PCI/PCIE
> devices/buses which are just children of first host bus, it can not allocate
> linux PIO less than PCIBIOS_MIN_IO, which means kernel can not called in/out()
> with port less than PCIBIOS_MIN_IO. But we had ioremap [PCI_IOBASE + 0,
> PCI_IOBASE + size) to [pci_ioadd, pci_ioadd + size) before.
> 
> 
> static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
> 		int resno, resource_size_t size, resource_size_t align)
> {
> 	struct resource *res = dev->resource + resno;
> 	resource_size_t min;
> 	int ret;
> 
> 	min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
> 
> 
> and in the later function:
> 
> static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
> 		resource_size_t size, resource_size_t align,
> 		resource_size_t min, unsigned long type_mask,
> 		resource_size_t (*alignf)(void *,
> 
> ....
> 	pci_bus_for_each_resource(bus, r, i) {
> 		resource_size_t min_used = min;
> ....
> 		if (avail.start)
> 			min_used = avail.start;
> 
> 		max = avail.end;
> 
> 		/* Ok, try it out.. */
> 		ret = allocate_resource(r, res, size, min_used, max,
> 					align, alignf, alignf_data);
> 
> After allocate_resource(), a IO resource is allocated, but whose 'start' is not
> less than min_used.( since avail.start is 0, min_used will keep the 'min'
> without change to avail.start; Should be PCIBIOS_MIN_IO).

I'm not completely sure I'm following here. Generally speaking, addresses
below PCIBIOS_MIN_IO are intended for PCI-ISA bridges and PCI devices with
hardcoded port numbers for ISA compatibility, while __pci_assign_resource
is meant to do dynamic assignment of I/O resources above PCIBIOS_MIN_IO
so it does not conflict with the legacy ISA ports.

Does that address your concern?

> 2.2) Is it possible the return linux PIO isn't page-aligned?
> 
> When calling pci_remap_iospace(const struct resource *res, phys_addr_t
> phys_addr), if res->start is not page-aligned, it seems that
> ioremap_page_range() will meet some issues for duplication iorempa for same
> virtual page.
> 
> of-course, if we always configure the I/O ranges size as page-aligned, it will
> be OK.
> 
> I found PowerPC will ensure the 'vaddress' and the 'size' are page-aligned
> before ioremap, do we need to improve the current handling in
> pci_register_io_range/pci_address_to_pio?

I think it would be a good idea to enforce page-alignment here, even
though everything could still work if it's not page-aligned.

The requirement for ioremap_page_range() is that the offset within
a page must be the same for the virtual and physical addresses.

Adding page-alignment to pci_register_io_range() could be an enhancement
that we can do independent of the other patches.

Thanks a lot for your detailed analysis and feedback.

	Arnd

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-24 10:24                                                         ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-24 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday, November 24, 2016 5:12:49 PM CET zhichang.yuan wrote:
> On 2016/11/24 7:23, Arnd Bergmann wrote:
> > On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> >> On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni wrote:
> >>> From: Arnd Bergmann [mailto:arnd at arndb.de]
> >>>> On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
> >>
> > @@ -781,7 +778,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);
> 
> I think those changes in pci_root.c is only to match the new definition of
> pci_register_io_range() and work for PCI I/O. It doesn't make sense for LPC, is
> it right?

Right, we wouldn't call acpi_pci_probe_root_resources() for LPC,
the change is just that we always pass the fwnode pointer to allow
matching based on that for any I/O space that does not have a
physical memory address associated with it.

I tried to keep this part general, so in theory that allows us to
have more than one I/O space without a CPU mapping, even though
we don't strictly need that for supporting your LPC controller.

> > diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
> > index a50025a3777f..df96955a43f8 100644
> > --- a/drivers/block/nbd.c
> > +++ b/drivers/block/nbd.c
> > @@ -760,8 +760,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
> >  		set_bit(NBD_RUNNING, &nbd->runtime_flags);
> >  		blk_mq_update_nr_hw_queues(&nbd->tag_set, nbd->num_connections);
> >  		args = kcalloc(num_connections, sizeof(*args), GFP_KERNEL);
> > -		if (!args)
> > +		if (!args) {
> > +			error = -ENOMEM;
> >  			goto out_err;
> > +		}
> >  		nbd->task_recv = current;
> >  		mutex_unlock(&nbd->config_lock);
> >  
> I think change here is none of the business.:)

Right, sorry about that, I forgot to commit this bugfix before looking
at the I/O space stuff.

> > +	*host = NULL;
> >  	/* Get parent & match bus type */
> >  	parent = of_get_parent(dev);
> >  	if (parent == NULL)
> > @@ -600,8 +605,9 @@ static u64 __of_translate_address(struct device_node *dev,
> >  		pbus = of_match_bus(parent);
> >  		pbus->count_cells(dev, &pna, &pns);
> >  		if (!OF_CHECK_COUNTS(pna, pns)) {
> > -			pr_err("Bad cell count for %s\n",
> > -			       of_node_full_name(dev));
> > +			pr_debug("Bad cell count for %s\n",
> > +				 of_node_full_name(dev));
> > +			*host = of_node_get(parent);
> >  			break;
> >  		}
> I don't think here is the right place to fill *host. I think you want to return
> the parent where the of_translate_one() failed for the 'ranges' property
> missing. So, I think this seems better:
> 
> if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop)) {
> 			*host = of_node_get(dev);
> 			break;
> }

You are right, I got the wrong place. The parent node will have 
a #address-cells but won't have ranges for the I/O space.

> > @@ -3272,7 +3276,12 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
> >  	/* 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) {
> > +		if (node == range->node)
> > +			goto end_register;
> > +
> I don't think it is safe to only check the node had been registered. For
> PCI/PCIE, there is only one I/O windows in bridge, it seems ok. But for non-pci
> devices, such as ISA/LPC, I wonder it is possible there are several disjoint I/O
> 'ranges' entries...

I think this part is completely safe, I can't imagine why you'd
have more than one range of I/O ports that have valid translations.

Do you have a specific example in mind where that would not be
the case, or are you just worried about the principle in general?

> What parameters are necessary for linux PIO allocation?
> 1) For those bus devices which have no MMIO( that is to say, indirectIO is
> using),  I think 'addr' is not needed, but 'size' is mandatory;

Agreed.

> I am thinking for our LPC, as there is no cpu address, we should not input
> 'addr' for the io range register. With 'size' as parameter, we implement a new
> io range register function where can assign an unique linux PIO for this
> register calling. The output linux PIO can allocate from a sub-range of whole
> I/O space of [0, IO_SPACE_LIMIT]. This sub-range is specific for indirectIO, I
> want to define a new macro, such as EXTIO_LIMIT, to represent the upper limit of
> indirect IO space.
> 
> #if defined(CONFIG_PCI) && defined(CONFIG_INDIRECT_PIO)
> #define EXTIO_LIMIT	PCIBIOS_MIN_IO
> #elif defined(CONFIG_INDIRECT_PIO)
> #define EXTIO_LIMIT	0x1000
> #else
> #define EXTIO_LIMIT 	0x00
> #end
> 
> We should do some checkings to ensure EXTIO_LIMIT < IO_SPACE_LIMIT.

I think we don't need to limit the EXTIO range@all. For your
specific case of LPC, we know it is limited, but my prototype
patch leaves this part generic enough to also allow using it
for a PCI host with indirect I/O space, and that can have a larger
size.

> Then when someone call pci_register_io_range() or a new function for the linux
> PIO register, we can allocate linux PIO from [0, EXTIO_LIMIT) for indirectIO
> bus, from [EXTIO_LIMIT, IO_SPACE_LIMIT] for MMIO;
> 
> But there are issues confused me yet. For example, how to know the IO size for
> the indirectIO bus? You known, there is no 'ranges' property for those buses....

Good point. We normally call pci_register_io_range() from
of_pci_range_to_resource and its ACPI equivalent.

When there is no ranges, we obviously won't call it, but there is
also no size associated with it. I think this is ok because
the host driver would already know the size based on the hardware
register layout, and it can just register that directly.

> 2) For PCI MMIO, I think 'addr' is needed

So far I assumed it was, but actually we can perhaps remove
the address if we manage to kill off pci_address_to_pio()
and pci_pio_to_address.

> As for the current pci_register_io_range()/pci_address_to_pio(), I have two doubts:
> 
> 2.1) If there are multiple PCI host bridges which support I/O transaction, I
> wonder whether the first host bridge can access the downstream devices with bus
> I/O address in [0, PCIBIOS_MIN_IO)
> 
> for the first host bridge, pci_address_to_pio() will return a linux PIO range
> start from 0.
> But when calling __pci_assign_resource() to allocate the linux PIO for PCI/PCIE
> devices/buses which are just children of first host bus, it can not allocate
> linux PIO less than PCIBIOS_MIN_IO, which means kernel can not called in/out()
> with port less than PCIBIOS_MIN_IO. But we had ioremap [PCI_IOBASE + 0,
> PCI_IOBASE + size) to [pci_ioadd, pci_ioadd + size) before.
> 
> 
> static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
> 		int resno, resource_size_t size, resource_size_t align)
> {
> 	struct resource *res = dev->resource + resno;
> 	resource_size_t min;
> 	int ret;
> 
> 	min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
> 
> 
> and in the later function:
> 
> static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
> 		resource_size_t size, resource_size_t align,
> 		resource_size_t min, unsigned long type_mask,
> 		resource_size_t (*alignf)(void *,
> 
> ....
> 	pci_bus_for_each_resource(bus, r, i) {
> 		resource_size_t min_used = min;
> ....
> 		if (avail.start)
> 			min_used = avail.start;
> 
> 		max = avail.end;
> 
> 		/* Ok, try it out.. */
> 		ret = allocate_resource(r, res, size, min_used, max,
> 					align, alignf, alignf_data);
> 
> After allocate_resource(), a IO resource is allocated, but whose 'start' is not
> less than min_used.( since avail.start is 0, min_used will keep the 'min'
> without change to avail.start; Should be PCIBIOS_MIN_IO).

I'm not completely sure I'm following here. Generally speaking, addresses
below PCIBIOS_MIN_IO are intended for PCI-ISA bridges and PCI devices with
hardcoded port numbers for ISA compatibility, while __pci_assign_resource
is meant to do dynamic assignment of I/O resources above PCIBIOS_MIN_IO
so it does not conflict with the legacy ISA ports.

Does that address your concern?

> 2.2) Is it possible the return linux PIO isn't page-aligned?
> 
> When calling pci_remap_iospace(const struct resource *res, phys_addr_t
> phys_addr), if res->start is not page-aligned, it seems that
> ioremap_page_range() will meet some issues for duplication iorempa for same
> virtual page.
> 
> of-course, if we always configure the I/O ranges size as page-aligned, it will
> be OK.
> 
> I found PowerPC will ensure the 'vaddress' and the 'size' are page-aligned
> before ioremap, do we need to improve the current handling in
> pci_register_io_range/pci_address_to_pio?

I think it would be a good idea to enforce page-alignment here, even
though everything could still work if it's not page-aligned.

The requirement for ioremap_page_range() is that the offset within
a page must be the same for the virtual and physical addresses.

Adding page-alignment to pci_register_io_range() could be an enhancement
that we can do independent of the other patches.

Thanks a lot for your detailed analysis and feedback.

	Arnd

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-23 23:23                                                     ` Arnd Bergmann
  (?)
  (?)
@ 2016-11-25  8:46                                                       ` Gabriele Paoloni
  -1 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-25  8:46 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: mark.rutland, catalin.marinas, linux-pci, liviu.dudau, Linuxarm,
	lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, T homas Petazzoni, linux-serial, benh,
	devicetree, minyard, will.deacon, John Garry, olof, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02, linux-kernel,
	Yuanzhichang, zourongrong

Hi Arnd

Many thanks for your contribution, much appreciated

I have some comments...see inline below 

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 23 November 2016 23:23
> To: linux-arm-kernel@lists.infradead.org
> Cc: Gabriele Paoloni; mark.rutland@arm.com; catalin.marinas@arm.com;
> linux-pci@vger.kernel.org; liviu.dudau@arm.com; Linuxarm;
> lorenzo.pieralisi@arm.com; xuwei (O); Jason Gunthorpe; T homas
> Petazzoni; linux-serial@vger.kernel.org; benh@kernel.crashing.org;
> devicetree@vger.kernel.org; minyard@acm.org; will.deacon@arm.com; John
> Garry; olof@lixom.net; robh+dt@kernel.org; bhelgaas@go og le.com;
> kantyzc@163.com; zhichang.yuan02@gmail.com; linux-
> kernel@vger.kernel.org; Yuanzhichang; zourongrong@gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> > On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni
> wrote:
> > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni
> wrote:
> >
> > Please don't proliferate the use of
> > pci_pio_to_address/pci_address_to_pio here, computing the physical
> > address from the logical address is trivial, you just need to
> > subtract the start of the range that you already use when matching
> > the port number range.
> >
> > The only thing we need here is to make of_address_to_resource()
> > return the correct logical port number that was registered for
> > a given host device when asked to translate an address that
> > does not have a CPU address associated with it.
> 
> Ok, I admit this was a little harder than I expected, but see below
> for a rough outline of how I think it can be done.
> 
> This makes it possible to translate bus specific I/O port numbers
> from device nodes into Linux port numbers, and gives a way to register
> them. We could take this further and completely remove
> pci_pio_to_address
> and pci_address_to_pio if we make the I/O port translation always
> go through the io_range list, looking up up the hostbridge by fwnode,
> but we don't have to do that now.
> 
> The patch is completely untested and probably buggy, it just seemed
> easier to put out a prototype than to keep going in circles with the
> discussion.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> 
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> index bf601d4df8cf..6cadf0501bb0 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 *node,
> +					struct resource_entry *entry)
>  {
>  #ifdef PCI_IOBASE
>  	struct resource *res = entry->res;
> @@ -739,11 +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))
> -		goto err;
> -
> -	port = pci_address_to_pio(cpu_addr);
> -	if (port == (unsigned long)-1)
> +	if (pci_register_io_range(node, cpu_addr, length, &port))
>  		goto err;
> 
>  	res->start = port;
> @@ -781,7 +778,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/block/nbd.c b/drivers/block/nbd.c
> index a50025a3777f..df96955a43f8 100644
> --- a/drivers/block/nbd.c
> +++ b/drivers/block/nbd.c
> @@ -760,8 +760,10 @@ static int __nbd_ioctl(struct block_device *bdev,
> struct nbd_device *nbd,
>  		set_bit(NBD_RUNNING, &nbd->runtime_flags);
>  		blk_mq_update_nr_hw_queues(&nbd->tag_set, nbd-
> >num_connections);
>  		args = kcalloc(num_connections, sizeof(*args), GFP_KERNEL);
> -		if (!args)
> +		if (!args) {
> +			error = -ENOMEM;
>  			goto out_err;
> +		}
>  		nbd->task_recv = current;
>  		mutex_unlock(&nbd->config_lock);
> 
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903fe9d2..5decaba96eed 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -2,6 +2,7 @@
>  #define pr_fmt(fmt)	"OF: " fmt
> 
>  #include <linux/device.h>
> +#include <linux/fwnode.h>
>  #include <linux/io.h>
>  #include <linux/ioport.h>
>  #include <linux/module.h>
> @@ -323,14 +324,9 @@ 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, &port);
>  		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 {
>  		if ((sizeof(resource_size_t) < 8) &&
> @@ -479,7 +475,7 @@ static int of_empty_ranges_quirk(struct device_node
> *np)
>  	return false;
>  }
> 
> -static int of_translate_one(struct device_node *parent, struct of_bus
> *bus,
> +static u64 of_translate_one(struct device_node *parent, struct of_bus
> *bus,
>  			    struct of_bus *pbus, __be32 *addr,
>  			    int na, int ns, int pna, const char *rprop)
>  {
> @@ -507,7 +503,7 @@ static int of_translate_one(struct device_node
> *parent, struct of_bus *bus,
>  	ranges = of_get_property(parent, rprop, &rlen);
>  	if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
>  		pr_debug("no ranges; cannot translate\n");
> -		return 1;
> +		return OF_BAD_ADDR;
>  	}
>  	if (ranges == NULL || rlen == 0) {
>  		offset = of_read_number(addr, na);
> @@ -528,7 +524,7 @@ static int of_translate_one(struct device_node
> *parent, struct of_bus *bus,
>  	}
>  	if (offset == OF_BAD_ADDR) {
>  		pr_debug("not found !\n");
> -		return 1;
> +		return offset;
>  	}
>  	memcpy(addr, ranges + na, 4 * pna);
> 
> @@ -537,7 +533,10 @@ static int of_translate_one(struct device_node
> *parent, struct of_bus *bus,
>  	pr_debug("with offset: %llx\n", (unsigned long long)offset);
> 
>  	/* Translate it into parent bus space */
> -	return pbus->translate(addr, offset, pna);
> +	if (pbus->translate(addr, offset, pna))
> +		return OF_BAD_ADDR;
> +
> +	return offset;
>  }
> 
>  /*
> @@ -549,9 +548,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 lacks a tranlation, and the return code is relative to
> + * that node.

This seems to be wrong to me. We are abusing of the error conditions.
So effectively if there is a buggy DT for an IO resource we end up
assuming that we are using a special IO device with unmapped addresses.

The patch at the bottom apply on top of this one and I think is a more
reasonable approach


>   */
>  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;
> @@ -564,6 +568,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)
> @@ -600,8 +605,9 @@ static u64 __of_translate_address(struct
> device_node *dev,
>  		pbus = of_match_bus(parent);
>  		pbus->count_cells(dev, &pna, &pns);
>  		if (!OF_CHECK_COUNTS(pna, pns)) {
> -			pr_err("Bad cell count for %s\n",
> -			       of_node_full_name(dev));
> +			pr_debug("Bad cell count for %s\n",
> +				 of_node_full_name(dev));
> +			*host = of_node_get(parent);
>  			break;
>  		}
> 
> @@ -609,7 +615,9 @@ static u64 __of_translate_address(struct
> device_node *dev,
>  		    pbus->name, pna, pns, of_node_full_name(parent));
> 
>  		/* Apply bus translation */
> -		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna,
> rprop))
> +		result = of_translate_one(dev, bus, pbus, addr, na, ns,
> +					  pna, rprop);
> +		if (result == OF_BAD_ADDR)

It seems to me that here you missed "*host = of_node_get(parent);"..?

>  			break;
> 
>  		/* Complete the move up one level */
> @@ -628,13 +636,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);
> 
> @@ -676,29 +703,48 @@ const __be32 *of_get_address(struct device_node
> *dev, int index, u64 *size,
>  }
>  EXPORT_SYMBOL(of_get_address);
> 
> +extern unsigned long extio_translate(struct fwnode_handle *node,
> unsigned long offset);
> +
> +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 = extio_translate(&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;
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index eda6a7cf0e54..320ab9fbf6af 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -3249,6 +3249,7 @@ EXPORT_SYMBOL(pci_request_regions_exclusive);
>  #ifdef PCI_IOBASE
>  struct io_range {
>  	struct list_head list;
> +	struct fwnode_handle *node;
>  	phys_addr_t start;
>  	resource_size_t size;
>  };
> @@ -3257,11 +3258,14 @@ static LIST_HEAD(io_range_list);
>  static DEFINE_SPINLOCK(io_range_lock);
>  #endif
> 
> +#define IO_RANGE_IOEXT (resource_size_t)(-1ull)
> +
>  /*
>   * 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 __weak pci_register_io_range(struct fwnode_handle *node,
> phys_addr_t addr,
> +				 resource_size_t size, unsigned long *port)
>  {
>  	int err = 0;
> 
> @@ -3272,7 +3276,12 @@ int __weak pci_register_io_range(phys_addr_t
> addr, resource_size_t size)
>  	/* 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) {
> +		if (node == range->node)
> +			goto end_register;
> +

It seems to me that the condition above is sufficient; i.e.
we can remove the one here below...?

> +		if (addr != IO_RANGE_IOEXT &&
> +		    addr >= range->start &&
> +		    addr + size <= range->start + size) {
>  			/* range already registered, bail out */
>  			goto end_register;
>  		}
> @@ -3298,6 +3307,7 @@ int __weak pci_register_io_range(phys_addr_t
> addr, resource_size_t size)
>  		goto end_register;
>  	}
> 
> +	range->node = node;
>  	range->start = addr;
>  	range->size = size;
> 
> @@ -3305,11 +3315,26 @@ int __weak pci_register_io_range(phys_addr_t
> addr, resource_size_t size)
> 
>  end_register:
>  	spin_unlock(&io_range_lock);
> +
> +	*port = allocated_size;
> +#else
> +	/*
> +	 * powerpc and microblaze have their own registration,
> +	 * just look up the value here
> +	 */
> +	*port = pci_address_to_pio(addr);
>  #endif
> 
>  	return err;
>  }
> 
> +#ifdef CONFIG_IOEXT
> +int ioext_register_io_range
> +{
> +	return pci_register_io_range(node, IO_RANGE_IOEXT, size, port);
> +}
> +#endif
> +
>  phys_addr_t pci_pio_to_address(unsigned long pio)
>  {
>  	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 6bd94a803e8f..b7a8fa3da3ca 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1192,7 +1192,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 *node, phys_addr_t
> addr,
> +			  resource_size_t size, unsigned long *port);
>  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);

I think the patch below is a more reasonable approach to identify
a host that does not support address translation and it should 
guarantee safety against broken DTs...

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 5decaba..9bfc526 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -540,6 +540,49 @@ static u64 of_translate_one(struct device_node *parent, struct of_bus *bus,
 }
 

Signed-off-by: Zhichang Yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>

 /*
+ * of_isa_indirect_io - get the IO address from some isa reg property value.
+ *	For some isa/lpc devices, no ranges property in ancestor node.
+ *	The device addresses are described directly in their regs property.
+ *	This fixup function will be called to get the IO address of isa/lpc
+ *	devices when the normal of_translation failed.
+ *
+ * @parent:	points to the parent dts node;
+ * @bus:		points to the of_bus which can be used to parse address;
+ * @addr:	the address from reg property;
+ * @na:		the address cell counter of @addr;
+ * @presult:	store the address paresed from @addr;
+ *
+ * return 1 when successfully get the I/O address;
+ * 0 will return for some failures.
+ */
+static int of_get_isa_indirect_io(struct device_node *parent,
+				struct of_bus *bus, __be32 *addr,
+				int na, u64 *presult)
+{
+	unsigned int flags;
+	unsigned int rlen;
+
+	/* whether support indirectIO */
+	if (!indirect_io_enabled())
+		return 0;
+
+	if (!of_bus_isa_match(parent))
+		return 0;
+
+	flags = bus->get_flags(addr);
+	if (!(flags & IORESOURCE_IO))
+		return 0;
+
+	/* there is ranges property, apply the normal translation directly. */
+	if (of_get_property(parent, "ranges", &rlen))
+		return 0;
+
+	*presult = of_read_number(addr + 1, na - 1);
+	/* this fixup is only valid for specific I/O range. */
+	return addr_is_indirect_io(*presult);
+}
+
+/*
  * Translate an address from the device-tree into a CPU physical address,
  * this walks up the tree and applies the various bus mappings on the
  * way.
@@ -600,14 +643,23 @@ static u64 __of_translate_address(struct device_node *dev,
 			result = of_read_number(addr, na);
 			break;
 		}
+		/*
+		 * For indirectIO device which has no ranges property, get
+		 * the address from reg directly.
+		 */
+		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
+			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
+				of_node_full_name(dev), result);
+			*host = of_node_get(parent);
+			break;
+		}
 
 		/* Get new parent bus and counts */
 		pbus = of_match_bus(parent);
 		pbus->count_cells(dev, &pna, &pns);
 		if (!OF_CHECK_COUNTS(pna, pns)) {
-			pr_debug("Bad cell count for %s\n",
+			pr_err("Bad cell count for %s\n",
 				 of_node_full_name(dev));
-			*host = of_node_get(parent);
 			break;
 		}
 
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 3786473..14848d8 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -24,6 +24,23 @@ struct of_pci_range {
 #define for_each_of_pci_range(parser, range) \
 	for (; of_pci_range_parser_one(parser, range);)
 
+#ifndef indirect_io_enabled
+#define indirect_io_enabled indirect_io_enabled
+static inline bool indirect_io_enabled(void)
+{
+	return false;
+}
+#endif
+
+#ifndef addr_is_indirect_io
+#define addr_is_indirect_io addr_is_indirect_io
+static inline int addr_is_indirect_io(u64 taddr)
+{
+	return 0;
+}
+#endif
+
+
 /* 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.7.4

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-25  8:46                                                       ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-25  8:46 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: mark.rutland, benh, liviu.dudau, Linuxarm, lorenzo.pieralisi,
	xuwei (O),
	Jason Gunthorpe, T homas Petazzoni, linux-serial,
	catalin.marinas, devicetree, minyard, will.deacon, John Garry,
	zourongrong, robh+dt, bhelgaas@go og le.com, kantyzc,
	zhichang.yuan02

Hi Arnd

Many thanks for your contribution, much appreciated

I have some comments...see inline below 

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 23 November 2016 23:23
> To: linux-arm-kernel@lists.infradead.org
> Cc: Gabriele Paoloni; mark.rutland@arm.com; catalin.marinas@arm.com;
> linux-pci@vger.kernel.org; liviu.dudau@arm.com; Linuxarm;
> lorenzo.pieralisi@arm.com; xuwei (O); Jason Gunthorpe; T homas
> Petazzoni; linux-serial@vger.kernel.org; benh@kernel.crashing.org;
> devicetree@vger.kernel.org; minyard@acm.org; will.deacon@arm.com; John
> Garry; olof@lixom.net; robh+dt@kernel.org; bhelgaas@go og le.com;
> kantyzc@163.com; zhichang.yuan02@gmail.com; linux-
> kernel@vger.kernel.org; Yuanzhichang; zourongrong@gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> > On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni
> wrote:
> > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni
> wrote:
> >
> > Please don't proliferate the use of
> > pci_pio_to_address/pci_address_to_pio here, computing the physical
> > address from the logical address is trivial, you just need to
> > subtract the start of the range that you already use when matching
> > the port number range.
> >
> > The only thing we need here is to make of_address_to_resource()
> > return the correct logical port number that was registered for
> > a given host device when asked to translate an address that
> > does not have a CPU address associated with it.
> 
> Ok, I admit this was a little harder than I expected, but see below
> for a rough outline of how I think it can be done.
> 
> This makes it possible to translate bus specific I/O port numbers
> from device nodes into Linux port numbers, and gives a way to register
> them. We could take this further and completely remove
> pci_pio_to_address
> and pci_address_to_pio if we make the I/O port translation always
> go through the io_range list, looking up up the hostbridge by fwnode,
> but we don't have to do that now.
> 
> The patch is completely untested and probably buggy, it just seemed
> easier to put out a prototype than to keep going in circles with the
> discussion.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> 
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> index bf601d4df8cf..6cadf0501bb0 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 *node,
> +					struct resource_entry *entry)
>  {
>  #ifdef PCI_IOBASE
>  	struct resource *res = entry->res;
> @@ -739,11 +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))
> -		goto err;
> -
> -	port = pci_address_to_pio(cpu_addr);
> -	if (port == (unsigned long)-1)
> +	if (pci_register_io_range(node, cpu_addr, length, &port))
>  		goto err;
> 
>  	res->start = port;
> @@ -781,7 +778,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/block/nbd.c b/drivers/block/nbd.c
> index a50025a3777f..df96955a43f8 100644
> --- a/drivers/block/nbd.c
> +++ b/drivers/block/nbd.c
> @@ -760,8 +760,10 @@ static int __nbd_ioctl(struct block_device *bdev,
> struct nbd_device *nbd,
>  		set_bit(NBD_RUNNING, &nbd->runtime_flags);
>  		blk_mq_update_nr_hw_queues(&nbd->tag_set, nbd-
> >num_connections);
>  		args = kcalloc(num_connections, sizeof(*args), GFP_KERNEL);
> -		if (!args)
> +		if (!args) {
> +			error = -ENOMEM;
>  			goto out_err;
> +		}
>  		nbd->task_recv = current;
>  		mutex_unlock(&nbd->config_lock);
> 
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903fe9d2..5decaba96eed 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -2,6 +2,7 @@
>  #define pr_fmt(fmt)	"OF: " fmt
> 
>  #include <linux/device.h>
> +#include <linux/fwnode.h>
>  #include <linux/io.h>
>  #include <linux/ioport.h>
>  #include <linux/module.h>
> @@ -323,14 +324,9 @@ 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, &port);
>  		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 {
>  		if ((sizeof(resource_size_t) < 8) &&
> @@ -479,7 +475,7 @@ static int of_empty_ranges_quirk(struct device_node
> *np)
>  	return false;
>  }
> 
> -static int of_translate_one(struct device_node *parent, struct of_bus
> *bus,
> +static u64 of_translate_one(struct device_node *parent, struct of_bus
> *bus,
>  			    struct of_bus *pbus, __be32 *addr,
>  			    int na, int ns, int pna, const char *rprop)
>  {
> @@ -507,7 +503,7 @@ static int of_translate_one(struct device_node
> *parent, struct of_bus *bus,
>  	ranges = of_get_property(parent, rprop, &rlen);
>  	if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
>  		pr_debug("no ranges; cannot translate\n");
> -		return 1;
> +		return OF_BAD_ADDR;
>  	}
>  	if (ranges == NULL || rlen == 0) {
>  		offset = of_read_number(addr, na);
> @@ -528,7 +524,7 @@ static int of_translate_one(struct device_node
> *parent, struct of_bus *bus,
>  	}
>  	if (offset == OF_BAD_ADDR) {
>  		pr_debug("not found !\n");
> -		return 1;
> +		return offset;
>  	}
>  	memcpy(addr, ranges + na, 4 * pna);
> 
> @@ -537,7 +533,10 @@ static int of_translate_one(struct device_node
> *parent, struct of_bus *bus,
>  	pr_debug("with offset: %llx\n", (unsigned long long)offset);
> 
>  	/* Translate it into parent bus space */
> -	return pbus->translate(addr, offset, pna);
> +	if (pbus->translate(addr, offset, pna))
> +		return OF_BAD_ADDR;
> +
> +	return offset;
>  }
> 
>  /*
> @@ -549,9 +548,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 lacks a tranlation, and the return code is relative to
> + * that node.

This seems to be wrong to me. We are abusing of the error conditions.
So effectively if there is a buggy DT for an IO resource we end up
assuming that we are using a special IO device with unmapped addresses.

The patch at the bottom apply on top of this one and I think is a more
reasonable approach


>   */
>  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;
> @@ -564,6 +568,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)
> @@ -600,8 +605,9 @@ static u64 __of_translate_address(struct
> device_node *dev,
>  		pbus = of_match_bus(parent);
>  		pbus->count_cells(dev, &pna, &pns);
>  		if (!OF_CHECK_COUNTS(pna, pns)) {
> -			pr_err("Bad cell count for %s\n",
> -			       of_node_full_name(dev));
> +			pr_debug("Bad cell count for %s\n",
> +				 of_node_full_name(dev));
> +			*host = of_node_get(parent);
>  			break;
>  		}
> 
> @@ -609,7 +615,9 @@ static u64 __of_translate_address(struct
> device_node *dev,
>  		    pbus->name, pna, pns, of_node_full_name(parent));
> 
>  		/* Apply bus translation */
> -		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna,
> rprop))
> +		result = of_translate_one(dev, bus, pbus, addr, na, ns,
> +					  pna, rprop);
> +		if (result == OF_BAD_ADDR)

It seems to me that here you missed "*host = of_node_get(parent);"..?

>  			break;
> 
>  		/* Complete the move up one level */
> @@ -628,13 +636,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);
> 
> @@ -676,29 +703,48 @@ const __be32 *of_get_address(struct device_node
> *dev, int index, u64 *size,
>  }
>  EXPORT_SYMBOL(of_get_address);
> 
> +extern unsigned long extio_translate(struct fwnode_handle *node,
> unsigned long offset);
> +
> +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 = extio_translate(&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;
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index eda6a7cf0e54..320ab9fbf6af 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -3249,6 +3249,7 @@ EXPORT_SYMBOL(pci_request_regions_exclusive);
>  #ifdef PCI_IOBASE
>  struct io_range {
>  	struct list_head list;
> +	struct fwnode_handle *node;
>  	phys_addr_t start;
>  	resource_size_t size;
>  };
> @@ -3257,11 +3258,14 @@ static LIST_HEAD(io_range_list);
>  static DEFINE_SPINLOCK(io_range_lock);
>  #endif
> 
> +#define IO_RANGE_IOEXT (resource_size_t)(-1ull)
> +
>  /*
>   * 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 __weak pci_register_io_range(struct fwnode_handle *node,
> phys_addr_t addr,
> +				 resource_size_t size, unsigned long *port)
>  {
>  	int err = 0;
> 
> @@ -3272,7 +3276,12 @@ int __weak pci_register_io_range(phys_addr_t
> addr, resource_size_t size)
>  	/* 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) {
> +		if (node == range->node)
> +			goto end_register;
> +

It seems to me that the condition above is sufficient; i.e.
we can remove the one here below...?

> +		if (addr != IO_RANGE_IOEXT &&
> +		    addr >= range->start &&
> +		    addr + size <= range->start + size) {
>  			/* range already registered, bail out */
>  			goto end_register;
>  		}
> @@ -3298,6 +3307,7 @@ int __weak pci_register_io_range(phys_addr_t
> addr, resource_size_t size)
>  		goto end_register;
>  	}
> 
> +	range->node = node;
>  	range->start = addr;
>  	range->size = size;
> 
> @@ -3305,11 +3315,26 @@ int __weak pci_register_io_range(phys_addr_t
> addr, resource_size_t size)
> 
>  end_register:
>  	spin_unlock(&io_range_lock);
> +
> +	*port = allocated_size;
> +#else
> +	/*
> +	 * powerpc and microblaze have their own registration,
> +	 * just look up the value here
> +	 */
> +	*port = pci_address_to_pio(addr);
>  #endif
> 
>  	return err;
>  }
> 
> +#ifdef CONFIG_IOEXT
> +int ioext_register_io_range
> +{
> +	return pci_register_io_range(node, IO_RANGE_IOEXT, size, port);
> +}
> +#endif
> +
>  phys_addr_t pci_pio_to_address(unsigned long pio)
>  {
>  	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 6bd94a803e8f..b7a8fa3da3ca 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1192,7 +1192,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 *node, phys_addr_t
> addr,
> +			  resource_size_t size, unsigned long *port);
>  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);

I think the patch below is a more reasonable approach to identify
a host that does not support address translation and it should 
guarantee safety against broken DTs...

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 5decaba..9bfc526 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -540,6 +540,49 @@ static u64 of_translate_one(struct device_node *parent, struct of_bus *bus,
 }
 

Signed-off-by: Zhichang Yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>

 /*
+ * of_isa_indirect_io - get the IO address from some isa reg property value.
+ *	For some isa/lpc devices, no ranges property in ancestor node.
+ *	The device addresses are described directly in their regs property.
+ *	This fixup function will be called to get the IO address of isa/lpc
+ *	devices when the normal of_translation failed.
+ *
+ * @parent:	points to the parent dts node;
+ * @bus:		points to the of_bus which can be used to parse address;
+ * @addr:	the address from reg property;
+ * @na:		the address cell counter of @addr;
+ * @presult:	store the address paresed from @addr;
+ *
+ * return 1 when successfully get the I/O address;
+ * 0 will return for some failures.
+ */
+static int of_get_isa_indirect_io(struct device_node *parent,
+				struct of_bus *bus, __be32 *addr,
+				int na, u64 *presult)
+{
+	unsigned int flags;
+	unsigned int rlen;
+
+	/* whether support indirectIO */
+	if (!indirect_io_enabled())
+		return 0;
+
+	if (!of_bus_isa_match(parent))
+		return 0;
+
+	flags = bus->get_flags(addr);
+	if (!(flags & IORESOURCE_IO))
+		return 0;
+
+	/* there is ranges property, apply the normal translation directly. */
+	if (of_get_property(parent, "ranges", &rlen))
+		return 0;
+
+	*presult = of_read_number(addr + 1, na - 1);
+	/* this fixup is only valid for specific I/O range. */
+	return addr_is_indirect_io(*presult);
+}
+
+/*
  * Translate an address from the device-tree into a CPU physical address,
  * this walks up the tree and applies the various bus mappings on the
  * way.
@@ -600,14 +643,23 @@ static u64 __of_translate_address(struct device_node *dev,
 			result = of_read_number(addr, na);
 			break;
 		}
+		/*
+		 * For indirectIO device which has no ranges property, get
+		 * the address from reg directly.
+		 */
+		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
+			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
+				of_node_full_name(dev), result);
+			*host = of_node_get(parent);
+			break;
+		}
 
 		/* Get new parent bus and counts */
 		pbus = of_match_bus(parent);
 		pbus->count_cells(dev, &pna, &pns);
 		if (!OF_CHECK_COUNTS(pna, pns)) {
-			pr_debug("Bad cell count for %s\n",
+			pr_err("Bad cell count for %s\n",
 				 of_node_full_name(dev));
-			*host = of_node_get(parent);
 			break;
 		}
 
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 3786473..14848d8 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -24,6 +24,23 @@ struct of_pci_range {
 #define for_each_of_pci_range(parser, range) \
 	for (; of_pci_range_parser_one(parser, range);)
 
+#ifndef indirect_io_enabled
+#define indirect_io_enabled indirect_io_enabled
+static inline bool indirect_io_enabled(void)
+{
+	return false;
+}
+#endif
+
+#ifndef addr_is_indirect_io
+#define addr_is_indirect_io addr_is_indirect_io
+static inline int addr_is_indirect_io(u64 taddr)
+{
+	return 0;
+}
+#endif
+
+
 /* 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.7.4

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-25  8:46                                                       ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-25  8:46 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: mark.rutland, catalin.marinas, linux-pci, liviu.dudau, Linuxarm,
	lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, T homas Petazzoni, linux-serial, benh,
	devicetree, minyard, will.deacon, John Garry, olof, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02, linux-kernel,
	Yuanzhichang, zourongrong

Hi Arnd

Many thanks for your contribution, much appreciated

I have some comments...see inline below 

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 23 November 2016 23:23
> To: linux-arm-kernel@lists.infradead.org
> Cc: Gabriele Paoloni; mark.rutland@arm.com; catalin.marinas@arm.com;
> linux-pci@vger.kernel.org; liviu.dudau@arm.com; Linuxarm;
> lorenzo.pieralisi@arm.com; xuwei (O); Jason Gunthorpe; T homas
> Petazzoni; linux-serial@vger.kernel.org; benh@kernel.crashing.org;
> devicetree@vger.kernel.org; minyard@acm.org; will.deacon@arm.com; John
> Garry; olof@lixom.net; robh+dt@kernel.org; bhelgaas@go og le.com;
> kantyzc@163.com; zhichang.yuan02@gmail.com; linux-
> kernel@vger.kernel.org; Yuanzhichang; zourongrong@gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> > On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni
> wrote:
> > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni
> wrote:
> >
> > Please don't proliferate the use of
> > pci_pio_to_address/pci_address_to_pio here, computing the physical
> > address from the logical address is trivial, you just need to
> > subtract the start of the range that you already use when matching
> > the port number range.
> >
> > The only thing we need here is to make of_address_to_resource()
> > return the correct logical port number that was registered for
> > a given host device when asked to translate an address that
> > does not have a CPU address associated with it.
> 
> Ok, I admit this was a little harder than I expected, but see below
> for a rough outline of how I think it can be done.
> 
> This makes it possible to translate bus specific I/O port numbers
> from device nodes into Linux port numbers, and gives a way to register
> them. We could take this further and completely remove
> pci_pio_to_address
> and pci_address_to_pio if we make the I/O port translation always
> go through the io_range list, looking up up the hostbridge by fwnode,
> but we don't have to do that now.
> 
> The patch is completely untested and probably buggy, it just seemed
> easier to put out a prototype than to keep going in circles with the
> discussion.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> 
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> index bf601d4df8cf..6cadf0501bb0 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 *node,
> +					struct resource_entry *entry)
>  {
>  #ifdef PCI_IOBASE
>  	struct resource *res = entry->res;
> @@ -739,11 +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))
> -		goto err;
> -
> -	port = pci_address_to_pio(cpu_addr);
> -	if (port == (unsigned long)-1)
> +	if (pci_register_io_range(node, cpu_addr, length, &port))
>  		goto err;
> 
>  	res->start = port;
> @@ -781,7 +778,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/block/nbd.c b/drivers/block/nbd.c
> index a50025a3777f..df96955a43f8 100644
> --- a/drivers/block/nbd.c
> +++ b/drivers/block/nbd.c
> @@ -760,8 +760,10 @@ static int __nbd_ioctl(struct block_device *bdev,
> struct nbd_device *nbd,
>  		set_bit(NBD_RUNNING, &nbd->runtime_flags);
>  		blk_mq_update_nr_hw_queues(&nbd->tag_set, nbd-
> >num_connections);
>  		args = kcalloc(num_connections, sizeof(*args), GFP_KERNEL);
> -		if (!args)
> +		if (!args) {
> +			error = -ENOMEM;
>  			goto out_err;
> +		}
>  		nbd->task_recv = current;
>  		mutex_unlock(&nbd->config_lock);
> 
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903fe9d2..5decaba96eed 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -2,6 +2,7 @@
>  #define pr_fmt(fmt)	"OF: " fmt
> 
>  #include <linux/device.h>
> +#include <linux/fwnode.h>
>  #include <linux/io.h>
>  #include <linux/ioport.h>
>  #include <linux/module.h>
> @@ -323,14 +324,9 @@ 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, &port);
>  		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 {
>  		if ((sizeof(resource_size_t) < 8) &&
> @@ -479,7 +475,7 @@ static int of_empty_ranges_quirk(struct device_node
> *np)
>  	return false;
>  }
> 
> -static int of_translate_one(struct device_node *parent, struct of_bus
> *bus,
> +static u64 of_translate_one(struct device_node *parent, struct of_bus
> *bus,
>  			    struct of_bus *pbus, __be32 *addr,
>  			    int na, int ns, int pna, const char *rprop)
>  {
> @@ -507,7 +503,7 @@ static int of_translate_one(struct device_node
> *parent, struct of_bus *bus,
>  	ranges = of_get_property(parent, rprop, &rlen);
>  	if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
>  		pr_debug("no ranges; cannot translate\n");
> -		return 1;
> +		return OF_BAD_ADDR;
>  	}
>  	if (ranges == NULL || rlen == 0) {
>  		offset = of_read_number(addr, na);
> @@ -528,7 +524,7 @@ static int of_translate_one(struct device_node
> *parent, struct of_bus *bus,
>  	}
>  	if (offset == OF_BAD_ADDR) {
>  		pr_debug("not found !\n");
> -		return 1;
> +		return offset;
>  	}
>  	memcpy(addr, ranges + na, 4 * pna);
> 
> @@ -537,7 +533,10 @@ static int of_translate_one(struct device_node
> *parent, struct of_bus *bus,
>  	pr_debug("with offset: %llx\n", (unsigned long long)offset);
> 
>  	/* Translate it into parent bus space */
> -	return pbus->translate(addr, offset, pna);
> +	if (pbus->translate(addr, offset, pna))
> +		return OF_BAD_ADDR;
> +
> +	return offset;
>  }
> 
>  /*
> @@ -549,9 +548,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 lacks a tranlation, and the return code is relative to
> + * that node.

This seems to be wrong to me. We are abusing of the error conditions.
So effectively if there is a buggy DT for an IO resource we end up
assuming that we are using a special IO device with unmapped addresses.

The patch at the bottom apply on top of this one and I think is a more
reasonable approach


>   */
>  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;
> @@ -564,6 +568,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)
> @@ -600,8 +605,9 @@ static u64 __of_translate_address(struct
> device_node *dev,
>  		pbus = of_match_bus(parent);
>  		pbus->count_cells(dev, &pna, &pns);
>  		if (!OF_CHECK_COUNTS(pna, pns)) {
> -			pr_err("Bad cell count for %s\n",
> -			       of_node_full_name(dev));
> +			pr_debug("Bad cell count for %s\n",
> +				 of_node_full_name(dev));
> +			*host = of_node_get(parent);
>  			break;
>  		}
> 
> @@ -609,7 +615,9 @@ static u64 __of_translate_address(struct
> device_node *dev,
>  		    pbus->name, pna, pns, of_node_full_name(parent));
> 
>  		/* Apply bus translation */
> -		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna,
> rprop))
> +		result = of_translate_one(dev, bus, pbus, addr, na, ns,
> +					  pna, rprop);
> +		if (result == OF_BAD_ADDR)

It seems to me that here you missed "*host = of_node_get(parent);"..?

>  			break;
> 
>  		/* Complete the move up one level */
> @@ -628,13 +636,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);
> 
> @@ -676,29 +703,48 @@ const __be32 *of_get_address(struct device_node
> *dev, int index, u64 *size,
>  }
>  EXPORT_SYMBOL(of_get_address);
> 
> +extern unsigned long extio_translate(struct fwnode_handle *node,
> unsigned long offset);
> +
> +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 = extio_translate(&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;
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index eda6a7cf0e54..320ab9fbf6af 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -3249,6 +3249,7 @@ EXPORT_SYMBOL(pci_request_regions_exclusive);
>  #ifdef PCI_IOBASE
>  struct io_range {
>  	struct list_head list;
> +	struct fwnode_handle *node;
>  	phys_addr_t start;
>  	resource_size_t size;
>  };
> @@ -3257,11 +3258,14 @@ static LIST_HEAD(io_range_list);
>  static DEFINE_SPINLOCK(io_range_lock);
>  #endif
> 
> +#define IO_RANGE_IOEXT (resource_size_t)(-1ull)
> +
>  /*
>   * 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 __weak pci_register_io_range(struct fwnode_handle *node,
> phys_addr_t addr,
> +				 resource_size_t size, unsigned long *port)
>  {
>  	int err = 0;
> 
> @@ -3272,7 +3276,12 @@ int __weak pci_register_io_range(phys_addr_t
> addr, resource_size_t size)
>  	/* 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) {
> +		if (node == range->node)
> +			goto end_register;
> +

It seems to me that the condition above is sufficient; i.e.
we can remove the one here below...?

> +		if (addr != IO_RANGE_IOEXT &&
> +		    addr >= range->start &&
> +		    addr + size <= range->start + size) {
>  			/* range already registered, bail out */
>  			goto end_register;
>  		}
> @@ -3298,6 +3307,7 @@ int __weak pci_register_io_range(phys_addr_t
> addr, resource_size_t size)
>  		goto end_register;
>  	}
> 
> +	range->node = node;
>  	range->start = addr;
>  	range->size = size;
> 
> @@ -3305,11 +3315,26 @@ int __weak pci_register_io_range(phys_addr_t
> addr, resource_size_t size)
> 
>  end_register:
>  	spin_unlock(&io_range_lock);
> +
> +	*port = allocated_size;
> +#else
> +	/*
> +	 * powerpc and microblaze have their own registration,
> +	 * just look up the value here
> +	 */
> +	*port = pci_address_to_pio(addr);
>  #endif
> 
>  	return err;
>  }
> 
> +#ifdef CONFIG_IOEXT
> +int ioext_register_io_range
> +{
> +	return pci_register_io_range(node, IO_RANGE_IOEXT, size, port);
> +}
> +#endif
> +
>  phys_addr_t pci_pio_to_address(unsigned long pio)
>  {
>  	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 6bd94a803e8f..b7a8fa3da3ca 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1192,7 +1192,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 *node, phys_addr_t
> addr,
> +			  resource_size_t size, unsigned long *port);
>  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);

I think the patch below is a more reasonable approach to identify
a host that does not support address translation and it should 
guarantee safety against broken DTs...

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 5decaba..9bfc526 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -540,6 +540,49 @@ static u64 of_translate_one(struct device_node *parent, struct of_bus *bus,
 }
 

Signed-off-by: Zhichang Yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>

 /*
+ * of_isa_indirect_io - get the IO address from some isa reg property value.
+ *	For some isa/lpc devices, no ranges property in ancestor node.
+ *	The device addresses are described directly in their regs property.
+ *	This fixup function will be called to get the IO address of isa/lpc
+ *	devices when the normal of_translation failed.
+ *
+ * @parent:	points to the parent dts node;
+ * @bus:		points to the of_bus which can be used to parse address;
+ * @addr:	the address from reg property;
+ * @na:		the address cell counter of @addr;
+ * @presult:	store the address paresed from @addr;
+ *
+ * return 1 when successfully get the I/O address;
+ * 0 will return for some failures.
+ */
+static int of_get_isa_indirect_io(struct device_node *parent,
+				struct of_bus *bus, __be32 *addr,
+				int na, u64 *presult)
+{
+	unsigned int flags;
+	unsigned int rlen;
+
+	/* whether support indirectIO */
+	if (!indirect_io_enabled())
+		return 0;
+
+	if (!of_bus_isa_match(parent))
+		return 0;
+
+	flags = bus->get_flags(addr);
+	if (!(flags & IORESOURCE_IO))
+		return 0;
+
+	/* there is ranges property, apply the normal translation directly. */
+	if (of_get_property(parent, "ranges", &rlen))
+		return 0;
+
+	*presult = of_read_number(addr + 1, na - 1);
+	/* this fixup is only valid for specific I/O range. */
+	return addr_is_indirect_io(*presult);
+}
+
+/*
  * Translate an address from the device-tree into a CPU physical address,
  * this walks up the tree and applies the various bus mappings on the
  * way.
@@ -600,14 +643,23 @@ static u64 __of_translate_address(struct device_node *dev,
 			result = of_read_number(addr, na);
 			break;
 		}
+		/*
+		 * For indirectIO device which has no ranges property, get
+		 * the address from reg directly.
+		 */
+		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
+			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
+				of_node_full_name(dev), result);
+			*host = of_node_get(parent);
+			break;
+		}
 
 		/* Get new parent bus and counts */
 		pbus = of_match_bus(parent);
 		pbus->count_cells(dev, &pna, &pns);
 		if (!OF_CHECK_COUNTS(pna, pns)) {
-			pr_debug("Bad cell count for %s\n",
+			pr_err("Bad cell count for %s\n",
 				 of_node_full_name(dev));
-			*host = of_node_get(parent);
 			break;
 		}
 
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 3786473..14848d8 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -24,6 +24,23 @@ struct of_pci_range {
 #define for_each_of_pci_range(parser, range) \
 	for (; of_pci_range_parser_one(parser, range);)
 
+#ifndef indirect_io_enabled
+#define indirect_io_enabled indirect_io_enabled
+static inline bool indirect_io_enabled(void)
+{
+	return false;
+}
+#endif
+
+#ifndef addr_is_indirect_io
+#define addr_is_indirect_io addr_is_indirect_io
+static inline int addr_is_indirect_io(u64 taddr)
+{
+	return 0;
+}
+#endif
+
+
 /* 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.7.4


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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-25  8:46                                                       ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-25  8:46 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd

Many thanks for your contribution, much appreciated

I have some comments...see inline below 

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 23 November 2016 23:23
> To: linux-arm-kernel at lists.infradead.org
> Cc: Gabriele Paoloni; mark.rutland at arm.com; catalin.marinas at arm.com;
> linux-pci at vger.kernel.org; liviu.dudau at arm.com; Linuxarm;
> lorenzo.pieralisi at arm.com; xuwei (O); Jason Gunthorpe; T homas
> Petazzoni; linux-serial at vger.kernel.org; benh at kernel.crashing.org;
> devicetree at vger.kernel.org; minyard at acm.org; will.deacon at arm.com; John
> Garry; olof at lixom.net; robh+dt at kernel.org; bhelgaas at go og le.com;
> kantyzc at 163.com; zhichang.yuan02 at gmail.com; linux-
> kernel at vger.kernel.org; Yuanzhichang; zourongrong at gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> > On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni
> wrote:
> > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni
> wrote:
> >
> > Please don't proliferate the use of
> > pci_pio_to_address/pci_address_to_pio here, computing the physical
> > address from the logical address is trivial, you just need to
> > subtract the start of the range that you already use when matching
> > the port number range.
> >
> > The only thing we need here is to make of_address_to_resource()
> > return the correct logical port number that was registered for
> > a given host device when asked to translate an address that
> > does not have a CPU address associated with it.
> 
> Ok, I admit this was a little harder than I expected, but see below
> for a rough outline of how I think it can be done.
> 
> This makes it possible to translate bus specific I/O port numbers
> from device nodes into Linux port numbers, and gives a way to register
> them. We could take this further and completely remove
> pci_pio_to_address
> and pci_address_to_pio if we make the I/O port translation always
> go through the io_range list, looking up up the hostbridge by fwnode,
> but we don't have to do that now.
> 
> The patch is completely untested and probably buggy, it just seemed
> easier to put out a prototype than to keep going in circles with the
> discussion.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> 
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> index bf601d4df8cf..6cadf0501bb0 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 *node,
> +					struct resource_entry *entry)
>  {
>  #ifdef PCI_IOBASE
>  	struct resource *res = entry->res;
> @@ -739,11 +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))
> -		goto err;
> -
> -	port = pci_address_to_pio(cpu_addr);
> -	if (port == (unsigned long)-1)
> +	if (pci_register_io_range(node, cpu_addr, length, &port))
>  		goto err;
> 
>  	res->start = port;
> @@ -781,7 +778,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/block/nbd.c b/drivers/block/nbd.c
> index a50025a3777f..df96955a43f8 100644
> --- a/drivers/block/nbd.c
> +++ b/drivers/block/nbd.c
> @@ -760,8 +760,10 @@ static int __nbd_ioctl(struct block_device *bdev,
> struct nbd_device *nbd,
>  		set_bit(NBD_RUNNING, &nbd->runtime_flags);
>  		blk_mq_update_nr_hw_queues(&nbd->tag_set, nbd-
> >num_connections);
>  		args = kcalloc(num_connections, sizeof(*args), GFP_KERNEL);
> -		if (!args)
> +		if (!args) {
> +			error = -ENOMEM;
>  			goto out_err;
> +		}
>  		nbd->task_recv = current;
>  		mutex_unlock(&nbd->config_lock);
> 
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903fe9d2..5decaba96eed 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -2,6 +2,7 @@
>  #define pr_fmt(fmt)	"OF: " fmt
> 
>  #include <linux/device.h>
> +#include <linux/fwnode.h>
>  #include <linux/io.h>
>  #include <linux/ioport.h>
>  #include <linux/module.h>
> @@ -323,14 +324,9 @@ 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, &port);
>  		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 {
>  		if ((sizeof(resource_size_t) < 8) &&
> @@ -479,7 +475,7 @@ static int of_empty_ranges_quirk(struct device_node
> *np)
>  	return false;
>  }
> 
> -static int of_translate_one(struct device_node *parent, struct of_bus
> *bus,
> +static u64 of_translate_one(struct device_node *parent, struct of_bus
> *bus,
>  			    struct of_bus *pbus, __be32 *addr,
>  			    int na, int ns, int pna, const char *rprop)
>  {
> @@ -507,7 +503,7 @@ static int of_translate_one(struct device_node
> *parent, struct of_bus *bus,
>  	ranges = of_get_property(parent, rprop, &rlen);
>  	if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
>  		pr_debug("no ranges; cannot translate\n");
> -		return 1;
> +		return OF_BAD_ADDR;
>  	}
>  	if (ranges == NULL || rlen == 0) {
>  		offset = of_read_number(addr, na);
> @@ -528,7 +524,7 @@ static int of_translate_one(struct device_node
> *parent, struct of_bus *bus,
>  	}
>  	if (offset == OF_BAD_ADDR) {
>  		pr_debug("not found !\n");
> -		return 1;
> +		return offset;
>  	}
>  	memcpy(addr, ranges + na, 4 * pna);
> 
> @@ -537,7 +533,10 @@ static int of_translate_one(struct device_node
> *parent, struct of_bus *bus,
>  	pr_debug("with offset: %llx\n", (unsigned long long)offset);
> 
>  	/* Translate it into parent bus space */
> -	return pbus->translate(addr, offset, pna);
> +	if (pbus->translate(addr, offset, pna))
> +		return OF_BAD_ADDR;
> +
> +	return offset;
>  }
> 
>  /*
> @@ -549,9 +548,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 lacks a tranlation, and the return code is relative to
> + * that node.

This seems to be wrong to me. We are abusing of the error conditions.
So effectively if there is a buggy DT for an IO resource we end up
assuming that we are using a special IO device with unmapped addresses.

The patch at the bottom apply on top of this one and I think is a more
reasonable approach


>   */
>  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;
> @@ -564,6 +568,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)
> @@ -600,8 +605,9 @@ static u64 __of_translate_address(struct
> device_node *dev,
>  		pbus = of_match_bus(parent);
>  		pbus->count_cells(dev, &pna, &pns);
>  		if (!OF_CHECK_COUNTS(pna, pns)) {
> -			pr_err("Bad cell count for %s\n",
> -			       of_node_full_name(dev));
> +			pr_debug("Bad cell count for %s\n",
> +				 of_node_full_name(dev));
> +			*host = of_node_get(parent);
>  			break;
>  		}
> 
> @@ -609,7 +615,9 @@ static u64 __of_translate_address(struct
> device_node *dev,
>  		    pbus->name, pna, pns, of_node_full_name(parent));
> 
>  		/* Apply bus translation */
> -		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna,
> rprop))
> +		result = of_translate_one(dev, bus, pbus, addr, na, ns,
> +					  pna, rprop);
> +		if (result == OF_BAD_ADDR)

It seems to me that here you missed "*host = of_node_get(parent);"..?

>  			break;
> 
>  		/* Complete the move up one level */
> @@ -628,13 +636,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);
> 
> @@ -676,29 +703,48 @@ const __be32 *of_get_address(struct device_node
> *dev, int index, u64 *size,
>  }
>  EXPORT_SYMBOL(of_get_address);
> 
> +extern unsigned long extio_translate(struct fwnode_handle *node,
> unsigned long offset);
> +
> +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 = extio_translate(&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;
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index eda6a7cf0e54..320ab9fbf6af 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -3249,6 +3249,7 @@ EXPORT_SYMBOL(pci_request_regions_exclusive);
>  #ifdef PCI_IOBASE
>  struct io_range {
>  	struct list_head list;
> +	struct fwnode_handle *node;
>  	phys_addr_t start;
>  	resource_size_t size;
>  };
> @@ -3257,11 +3258,14 @@ static LIST_HEAD(io_range_list);
>  static DEFINE_SPINLOCK(io_range_lock);
>  #endif
> 
> +#define IO_RANGE_IOEXT (resource_size_t)(-1ull)
> +
>  /*
>   * 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 __weak pci_register_io_range(struct fwnode_handle *node,
> phys_addr_t addr,
> +				 resource_size_t size, unsigned long *port)
>  {
>  	int err = 0;
> 
> @@ -3272,7 +3276,12 @@ int __weak pci_register_io_range(phys_addr_t
> addr, resource_size_t size)
>  	/* 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) {
> +		if (node == range->node)
> +			goto end_register;
> +

It seems to me that the condition above is sufficient; i.e.
we can remove the one here below...?

> +		if (addr != IO_RANGE_IOEXT &&
> +		    addr >= range->start &&
> +		    addr + size <= range->start + size) {
>  			/* range already registered, bail out */
>  			goto end_register;
>  		}
> @@ -3298,6 +3307,7 @@ int __weak pci_register_io_range(phys_addr_t
> addr, resource_size_t size)
>  		goto end_register;
>  	}
> 
> +	range->node = node;
>  	range->start = addr;
>  	range->size = size;
> 
> @@ -3305,11 +3315,26 @@ int __weak pci_register_io_range(phys_addr_t
> addr, resource_size_t size)
> 
>  end_register:
>  	spin_unlock(&io_range_lock);
> +
> +	*port = allocated_size;
> +#else
> +	/*
> +	 * powerpc and microblaze have their own registration,
> +	 * just look up the value here
> +	 */
> +	*port = pci_address_to_pio(addr);
>  #endif
> 
>  	return err;
>  }
> 
> +#ifdef CONFIG_IOEXT
> +int ioext_register_io_range
> +{
> +	return pci_register_io_range(node, IO_RANGE_IOEXT, size, port);
> +}
> +#endif
> +
>  phys_addr_t pci_pio_to_address(unsigned long pio)
>  {
>  	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 6bd94a803e8f..b7a8fa3da3ca 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1192,7 +1192,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 *node, phys_addr_t
> addr,
> +			  resource_size_t size, unsigned long *port);
>  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);

I think the patch below is a more reasonable approach to identify
a host that does not support address translation and it should 
guarantee safety against broken DTs...

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 5decaba..9bfc526 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -540,6 +540,49 @@ static u64 of_translate_one(struct device_node *parent, struct of_bus *bus,
 }
 

Signed-off-by: Zhichang Yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>

 /*
+ * of_isa_indirect_io - get the IO address from some isa reg property value.
+ *	For some isa/lpc devices, no ranges property in ancestor node.
+ *	The device addresses are described directly in their regs property.
+ *	This fixup function will be called to get the IO address of isa/lpc
+ *	devices when the normal of_translation failed.
+ *
+ * @parent:	points to the parent dts node;
+ * @bus:		points to the of_bus which can be used to parse address;
+ * @addr:	the address from reg property;
+ * @na:		the address cell counter of @addr;
+ * @presult:	store the address paresed from @addr;
+ *
+ * return 1 when successfully get the I/O address;
+ * 0 will return for some failures.
+ */
+static int of_get_isa_indirect_io(struct device_node *parent,
+				struct of_bus *bus, __be32 *addr,
+				int na, u64 *presult)
+{
+	unsigned int flags;
+	unsigned int rlen;
+
+	/* whether support indirectIO */
+	if (!indirect_io_enabled())
+		return 0;
+
+	if (!of_bus_isa_match(parent))
+		return 0;
+
+	flags = bus->get_flags(addr);
+	if (!(flags & IORESOURCE_IO))
+		return 0;
+
+	/* there is ranges property, apply the normal translation directly. */
+	if (of_get_property(parent, "ranges", &rlen))
+		return 0;
+
+	*presult = of_read_number(addr + 1, na - 1);
+	/* this fixup is only valid for specific I/O range. */
+	return addr_is_indirect_io(*presult);
+}
+
+/*
  * Translate an address from the device-tree into a CPU physical address,
  * this walks up the tree and applies the various bus mappings on the
  * way.
@@ -600,14 +643,23 @@ static u64 __of_translate_address(struct device_node *dev,
 			result = of_read_number(addr, na);
 			break;
 		}
+		/*
+		 * For indirectIO device which has no ranges property, get
+		 * the address from reg directly.
+		 */
+		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
+			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
+				of_node_full_name(dev), result);
+			*host = of_node_get(parent);
+			break;
+		}
 
 		/* Get new parent bus and counts */
 		pbus = of_match_bus(parent);
 		pbus->count_cells(dev, &pna, &pns);
 		if (!OF_CHECK_COUNTS(pna, pns)) {
-			pr_debug("Bad cell count for %s\n",
+			pr_err("Bad cell count for %s\n",
 				 of_node_full_name(dev));
-			*host = of_node_get(parent);
 			break;
 		}
 
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 3786473..14848d8 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -24,6 +24,23 @@ struct of_pci_range {
 #define for_each_of_pci_range(parser, range) \
 	for (; of_pci_range_parser_one(parser, range);)
 
+#ifndef indirect_io_enabled
+#define indirect_io_enabled indirect_io_enabled
+static inline bool indirect_io_enabled(void)
+{
+	return false;
+}
+#endif
+
+#ifndef addr_is_indirect_io
+#define addr_is_indirect_io addr_is_indirect_io
+static inline int addr_is_indirect_io(u64 taddr)
+{
+	return 0;
+}
+#endif
+
+
 /* 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.7.4

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-25  8:46                                                       ` Gabriele Paoloni
  (?)
  (?)
@ 2016-11-25 12:03                                                         ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-25 12:03 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: linux-arm-kernel, mark.rutland, catalin.marinas, linux-pci,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, T homas Petazzoni, linux-serial, benh,
	devicetree, minyard, will.deacon, John Garry, olof, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02, linux-kernel,
	Yuanzhichang, zourongrong

On Friday, November 25, 2016 8:46:11 AM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > 
> > On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> > > On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni
> > wrote:
> > > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni
> >  /*
> > @@ -549,9 +548,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 lacks a tranlation, and the return code is relative to
> > + * that node.
> 
> This seems to be wrong to me. We are abusing of the error conditions.
> So effectively if there is a buggy DT for an IO resource we end up
> assuming that we are using a special IO device with unmapped addresses.
> 
> The patch at the bottom apply on top of this one and I think is a more
> reasonable approach

It was meant as a logical extension to the existing interface,
translating the address as far as we can, and reporting back
how far we got.

Maybe we can return 'of_root' by instead of NULL to signify
that we have converted all the way to the root of the DT?
That would make it more consistent, but slightly more complicated
for the common case.

> >   */
> >  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;
> > @@ -564,6 +568,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)
> > @@ -600,8 +605,9 @@ static u64 __of_translate_address(struct
> > device_node *dev,
> >  		pbus = of_match_bus(parent);
> >  		pbus->count_cells(dev, &pna, &pns);
> >  		if (!OF_CHECK_COUNTS(pna, pns)) {
> > -			pr_err("Bad cell count for %s\n",
> > -			       of_node_full_name(dev));
> > +			pr_debug("Bad cell count for %s\n",
> > +				 of_node_full_name(dev));
> > +			*host = of_node_get(parent);
> >  			break;
> >  		}
> > 
> > @@ -609,7 +615,9 @@ static u64 __of_translate_address(struct
> > device_node *dev,
> >  		    pbus->name, pna, pns, of_node_full_name(parent));
> > 
> >  		/* Apply bus translation */
> > -		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna,
> > rprop))
> > +		result = of_translate_one(dev, bus, pbus, addr, na, ns,
> > +					  pna, rprop);
> > +		if (result == OF_BAD_ADDR)
> 
> It seems to me that here you missed "*host = of_node_get(parent);"..?
> 

Yes, Zhichang also pointed out the same thing, this is not
right yet. My thought was that we need to check the #address-cells
and #size-cells of the parent node and return if they are not set,
but the bus should really have those.

What we need to do instead is check the "ranges" of the parent
and fail if there is no translation. Simply setting the host
here however won't work either because that leads to returning
OF_BAD_ADDR.


> >  		/* Complete the move up one level */
> > @@ -628,13 +636,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;
...
> > +
> >  phys_addr_t pci_pio_to_address(unsigned long pio)
> >  {
> >  	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
> > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > index 6bd94a803e8f..b7a8fa3da3ca 100644
> > --- a/include/linux/pci.h
> > +++ b/include/linux/pci.h
> > @@ -1192,7 +1192,8 @@ int __must_check pci_bus_alloc_resource(struct
> > pci_bus *bus,
> >  			void *alignf_data);

[Many lines of reply trimmed here, please make sure you don't quote too
much context when you reply, it's really annoying to read through
it otherwise]

>  /*
> + * of_isa_indirect_io - get the IO address from some isa reg property value.
> + *	For some isa/lpc devices, no ranges property in ancestor node.
> + *	The device addresses are described directly in their regs property.
> + *	This fixup function will be called to get the IO address of isa/lpc
> + *	devices when the normal of_translation failed.
> + *
> + * @parent:	points to the parent dts node;
> + * @bus:		points to the of_bus which can be used to parse address;
> + * @addr:	the address from reg property;
> + * @na:		the address cell counter of @addr;
> + * @presult:	store the address paresed from @addr;
> + *
> + * return 1 when successfully get the I/O address;
> + * 0 will return for some failures.
> + */
> +static int of_get_isa_indirect_io(struct device_node *parent,
> +				struct of_bus *bus, __be32 *addr,
> +				int na, u64 *presult)
> +{
> +	unsigned int flags;
> +	unsigned int rlen;
> +
> +	/* whether support indirectIO */
> +	if (!indirect_io_enabled())
> +		return 0;
> +
> +	if (!of_bus_isa_match(parent))
> +		return 0;
> +
> +	flags = bus->get_flags(addr);
> +	if (!(flags & IORESOURCE_IO))
> +		return 0;
> +
> +	/* there is ranges property, apply the normal translation directly. */
> +	if (of_get_property(parent, "ranges", &rlen))
> +		return 0;
> +
> +	*presult = of_read_number(addr + 1, na - 1);
> +	/* this fixup is only valid for specific I/O range. */
> +	return addr_is_indirect_io(*presult);
> +}

Right, this would work. The reason I didn't go down this route is
that I wanted to keep it generic enough to allow doing the same
for PCI host bridges with a nonlinear mapping of the I/O space.

There isn't really anything special about ISA here, other than the
fact that the one driver that needs it happens to be for ISA rather
than PCI.

> +/*
>   * Translate an address from the device-tree into a CPU physical address,
>   * this walks up the tree and applies the various bus mappings on the
>   * way.
> @@ -600,14 +643,23 @@ static u64 __of_translate_address(struct device_node *dev,
>  			result = of_read_number(addr, na);
>  			break;
>  		}
> +		/*
> +		 * For indirectIO device which has no ranges property, get
> +		 * the address from reg directly.
> +		 */
> +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> +			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
> +				of_node_full_name(dev), result);
> +			*host = of_node_get(parent);
> +			break;
> +		}
>  

If we do the special case for ISA as you suggest above, I would still want
to keep it in of_translate_ioport(), I think that's a useful change by
itself in my patch.

	Arnde

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-25 12:03                                                         ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-25 12:03 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: linux-arm-kernel, mark.rutland, catalin.marinas, linux-pci,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, T homas Petazzoni, linux-serial, benh,
	devicetree, minyard, will.deacon

On Friday, November 25, 2016 8:46:11 AM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > 
> > On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> > > On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni
> > wrote:
> > > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni
> >  /*
> > @@ -549,9 +548,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 lacks a tranlation, and the return code is relative to
> > + * that node.
> 
> This seems to be wrong to me. We are abusing of the error conditions.
> So effectively if there is a buggy DT for an IO resource we end up
> assuming that we are using a special IO device with unmapped addresses.
> 
> The patch at the bottom apply on top of this one and I think is a more
> reasonable approach

It was meant as a logical extension to the existing interface,
translating the address as far as we can, and reporting back
how far we got.

Maybe we can return 'of_root' by instead of NULL to signify
that we have converted all the way to the root of the DT?
That would make it more consistent, but slightly more complicated
for the common case.

> >   */
> >  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;
> > @@ -564,6 +568,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)
> > @@ -600,8 +605,9 @@ static u64 __of_translate_address(struct
> > device_node *dev,
> >  		pbus = of_match_bus(parent);
> >  		pbus->count_cells(dev, &pna, &pns);
> >  		if (!OF_CHECK_COUNTS(pna, pns)) {
> > -			pr_err("Bad cell count for %s\n",
> > -			       of_node_full_name(dev));
> > +			pr_debug("Bad cell count for %s\n",
> > +				 of_node_full_name(dev));
> > +			*host = of_node_get(parent);
> >  			break;
> >  		}
> > 
> > @@ -609,7 +615,9 @@ static u64 __of_translate_address(struct
> > device_node *dev,
> >  		    pbus->name, pna, pns, of_node_full_name(parent));
> > 
> >  		/* Apply bus translation */
> > -		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna,
> > rprop))
> > +		result = of_translate_one(dev, bus, pbus, addr, na, ns,
> > +					  pna, rprop);
> > +		if (result == OF_BAD_ADDR)
> 
> It seems to me that here you missed "*host = of_node_get(parent);"..?
> 

Yes, Zhichang also pointed out the same thing, this is not
right yet. My thought was that we need to check the #address-cells
and #size-cells of the parent node and return if they are not set,
but the bus should really have those.

What we need to do instead is check the "ranges" of the parent
and fail if there is no translation. Simply setting the host
here however won't work either because that leads to returning
OF_BAD_ADDR.


> >  		/* Complete the move up one level */
> > @@ -628,13 +636,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;
...
> > +
> >  phys_addr_t pci_pio_to_address(unsigned long pio)
> >  {
> >  	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
> > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > index 6bd94a803e8f..b7a8fa3da3ca 100644
> > --- a/include/linux/pci.h
> > +++ b/include/linux/pci.h
> > @@ -1192,7 +1192,8 @@ int __must_check pci_bus_alloc_resource(struct
> > pci_bus *bus,
> >  			void *alignf_data);

[Many lines of reply trimmed here, please make sure you don't quote too
much context when you reply, it's really annoying to read through
it otherwise]

>  /*
> + * of_isa_indirect_io - get the IO address from some isa reg property value.
> + *	For some isa/lpc devices, no ranges property in ancestor node.
> + *	The device addresses are described directly in their regs property.
> + *	This fixup function will be called to get the IO address of isa/lpc
> + *	devices when the normal of_translation failed.
> + *
> + * @parent:	points to the parent dts node;
> + * @bus:		points to the of_bus which can be used to parse address;
> + * @addr:	the address from reg property;
> + * @na:		the address cell counter of @addr;
> + * @presult:	store the address paresed from @addr;
> + *
> + * return 1 when successfully get the I/O address;
> + * 0 will return for some failures.
> + */
> +static int of_get_isa_indirect_io(struct device_node *parent,
> +				struct of_bus *bus, __be32 *addr,
> +				int na, u64 *presult)
> +{
> +	unsigned int flags;
> +	unsigned int rlen;
> +
> +	/* whether support indirectIO */
> +	if (!indirect_io_enabled())
> +		return 0;
> +
> +	if (!of_bus_isa_match(parent))
> +		return 0;
> +
> +	flags = bus->get_flags(addr);
> +	if (!(flags & IORESOURCE_IO))
> +		return 0;
> +
> +	/* there is ranges property, apply the normal translation directly. */
> +	if (of_get_property(parent, "ranges", &rlen))
> +		return 0;
> +
> +	*presult = of_read_number(addr + 1, na - 1);
> +	/* this fixup is only valid for specific I/O range. */
> +	return addr_is_indirect_io(*presult);
> +}

Right, this would work. The reason I didn't go down this route is
that I wanted to keep it generic enough to allow doing the same
for PCI host bridges with a nonlinear mapping of the I/O space.

There isn't really anything special about ISA here, other than the
fact that the one driver that needs it happens to be for ISA rather
than PCI.

> +/*
>   * Translate an address from the device-tree into a CPU physical address,
>   * this walks up the tree and applies the various bus mappings on the
>   * way.
> @@ -600,14 +643,23 @@ static u64 __of_translate_address(struct device_node *dev,
>  			result = of_read_number(addr, na);
>  			break;
>  		}
> +		/*
> +		 * For indirectIO device which has no ranges property, get
> +		 * the address from reg directly.
> +		 */
> +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> +			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
> +				of_node_full_name(dev), result);
> +			*host = of_node_get(parent);
> +			break;
> +		}
>  

If we do the special case for ISA as you suggest above, I would still want
to keep it in of_translate_ioport(), I think that's a useful change by
itself in my patch.

	Arnde

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

* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-25 12:03                                                         ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-25 12:03 UTC (permalink / raw)
  To: Gabriele Paoloni
  Cc: linux-arm-kernel, mark.rutland, catalin.marinas, linux-pci,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, T homas Petazzoni, linux-serial, benh,
	devicetree, minyard, will.deacon, John Garry, olof, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan02, linux-kernel,
	Yuanzhichang, zourongrong

On Friday, November 25, 2016 8:46:11 AM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > 
> > On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> > > On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni
> > wrote:
> > > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni
> >  /*
> > @@ -549,9 +548,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 lacks a tranlation, and the return code is relative to
> > + * that node.
> 
> This seems to be wrong to me. We are abusing of the error conditions.
> So effectively if there is a buggy DT for an IO resource we end up
> assuming that we are using a special IO device with unmapped addresses.
> 
> The patch at the bottom apply on top of this one and I think is a more
> reasonable approach

It was meant as a logical extension to the existing interface,
translating the address as far as we can, and reporting back
how far we got.

Maybe we can return 'of_root' by instead of NULL to signify
that we have converted all the way to the root of the DT?
That would make it more consistent, but slightly more complicated
for the common case.

> >   */
> >  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;
> > @@ -564,6 +568,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)
> > @@ -600,8 +605,9 @@ static u64 __of_translate_address(struct
> > device_node *dev,
> >  		pbus = of_match_bus(parent);
> >  		pbus->count_cells(dev, &pna, &pns);
> >  		if (!OF_CHECK_COUNTS(pna, pns)) {
> > -			pr_err("Bad cell count for %s\n",
> > -			       of_node_full_name(dev));
> > +			pr_debug("Bad cell count for %s\n",
> > +				 of_node_full_name(dev));
> > +			*host = of_node_get(parent);
> >  			break;
> >  		}
> > 
> > @@ -609,7 +615,9 @@ static u64 __of_translate_address(struct
> > device_node *dev,
> >  		    pbus->name, pna, pns, of_node_full_name(parent));
> > 
> >  		/* Apply bus translation */
> > -		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna,
> > rprop))
> > +		result = of_translate_one(dev, bus, pbus, addr, na, ns,
> > +					  pna, rprop);
> > +		if (result == OF_BAD_ADDR)
> 
> It seems to me that here you missed "*host = of_node_get(parent);"..?
> 

Yes, Zhichang also pointed out the same thing, this is not
right yet. My thought was that we need to check the #address-cells
and #size-cells of the parent node and return if they are not set,
but the bus should really have those.

What we need to do instead is check the "ranges" of the parent
and fail if there is no translation. Simply setting the host
here however won't work either because that leads to returning
OF_BAD_ADDR.


> >  		/* Complete the move up one level */
> > @@ -628,13 +636,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;
...
> > +
> >  phys_addr_t pci_pio_to_address(unsigned long pio)
> >  {
> >  	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
> > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > index 6bd94a803e8f..b7a8fa3da3ca 100644
> > --- a/include/linux/pci.h
> > +++ b/include/linux/pci.h
> > @@ -1192,7 +1192,8 @@ int __must_check pci_bus_alloc_resource(struct
> > pci_bus *bus,
> >  			void *alignf_data);

[Many lines of reply trimmed here, please make sure you don't quote too
much context when you reply, it's really annoying to read through
it otherwise]

>  /*
> + * of_isa_indirect_io - get the IO address from some isa reg property value.
> + *	For some isa/lpc devices, no ranges property in ancestor node.
> + *	The device addresses are described directly in their regs property.
> + *	This fixup function will be called to get the IO address of isa/lpc
> + *	devices when the normal of_translation failed.
> + *
> + * @parent:	points to the parent dts node;
> + * @bus:		points to the of_bus which can be used to parse address;
> + * @addr:	the address from reg property;
> + * @na:		the address cell counter of @addr;
> + * @presult:	store the address paresed from @addr;
> + *
> + * return 1 when successfully get the I/O address;
> + * 0 will return for some failures.
> + */
> +static int of_get_isa_indirect_io(struct device_node *parent,
> +				struct of_bus *bus, __be32 *addr,
> +				int na, u64 *presult)
> +{
> +	unsigned int flags;
> +	unsigned int rlen;
> +
> +	/* whether support indirectIO */
> +	if (!indirect_io_enabled())
> +		return 0;
> +
> +	if (!of_bus_isa_match(parent))
> +		return 0;
> +
> +	flags = bus->get_flags(addr);
> +	if (!(flags & IORESOURCE_IO))
> +		return 0;
> +
> +	/* there is ranges property, apply the normal translation directly. */
> +	if (of_get_property(parent, "ranges", &rlen))
> +		return 0;
> +
> +	*presult = of_read_number(addr + 1, na - 1);
> +	/* this fixup is only valid for specific I/O range. */
> +	return addr_is_indirect_io(*presult);
> +}

Right, this would work. The reason I didn't go down this route is
that I wanted to keep it generic enough to allow doing the same
for PCI host bridges with a nonlinear mapping of the I/O space.

There isn't really anything special about ISA here, other than the
fact that the one driver that needs it happens to be for ISA rather
than PCI.

> +/*
>   * Translate an address from the device-tree into a CPU physical address,
>   * this walks up the tree and applies the various bus mappings on the
>   * way.
> @@ -600,14 +643,23 @@ static u64 __of_translate_address(struct device_node *dev,
>  			result = of_read_number(addr, na);
>  			break;
>  		}
> +		/*
> +		 * For indirectIO device which has no ranges property, get
> +		 * the address from reg directly.
> +		 */
> +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> +			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
> +				of_node_full_name(dev), result);
> +			*host = of_node_get(parent);
> +			break;
> +		}
>  

If we do the special case for ISA as you suggest above, I would still want
to keep it in of_translate_ioport(), I think that's a useful change by
itself in my patch.

	Arnde





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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-25 12:03                                                         ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2016-11-25 12:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday, November 25, 2016 8:46:11 AM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > 
> > On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> > > On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni
> > wrote:
> > > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > > > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni
> >  /*
> > @@ -549,9 +548,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 lacks a tranlation, and the return code is relative to
> > + * that node.
> 
> This seems to be wrong to me. We are abusing of the error conditions.
> So effectively if there is a buggy DT for an IO resource we end up
> assuming that we are using a special IO device with unmapped addresses.
> 
> The patch at the bottom apply on top of this one and I think is a more
> reasonable approach

It was meant as a logical extension to the existing interface,
translating the address as far as we can, and reporting back
how far we got.

Maybe we can return 'of_root' by instead of NULL to signify
that we have converted all the way to the root of the DT?
That would make it more consistent, but slightly more complicated
for the common case.

> >   */
> >  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;
> > @@ -564,6 +568,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)
> > @@ -600,8 +605,9 @@ static u64 __of_translate_address(struct
> > device_node *dev,
> >  		pbus = of_match_bus(parent);
> >  		pbus->count_cells(dev, &pna, &pns);
> >  		if (!OF_CHECK_COUNTS(pna, pns)) {
> > -			pr_err("Bad cell count for %s\n",
> > -			       of_node_full_name(dev));
> > +			pr_debug("Bad cell count for %s\n",
> > +				 of_node_full_name(dev));
> > +			*host = of_node_get(parent);
> >  			break;
> >  		}
> > 
> > @@ -609,7 +615,9 @@ static u64 __of_translate_address(struct
> > device_node *dev,
> >  		    pbus->name, pna, pns, of_node_full_name(parent));
> > 
> >  		/* Apply bus translation */
> > -		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna,
> > rprop))
> > +		result = of_translate_one(dev, bus, pbus, addr, na, ns,
> > +					  pna, rprop);
> > +		if (result == OF_BAD_ADDR)
> 
> It seems to me that here you missed "*host = of_node_get(parent);"..?
> 

Yes, Zhichang also pointed out the same thing, this is not
right yet. My thought was that we need to check the #address-cells
and #size-cells of the parent node and return if they are not set,
but the bus should really have those.

What we need to do instead is check the "ranges" of the parent
and fail if there is no translation. Simply setting the host
here however won't work either because that leads to returning
OF_BAD_ADDR.


> >  		/* Complete the move up one level */
> > @@ -628,13 +636,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;
...
> > +
> >  phys_addr_t pci_pio_to_address(unsigned long pio)
> >  {
> >  	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
> > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > index 6bd94a803e8f..b7a8fa3da3ca 100644
> > --- a/include/linux/pci.h
> > +++ b/include/linux/pci.h
> > @@ -1192,7 +1192,8 @@ int __must_check pci_bus_alloc_resource(struct
> > pci_bus *bus,
> >  			void *alignf_data);

[Many lines of reply trimmed here, please make sure you don't quote too
much context when you reply, it's really annoying to read through
it otherwise]

>  /*
> + * of_isa_indirect_io - get the IO address from some isa reg property value.
> + *	For some isa/lpc devices, no ranges property in ancestor node.
> + *	The device addresses are described directly in their regs property.
> + *	This fixup function will be called to get the IO address of isa/lpc
> + *	devices when the normal of_translation failed.
> + *
> + * @parent:	points to the parent dts node;
> + * @bus:		points to the of_bus which can be used to parse address;
> + * @addr:	the address from reg property;
> + * @na:		the address cell counter of @addr;
> + * @presult:	store the address paresed from @addr;
> + *
> + * return 1 when successfully get the I/O address;
> + * 0 will return for some failures.
> + */
> +static int of_get_isa_indirect_io(struct device_node *parent,
> +				struct of_bus *bus, __be32 *addr,
> +				int na, u64 *presult)
> +{
> +	unsigned int flags;
> +	unsigned int rlen;
> +
> +	/* whether support indirectIO */
> +	if (!indirect_io_enabled())
> +		return 0;
> +
> +	if (!of_bus_isa_match(parent))
> +		return 0;
> +
> +	flags = bus->get_flags(addr);
> +	if (!(flags & IORESOURCE_IO))
> +		return 0;
> +
> +	/* there is ranges property, apply the normal translation directly. */
> +	if (of_get_property(parent, "ranges", &rlen))
> +		return 0;
> +
> +	*presult = of_read_number(addr + 1, na - 1);
> +	/* this fixup is only valid for specific I/O range. */
> +	return addr_is_indirect_io(*presult);
> +}

Right, this would work. The reason I didn't go down this route is
that I wanted to keep it generic enough to allow doing the same
for PCI host bridges with a nonlinear mapping of the I/O space.

There isn't really anything special about ISA here, other than the
fact that the one driver that needs it happens to be for ISA rather
than PCI.

> +/*
>   * Translate an address from the device-tree into a CPU physical address,
>   * this walks up the tree and applies the various bus mappings on the
>   * way.
> @@ -600,14 +643,23 @@ static u64 __of_translate_address(struct device_node *dev,
>  			result = of_read_number(addr, na);
>  			break;
>  		}
> +		/*
> +		 * For indirectIO device which has no ranges property, get
> +		 * the address from reg directly.
> +		 */
> +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> +			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
> +				of_node_full_name(dev), result);
> +			*host = of_node_get(parent);
> +			break;
> +		}
>  

If we do the special case for ISA as you suggest above, I would still want
to keep it in of_translate_ioport(), I think that's a useful change by
itself in my patch.

	Arnde

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
  2016-11-25 12:03                                                         ` Arnd Bergmann
  (?)
  (?)
@ 2016-11-25 16:27                                                           ` Gabriele Paoloni
  -1 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-25 16:27 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, mark.rutland, catalin.marinas, linux-pci,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, T homas Petazzoni, linux-serial, benh,
	devicetree, minyard, will.deacon, John Garry, olof, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan 02@gmail.com,
	linux-kernel, Yuanzhichang, zourongrong

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 25 November 2016 12:04
> To: Gabriele Paoloni
> Cc: linux-arm-kernel@lists.infradead.org; mark.rutland@arm.com;
> catalin.marinas@arm.com; linux-pci@vger.kernel.org;
> liviu.dudau@arm.com; Linuxarm; lorenzo.pieralisi@arm.com; xuwei (O);
> Jason Gunthorpe; T homas Petazzoni; linux-serial@vger.kernel.org;
> benh@kernel.crashing.org; devicetree@vger.kernel.org; minyard@acm.org;
> will.deacon@arm.com; John Garry; olof@lixom.net; robh+dt@kernel.org;
> bhelgaas@go og le.com; kantyzc@163.com; zhichang.yuan 02@gmail.com;
> linux-kernel@vger.kernel.org; Yuanzhichang; zourongrong@gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 25, 2016 8:46:11 AM CET Gabriele Paoloni wrote:
> > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > >
> > > On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> > > > On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni
> > > wrote:
> > > > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > > > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni
> > >  /*
> > > @@ -549,9 +548,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 lacks a tranlation, and the return code is relative
> to
> > > + * that node.
> >
> > This seems to be wrong to me. We are abusing of the error conditions.
> > So effectively if there is a buggy DT for an IO resource we end up
> > assuming that we are using a special IO device with unmapped
> addresses.
> >
> > The patch at the bottom apply on top of this one and I think is a
> more
> > reasonable approach
> 
> It was meant as a logical extension to the existing interface,
> translating the address as far as we can, and reporting back
> how far we got.
> 
> Maybe we can return 'of_root' by instead of NULL to signify
> that we have converted all the way to the root of the DT?
> That would make it more consistent, but slightly more complicated
> for the common case.

Mmm not sure really...the point is that now the **host parameter is
used both as a flag and also in of_translate_ioport...the problem
that I see is where we set the "host" parameter...I have a proposal
below...

[...]

> pci_bus_alloc_resource(struct
> > > pci_bus *bus,
> > >  			void *alignf_data);
> 
> [Many lines of reply trimmed here, please make sure you don't quote too
> much context when you reply, it's really annoying to read through
> it otherwise]

Sorry! I'll take care of this in the future...

> 
> >  /*
> > + * of_isa_indirect_io - get the IO address from some isa reg
> property value.
> > + *	For some isa/lpc devices, no ranges property in ancestor node.
> > + *	The device addresses are described directly in their regs
> property.
> > + *	This fixup function will be called to get the IO address of
> isa/lpc
> > + *	devices when the normal of_translation failed.
> > + *
> > + * @parent:	points to the parent dts node;
> > + * @bus:		points to the of_bus which can be used to parse
> address;
> > + * @addr:	the address from reg property;
> > + * @na:		the address cell counter of @addr;
> > + * @presult:	store the address paresed from @addr;
> > + *
> > + * return 1 when successfully get the I/O address;
> > + * 0 will return for some failures.
> > + */
> > +static int of_get_isa_indirect_io(struct device_node *parent,
> > +				struct of_bus *bus, __be32 *addr,
> > +				int na, u64 *presult)
> > +{
> > +	unsigned int flags;
> > +	unsigned int rlen;
> > +
> > +	/* whether support indirectIO */
> > +	if (!indirect_io_enabled())
> > +		return 0;
> > +
> > +	if (!of_bus_isa_match(parent))
> > +		return 0;
> > +
> > +	flags = bus->get_flags(addr);
> > +	if (!(flags & IORESOURCE_IO))
> > +		return 0;
> > +
> > +	/* there is ranges property, apply the normal translation
> directly. */
> > +	if (of_get_property(parent, "ranges", &rlen))
> > +		return 0;
> > +
> > +	*presult = of_read_number(addr + 1, na - 1);
> > +	/* this fixup is only valid for specific I/O range. */
> > +	return addr_is_indirect_io(*presult);
> > +}
> 
> Right, this would work. The reason I didn't go down this route is
> that I wanted to keep it generic enough to allow doing the same
> for PCI host bridges with a nonlinear mapping of the I/O space.
> 
> There isn't really anything special about ISA here, other than the
> fact that the one driver that needs it happens to be for ISA rather
> than PCI.

Yes I see your point please consider the patch at the bottom...

> 
> > +/*
> >   * Translate an address from the device-tree into a CPU physical
> address,
> >   * this walks up the tree and applies the various bus mappings on
> the
> >   * way.
> > @@ -600,14 +643,23 @@ static u64 __of_translate_address(struct
> device_node *dev,
> >  			result = of_read_number(addr, na);
> >  			break;
> >  		}
> > +		/*
> > +		 * For indirectIO device which has no ranges property, get
> > +		 * the address from reg directly.
> > +		 */
> > +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> > +			pr_debug("isa indirectIO matched(%s)..addr =
> 0x%llx\n",
> > +				of_node_full_name(dev), result);
> > +			*host = of_node_get(parent);
> > +			break;
> > +		}
> >
> 
> If we do the special case for ISA as you suggest above, I would still
> want
> to keep it in of_translate_ioport(), I think that's a useful change by
> itself in my patch.

This comes without saying...the patch I proposed here already applied on
top of your changes and, in fact, you can see that I set 
"*host = of_node_get(parent);" above in my patch to be used by 
of_translate_ioport()
 
> 
> 	Arnde
> 
> 
> 

Below I have reworked my patch (that still applies on top of your one) to
make it not ISA specific.
Notice that of_translate_ioport() still stands and that in addr_is_indirect_io()
we make sure the bus address to be in the bus address range that the special
host operates on...

---
 drivers/of/address.c       | 56 ++++++++++++++++++++++++++++++++++++++++++++--
 include/linux/of_address.h | 17 ++++++++++++++
 2 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 5decaba..2b34931 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -540,6 +540,48 @@ static u64 of_translate_one(struct device_node *parent, struct of_bus *bus,
 }
 
 /*
+ * of_get_indirect_io - get the IO address from some reg property value.
+ *	For some special host devices, we have no ranges property node and
+ *	we directly use the bus addresses of the children regs property.
+ *	This fixup function will be called to get the IO address of isa/lpc
+ *	devices when the normal of_translation failed.
+ *
+ * @parent:	points to the parent dts node;
+ * @bus:		points to the of_bus which can be used to parse address;
+ * @addr:	the address from reg property;
+ * @na:		the address cell counter of @addr;
+ * @presult:	store the address parsed from @addr;
+ *
+ * return 1 when successfully get the I/O address;
+ * 0 will return for some failures.
+ */
+static int of_get_indirect_io(struct device_node *parent,
+				struct of_bus *bus, __be32 *addr,
+				int na, u64 *presult)
+{
+	unsigned int flags;
+	unsigned int rlen;
+
+	/* whether support indirectIO */
+	if (!indirect_io_enabled())
+		return 0;
+
+	flags = bus->get_flags(addr);
+	if (!(flags & IORESOURCE_IO))
+		return 0;
+
+	/* there is ranges property, apply the normal translation directly. */
+	if (of_get_property(parent, "ranges", &rlen))
+		return 0;
+
+	*presult = of_read_number(addr + 1, na - 1);
+
+	/* check if the bus address falls into the range of
+	 * the special host device*/
+	return addr_is_indirect_io(*presult);
+}
+
+/*
  * Translate an address from the device-tree into a CPU physical address,
  * this walks up the tree and applies the various bus mappings on the
  * way.
@@ -601,13 +643,23 @@ static u64 __of_translate_address(struct device_node *dev,
 			break;
 		}
 
+		/*
+		 * For indirectIO device which has no ranges property, get
+		 * the address from reg directly.
+		 */
+		if (of_get_indirect_io(dev, bus, addr, na, &result)) {
+			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
+				of_node_full_name(dev), result);
+			*host = of_node_get(parent);
+			break;
+		}
+
 		/* Get new parent bus and counts */
 		pbus = of_match_bus(parent);
 		pbus->count_cells(dev, &pna, &pns);
 		if (!OF_CHECK_COUNTS(pna, pns)) {
-			pr_debug("Bad cell count for %s\n",
+			pr_err("Bad cell count for %s\n",
 				 of_node_full_name(dev));
-			*host = of_node_get(parent);
 			break;
 		}
 
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 3786473..14848d8 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -24,6 +24,23 @@ struct of_pci_range {
 #define for_each_of_pci_range(parser, range) \
 	for (; of_pci_range_parser_one(parser, range);)
 
+#ifndef indirect_io_enabled
+#define indirect_io_enabled indirect_io_enabled
+static inline bool indirect_io_enabled(void)
+{
+	return false;
+}
+#endif
+
+#ifndef addr_is_indirect_io
+#define addr_is_indirect_io addr_is_indirect_io
+static inline int addr_is_indirect_io(u64 taddr)
+{
+	return 0;
+}
+#endif
+
+
 /* 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.7.4

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-25 16:27                                                           ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-25 16:27 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: mark.rutland, benh, liviu.dudau, Linuxarm, lorenzo.pieralisi,
	xuwei (O),
	Jason Gunthorpe, T homas Petazzoni, linux-serial,
	catalin.marinas, devicetree, minyard, will.deacon, John Garry,
	zourongrong, robh+dt, bhelgaas@go og le.com, kantyzc,
	zhichang.yuan

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 25 November 2016 12:04
> To: Gabriele Paoloni
> Cc: linux-arm-kernel@lists.infradead.org; mark.rutland@arm.com;
> catalin.marinas@arm.com; linux-pci@vger.kernel.org;
> liviu.dudau@arm.com; Linuxarm; lorenzo.pieralisi@arm.com; xuwei (O);
> Jason Gunthorpe; T homas Petazzoni; linux-serial@vger.kernel.org;
> benh@kernel.crashing.org; devicetree@vger.kernel.org; minyard@acm.org;
> will.deacon@arm.com; John Garry; olof@lixom.net; robh+dt@kernel.org;
> bhelgaas@go og le.com; kantyzc@163.com; zhichang.yuan 02@gmail.com;
> linux-kernel@vger.kernel.org; Yuanzhichang; zourongrong@gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 25, 2016 8:46:11 AM CET Gabriele Paoloni wrote:
> > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > >
> > > On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> > > > On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni
> > > wrote:
> > > > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > > > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni
> > >  /*
> > > @@ -549,9 +548,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 lacks a tranlation, and the return code is relative
> to
> > > + * that node.
> >
> > This seems to be wrong to me. We are abusing of the error conditions.
> > So effectively if there is a buggy DT for an IO resource we end up
> > assuming that we are using a special IO device with unmapped
> addresses.
> >
> > The patch at the bottom apply on top of this one and I think is a
> more
> > reasonable approach
> 
> It was meant as a logical extension to the existing interface,
> translating the address as far as we can, and reporting back
> how far we got.
> 
> Maybe we can return 'of_root' by instead of NULL to signify
> that we have converted all the way to the root of the DT?
> That would make it more consistent, but slightly more complicated
> for the common case.

Mmm not sure really...the point is that now the **host parameter is
used both as a flag and also in of_translate_ioport...the problem
that I see is where we set the "host" parameter...I have a proposal
below...

[...]

> pci_bus_alloc_resource(struct
> > > pci_bus *bus,
> > >  			void *alignf_data);
> 
> [Many lines of reply trimmed here, please make sure you don't quote too
> much context when you reply, it's really annoying to read through
> it otherwise]

Sorry! I'll take care of this in the future...

> 
> >  /*
> > + * of_isa_indirect_io - get the IO address from some isa reg
> property value.
> > + *	For some isa/lpc devices, no ranges property in ancestor node.
> > + *	The device addresses are described directly in their regs
> property.
> > + *	This fixup function will be called to get the IO address of
> isa/lpc
> > + *	devices when the normal of_translation failed.
> > + *
> > + * @parent:	points to the parent dts node;
> > + * @bus:		points to the of_bus which can be used to parse
> address;
> > + * @addr:	the address from reg property;
> > + * @na:		the address cell counter of @addr;
> > + * @presult:	store the address paresed from @addr;
> > + *
> > + * return 1 when successfully get the I/O address;
> > + * 0 will return for some failures.
> > + */
> > +static int of_get_isa_indirect_io(struct device_node *parent,
> > +				struct of_bus *bus, __be32 *addr,
> > +				int na, u64 *presult)
> > +{
> > +	unsigned int flags;
> > +	unsigned int rlen;
> > +
> > +	/* whether support indirectIO */
> > +	if (!indirect_io_enabled())
> > +		return 0;
> > +
> > +	if (!of_bus_isa_match(parent))
> > +		return 0;
> > +
> > +	flags = bus->get_flags(addr);
> > +	if (!(flags & IORESOURCE_IO))
> > +		return 0;
> > +
> > +	/* there is ranges property, apply the normal translation
> directly. */
> > +	if (of_get_property(parent, "ranges", &rlen))
> > +		return 0;
> > +
> > +	*presult = of_read_number(addr + 1, na - 1);
> > +	/* this fixup is only valid for specific I/O range. */
> > +	return addr_is_indirect_io(*presult);
> > +}
> 
> Right, this would work. The reason I didn't go down this route is
> that I wanted to keep it generic enough to allow doing the same
> for PCI host bridges with a nonlinear mapping of the I/O space.
> 
> There isn't really anything special about ISA here, other than the
> fact that the one driver that needs it happens to be for ISA rather
> than PCI.

Yes I see your point please consider the patch at the bottom...

> 
> > +/*
> >   * Translate an address from the device-tree into a CPU physical
> address,
> >   * this walks up the tree and applies the various bus mappings on
> the
> >   * way.
> > @@ -600,14 +643,23 @@ static u64 __of_translate_address(struct
> device_node *dev,
> >  			result = of_read_number(addr, na);
> >  			break;
> >  		}
> > +		/*
> > +		 * For indirectIO device which has no ranges property, get
> > +		 * the address from reg directly.
> > +		 */
> > +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> > +			pr_debug("isa indirectIO matched(%s)..addr =
> 0x%llx\n",
> > +				of_node_full_name(dev), result);
> > +			*host = of_node_get(parent);
> > +			break;
> > +		}
> >
> 
> If we do the special case for ISA as you suggest above, I would still
> want
> to keep it in of_translate_ioport(), I think that's a useful change by
> itself in my patch.

This comes without saying...the patch I proposed here already applied on
top of your changes and, in fact, you can see that I set 
"*host = of_node_get(parent);" above in my patch to be used by 
of_translate_ioport()
 
> 
> 	Arnde
> 
> 
> 

Below I have reworked my patch (that still applies on top of your one) to
make it not ISA specific.
Notice that of_translate_ioport() still stands and that in addr_is_indirect_io()
we make sure the bus address to be in the bus address range that the special
host operates on...

---
 drivers/of/address.c       | 56 ++++++++++++++++++++++++++++++++++++++++++++--
 include/linux/of_address.h | 17 ++++++++++++++
 2 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 5decaba..2b34931 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -540,6 +540,48 @@ static u64 of_translate_one(struct device_node *parent, struct of_bus *bus,
 }
 
 /*
+ * of_get_indirect_io - get the IO address from some reg property value.
+ *	For some special host devices, we have no ranges property node and
+ *	we directly use the bus addresses of the children regs property.
+ *	This fixup function will be called to get the IO address of isa/lpc
+ *	devices when the normal of_translation failed.
+ *
+ * @parent:	points to the parent dts node;
+ * @bus:		points to the of_bus which can be used to parse address;
+ * @addr:	the address from reg property;
+ * @na:		the address cell counter of @addr;
+ * @presult:	store the address parsed from @addr;
+ *
+ * return 1 when successfully get the I/O address;
+ * 0 will return for some failures.
+ */
+static int of_get_indirect_io(struct device_node *parent,
+				struct of_bus *bus, __be32 *addr,
+				int na, u64 *presult)
+{
+	unsigned int flags;
+	unsigned int rlen;
+
+	/* whether support indirectIO */
+	if (!indirect_io_enabled())
+		return 0;
+
+	flags = bus->get_flags(addr);
+	if (!(flags & IORESOURCE_IO))
+		return 0;
+
+	/* there is ranges property, apply the normal translation directly. */
+	if (of_get_property(parent, "ranges", &rlen))
+		return 0;
+
+	*presult = of_read_number(addr + 1, na - 1);
+
+	/* check if the bus address falls into the range of
+	 * the special host device*/
+	return addr_is_indirect_io(*presult);
+}
+
+/*
  * Translate an address from the device-tree into a CPU physical address,
  * this walks up the tree and applies the various bus mappings on the
  * way.
@@ -601,13 +643,23 @@ static u64 __of_translate_address(struct device_node *dev,
 			break;
 		}
 
+		/*
+		 * For indirectIO device which has no ranges property, get
+		 * the address from reg directly.
+		 */
+		if (of_get_indirect_io(dev, bus, addr, na, &result)) {
+			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
+				of_node_full_name(dev), result);
+			*host = of_node_get(parent);
+			break;
+		}
+
 		/* Get new parent bus and counts */
 		pbus = of_match_bus(parent);
 		pbus->count_cells(dev, &pna, &pns);
 		if (!OF_CHECK_COUNTS(pna, pns)) {
-			pr_debug("Bad cell count for %s\n",
+			pr_err("Bad cell count for %s\n",
 				 of_node_full_name(dev));
-			*host = of_node_get(parent);
 			break;
 		}
 
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 3786473..14848d8 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -24,6 +24,23 @@ struct of_pci_range {
 #define for_each_of_pci_range(parser, range) \
 	for (; of_pci_range_parser_one(parser, range);)
 
+#ifndef indirect_io_enabled
+#define indirect_io_enabled indirect_io_enabled
+static inline bool indirect_io_enabled(void)
+{
+	return false;
+}
+#endif
+
+#ifndef addr_is_indirect_io
+#define addr_is_indirect_io addr_is_indirect_io
+static inline int addr_is_indirect_io(u64 taddr)
+{
+	return 0;
+}
+#endif
+
+
 /* 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.7.4

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

* RE: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-25 16:27                                                           ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-25 16:27 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, mark.rutland, catalin.marinas, linux-pci,
	liviu.dudau, Linuxarm, lorenzo.pieralisi, xuwei (O),
	Jason Gunthorpe, T homas Petazzoni, linux-serial, benh,
	devicetree, minyard, will.deacon, John Garry, olof, robh+dt,
	bhelgaas@go og le.com, kantyzc, zhichang.yuan 02@gmail.com,
	linux-kernel, Yuanzhichang, zourongrong

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: 25 November 2016 12:04
> To: Gabriele Paoloni
> Cc: linux-arm-kernel@lists.infradead.org; mark.rutland@arm.com;
> catalin.marinas@arm.com; linux-pci@vger.kernel.org;
> liviu.dudau@arm.com; Linuxarm; lorenzo.pieralisi@arm.com; xuwei (O);
> Jason Gunthorpe; T homas Petazzoni; linux-serial@vger.kernel.org;
> benh@kernel.crashing.org; devicetree@vger.kernel.org; minyard@acm.org;
> will.deacon@arm.com; John Garry; olof@lixom.net; robh+dt@kernel.org;
> bhelgaas@go og le.com; kantyzc@163.com; zhichang.yuan 02@gmail.com;
> linux-kernel@vger.kernel.org; Yuanzhichang; zourongrong@gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 25, 2016 8:46:11 AM CET Gabriele Paoloni wrote:
> > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > >
> > > On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> > > > On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni
> > > wrote:
> > > > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > > > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni
> > >  /*
> > > @@ -549,9 +548,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 lacks a tranlation, and the return code is relative
> to
> > > + * that node.
> >
> > This seems to be wrong to me. We are abusing of the error conditions.
> > So effectively if there is a buggy DT for an IO resource we end up
> > assuming that we are using a special IO device with unmapped
> addresses.
> >
> > The patch at the bottom apply on top of this one and I think is a
> more
> > reasonable approach
> 
> It was meant as a logical extension to the existing interface,
> translating the address as far as we can, and reporting back
> how far we got.
> 
> Maybe we can return 'of_root' by instead of NULL to signify
> that we have converted all the way to the root of the DT?
> That would make it more consistent, but slightly more complicated
> for the common case.

Mmm not sure really...the point is that now the **host parameter is
used both as a flag and also in of_translate_ioport...the problem
that I see is where we set the "host" parameter...I have a proposal
below...

[...]

> pci_bus_alloc_resource(struct
> > > pci_bus *bus,
> > >  			void *alignf_data);
> 
> [Many lines of reply trimmed here, please make sure you don't quote too
> much context when you reply, it's really annoying to read through
> it otherwise]

Sorry! I'll take care of this in the future...

> 
> >  /*
> > + * of_isa_indirect_io - get the IO address from some isa reg
> property value.
> > + *	For some isa/lpc devices, no ranges property in ancestor node.
> > + *	The device addresses are described directly in their regs
> property.
> > + *	This fixup function will be called to get the IO address of
> isa/lpc
> > + *	devices when the normal of_translation failed.
> > + *
> > + * @parent:	points to the parent dts node;
> > + * @bus:		points to the of_bus which can be used to parse
> address;
> > + * @addr:	the address from reg property;
> > + * @na:		the address cell counter of @addr;
> > + * @presult:	store the address paresed from @addr;
> > + *
> > + * return 1 when successfully get the I/O address;
> > + * 0 will return for some failures.
> > + */
> > +static int of_get_isa_indirect_io(struct device_node *parent,
> > +				struct of_bus *bus, __be32 *addr,
> > +				int na, u64 *presult)
> > +{
> > +	unsigned int flags;
> > +	unsigned int rlen;
> > +
> > +	/* whether support indirectIO */
> > +	if (!indirect_io_enabled())
> > +		return 0;
> > +
> > +	if (!of_bus_isa_match(parent))
> > +		return 0;
> > +
> > +	flags = bus->get_flags(addr);
> > +	if (!(flags & IORESOURCE_IO))
> > +		return 0;
> > +
> > +	/* there is ranges property, apply the normal translation
> directly. */
> > +	if (of_get_property(parent, "ranges", &rlen))
> > +		return 0;
> > +
> > +	*presult = of_read_number(addr + 1, na - 1);
> > +	/* this fixup is only valid for specific I/O range. */
> > +	return addr_is_indirect_io(*presult);
> > +}
> 
> Right, this would work. The reason I didn't go down this route is
> that I wanted to keep it generic enough to allow doing the same
> for PCI host bridges with a nonlinear mapping of the I/O space.
> 
> There isn't really anything special about ISA here, other than the
> fact that the one driver that needs it happens to be for ISA rather
> than PCI.

Yes I see your point please consider the patch at the bottom...

> 
> > +/*
> >   * Translate an address from the device-tree into a CPU physical
> address,
> >   * this walks up the tree and applies the various bus mappings on
> the
> >   * way.
> > @@ -600,14 +643,23 @@ static u64 __of_translate_address(struct
> device_node *dev,
> >  			result = of_read_number(addr, na);
> >  			break;
> >  		}
> > +		/*
> > +		 * For indirectIO device which has no ranges property, get
> > +		 * the address from reg directly.
> > +		 */
> > +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> > +			pr_debug("isa indirectIO matched(%s)..addr =
> 0x%llx\n",
> > +				of_node_full_name(dev), result);
> > +			*host = of_node_get(parent);
> > +			break;
> > +		}
> >
> 
> If we do the special case for ISA as you suggest above, I would still
> want
> to keep it in of_translate_ioport(), I think that's a useful change by
> itself in my patch.

This comes without saying...the patch I proposed here already applied on
top of your changes and, in fact, you can see that I set 
"*host = of_node_get(parent);" above in my patch to be used by 
of_translate_ioport()
 
> 
> 	Arnde
> 
> 
> 

Below I have reworked my patch (that still applies on top of your one) to
make it not ISA specific.
Notice that of_translate_ioport() still stands and that in addr_is_indirect_io()
we make sure the bus address to be in the bus address range that the special
host operates on...

---
 drivers/of/address.c       | 56 ++++++++++++++++++++++++++++++++++++++++++++--
 include/linux/of_address.h | 17 ++++++++++++++
 2 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 5decaba..2b34931 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -540,6 +540,48 @@ static u64 of_translate_one(struct device_node *parent, struct of_bus *bus,
 }
 
 /*
+ * of_get_indirect_io - get the IO address from some reg property value.
+ *	For some special host devices, we have no ranges property node and
+ *	we directly use the bus addresses of the children regs property.
+ *	This fixup function will be called to get the IO address of isa/lpc
+ *	devices when the normal of_translation failed.
+ *
+ * @parent:	points to the parent dts node;
+ * @bus:		points to the of_bus which can be used to parse address;
+ * @addr:	the address from reg property;
+ * @na:		the address cell counter of @addr;
+ * @presult:	store the address parsed from @addr;
+ *
+ * return 1 when successfully get the I/O address;
+ * 0 will return for some failures.
+ */
+static int of_get_indirect_io(struct device_node *parent,
+				struct of_bus *bus, __be32 *addr,
+				int na, u64 *presult)
+{
+	unsigned int flags;
+	unsigned int rlen;
+
+	/* whether support indirectIO */
+	if (!indirect_io_enabled())
+		return 0;
+
+	flags = bus->get_flags(addr);
+	if (!(flags & IORESOURCE_IO))
+		return 0;
+
+	/* there is ranges property, apply the normal translation directly. */
+	if (of_get_property(parent, "ranges", &rlen))
+		return 0;
+
+	*presult = of_read_number(addr + 1, na - 1);
+
+	/* check if the bus address falls into the range of
+	 * the special host device*/
+	return addr_is_indirect_io(*presult);
+}
+
+/*
  * Translate an address from the device-tree into a CPU physical address,
  * this walks up the tree and applies the various bus mappings on the
  * way.
@@ -601,13 +643,23 @@ static u64 __of_translate_address(struct device_node *dev,
 			break;
 		}
 
+		/*
+		 * For indirectIO device which has no ranges property, get
+		 * the address from reg directly.
+		 */
+		if (of_get_indirect_io(dev, bus, addr, na, &result)) {
+			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
+				of_node_full_name(dev), result);
+			*host = of_node_get(parent);
+			break;
+		}
+
 		/* Get new parent bus and counts */
 		pbus = of_match_bus(parent);
 		pbus->count_cells(dev, &pna, &pns);
 		if (!OF_CHECK_COUNTS(pna, pns)) {
-			pr_debug("Bad cell count for %s\n",
+			pr_err("Bad cell count for %s\n",
 				 of_node_full_name(dev));
-			*host = of_node_get(parent);
 			break;
 		}
 
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 3786473..14848d8 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -24,6 +24,23 @@ struct of_pci_range {
 #define for_each_of_pci_range(parser, range) \
 	for (; of_pci_range_parser_one(parser, range);)
 
+#ifndef indirect_io_enabled
+#define indirect_io_enabled indirect_io_enabled
+static inline bool indirect_io_enabled(void)
+{
+	return false;
+}
+#endif
+
+#ifndef addr_is_indirect_io
+#define addr_is_indirect_io addr_is_indirect_io
+static inline int addr_is_indirect_io(u64 taddr)
+{
+	return 0;
+}
+#endif
+
+
 /* 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.7.4




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

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
@ 2016-11-25 16:27                                                           ` Gabriele Paoloni
  0 siblings, 0 replies; 286+ messages in thread
From: Gabriele Paoloni @ 2016-11-25 16:27 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd

> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: 25 November 2016 12:04
> To: Gabriele Paoloni
> Cc: linux-arm-kernel at lists.infradead.org; mark.rutland at arm.com;
> catalin.marinas at arm.com; linux-pci at vger.kernel.org;
> liviu.dudau at arm.com; Linuxarm; lorenzo.pieralisi at arm.com; xuwei (O);
> Jason Gunthorpe; T homas Petazzoni; linux-serial at vger.kernel.org;
> benh at kernel.crashing.org; devicetree at vger.kernel.org; minyard at acm.org;
> will.deacon at arm.com; John Garry; olof at lixom.net; robh+dt at kernel.org;
> bhelgaas at go og le.com; kantyzc at 163.com; zhichang.yuan 02 at gmail.com;
> linux-kernel at vger.kernel.org; Yuanzhichang; zourongrong at gmail.com
> Subject: Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on
> Hip06
> 
> On Friday, November 25, 2016 8:46:11 AM CET Gabriele Paoloni wrote:
> > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > >
> > > On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> > > > On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni
> > > wrote:
> > > > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > > > > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni
> > >  /*
> > > @@ -549,9 +548,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 lacks a tranlation, and the return code is relative
> to
> > > + * that node.
> >
> > This seems to be wrong to me. We are abusing of the error conditions.
> > So effectively if there is a buggy DT for an IO resource we end up
> > assuming that we are using a special IO device with unmapped
> addresses.
> >
> > The patch at the bottom apply on top of this one and I think is a
> more
> > reasonable approach
> 
> It was meant as a logical extension to the existing interface,
> translating the address as far as we can, and reporting back
> how far we got.
> 
> Maybe we can return 'of_root' by instead of NULL to signify
> that we have converted all the way to the root of the DT?
> That would make it more consistent, but slightly more complicated
> for the common case.

Mmm not sure really...the point is that now the **host parameter is
used both as a flag and also in of_translate_ioport...the problem
that I see is where we set the "host" parameter...I have a proposal
below...

[...]

> pci_bus_alloc_resource(struct
> > > pci_bus *bus,
> > >  			void *alignf_data);
> 
> [Many lines of reply trimmed here, please make sure you don't quote too
> much context when you reply, it's really annoying to read through
> it otherwise]

Sorry! I'll take care of this in the future...

> 
> >  /*
> > + * of_isa_indirect_io - get the IO address from some isa reg
> property value.
> > + *	For some isa/lpc devices, no ranges property in ancestor node.
> > + *	The device addresses are described directly in their regs
> property.
> > + *	This fixup function will be called to get the IO address of
> isa/lpc
> > + *	devices when the normal of_translation failed.
> > + *
> > + * @parent:	points to the parent dts node;
> > + * @bus:		points to the of_bus which can be used to parse
> address;
> > + * @addr:	the address from reg property;
> > + * @na:		the address cell counter of @addr;
> > + * @presult:	store the address paresed from @addr;
> > + *
> > + * return 1 when successfully get the I/O address;
> > + * 0 will return for some failures.
> > + */
> > +static int of_get_isa_indirect_io(struct device_node *parent,
> > +				struct of_bus *bus, __be32 *addr,
> > +				int na, u64 *presult)
> > +{
> > +	unsigned int flags;
> > +	unsigned int rlen;
> > +
> > +	/* whether support indirectIO */
> > +	if (!indirect_io_enabled())
> > +		return 0;
> > +
> > +	if (!of_bus_isa_match(parent))
> > +		return 0;
> > +
> > +	flags = bus->get_flags(addr);
> > +	if (!(flags & IORESOURCE_IO))
> > +		return 0;
> > +
> > +	/* there is ranges property, apply the normal translation
> directly. */
> > +	if (of_get_property(parent, "ranges", &rlen))
> > +		return 0;
> > +
> > +	*presult = of_read_number(addr + 1, na - 1);
> > +	/* this fixup is only valid for specific I/O range. */
> > +	return addr_is_indirect_io(*presult);
> > +}
> 
> Right, this would work. The reason I didn't go down this route is
> that I wanted to keep it generic enough to allow doing the same
> for PCI host bridges with a nonlinear mapping of the I/O space.
> 
> There isn't really anything special about ISA here, other than the
> fact that the one driver that needs it happens to be for ISA rather
> than PCI.

Yes I see your point please consider the patch at the bottom...

> 
> > +/*
> >   * Translate an address from the device-tree into a CPU physical
> address,
> >   * this walks up the tree and applies the various bus mappings on
> the
> >   * way.
> > @@ -600,14 +643,23 @@ static u64 __of_translate_address(struct
> device_node *dev,
> >  			result = of_read_number(addr, na);
> >  			break;
> >  		}
> > +		/*
> > +		 * For indirectIO device which has no ranges property, get
> > +		 * the address from reg directly.
> > +		 */
> > +		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> > +			pr_debug("isa indirectIO matched(%s)..addr =
> 0x%llx\n",
> > +				of_node_full_name(dev), result);
> > +			*host = of_node_get(parent);
> > +			break;
> > +		}
> >
> 
> If we do the special case for ISA as you suggest above, I would still
> want
> to keep it in of_translate_ioport(), I think that's a useful change by
> itself in my patch.

This comes without saying...the patch I proposed here already applied on
top of your changes and, in fact, you can see that I set 
"*host = of_node_get(parent);" above in my patch to be used by 
of_translate_ioport()
 
> 
> 	Arnde
> 
> 
> 

Below I have reworked my patch (that still applies on top of your one) to
make it not ISA specific.
Notice that of_translate_ioport() still stands and that in addr_is_indirect_io()
we make sure the bus address to be in the bus address range that the special
host operates on...

---
 drivers/of/address.c       | 56 ++++++++++++++++++++++++++++++++++++++++++++--
 include/linux/of_address.h | 17 ++++++++++++++
 2 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 5decaba..2b34931 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -540,6 +540,48 @@ static u64 of_translate_one(struct device_node *parent, struct of_bus *bus,
 }
 
 /*
+ * of_get_indirect_io - get the IO address from some reg property value.
+ *	For some special host devices, we have no ranges property node and
+ *	we directly use the bus addresses of the children regs property.
+ *	This fixup function will be called to get the IO address of isa/lpc
+ *	devices when the normal of_translation failed.
+ *
+ * @parent:	points to the parent dts node;
+ * @bus:		points to the of_bus which can be used to parse address;
+ * @addr:	the address from reg property;
+ * @na:		the address cell counter of @addr;
+ * @presult:	store the address parsed from @addr;
+ *
+ * return 1 when successfully get the I/O address;
+ * 0 will return for some failures.
+ */
+static int of_get_indirect_io(struct device_node *parent,
+				struct of_bus *bus, __be32 *addr,
+				int na, u64 *presult)
+{
+	unsigned int flags;
+	unsigned int rlen;
+
+	/* whether support indirectIO */
+	if (!indirect_io_enabled())
+		return 0;
+
+	flags = bus->get_flags(addr);
+	if (!(flags & IORESOURCE_IO))
+		return 0;
+
+	/* there is ranges property, apply the normal translation directly. */
+	if (of_get_property(parent, "ranges", &rlen))
+		return 0;
+
+	*presult = of_read_number(addr + 1, na - 1);
+
+	/* check if the bus address falls into the range of
+	 * the special host device*/
+	return addr_is_indirect_io(*presult);
+}
+
+/*
  * Translate an address from the device-tree into a CPU physical address,
  * this walks up the tree and applies the various bus mappings on the
  * way.
@@ -601,13 +643,23 @@ static u64 __of_translate_address(struct device_node *dev,
 			break;
 		}
 
+		/*
+		 * For indirectIO device which has no ranges property, get
+		 * the address from reg directly.
+		 */
+		if (of_get_indirect_io(dev, bus, addr, na, &result)) {
+			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
+				of_node_full_name(dev), result);
+			*host = of_node_get(parent);
+			break;
+		}
+
 		/* Get new parent bus and counts */
 		pbus = of_match_bus(parent);
 		pbus->count_cells(dev, &pna, &pns);
 		if (!OF_CHECK_COUNTS(pna, pns)) {
-			pr_debug("Bad cell count for %s\n",
+			pr_err("Bad cell count for %s\n",
 				 of_node_full_name(dev));
-			*host = of_node_get(parent);
 			break;
 		}
 
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 3786473..14848d8 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -24,6 +24,23 @@ struct of_pci_range {
 #define for_each_of_pci_range(parser, range) \
 	for (; of_pci_range_parser_one(parser, range);)
 
+#ifndef indirect_io_enabled
+#define indirect_io_enabled indirect_io_enabled
+static inline bool indirect_io_enabled(void)
+{
+	return false;
+}
+#endif
+
+#ifndef addr_is_indirect_io
+#define addr_is_indirect_io addr_is_indirect_io
+static inline int addr_is_indirect_io(u64 taddr)
+{
+	return 0;
+}
+#endif
+
+
 /* 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.7.4

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-11-08  3:47   ` zhichang.yuan
  (?)
  (?)
@ 2016-12-22  8:15     ` Ming Lei
  -1 siblings, 0 replies; 286+ messages in thread
From: Ming Lei @ 2016-12-22  8:15 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: Catalin Marinas, Will Deacon, Rob Herring, Bjorn Helgaas,
	Mark Rutland, Olof Johansson, Arnd Bergmann, linux-arm-kernel,
	Lorenzo Pieralisi, Linux Kernel Mailing List, linuxarm,
	devicetree, linux-pci, linux-serial, minyard,
	Benjamin Herrenschmidt, Liviu Dudau, zourongrong, john.garry,
	gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5

Hi Guys,

On Tue, Nov 8, 2016 at 11:47 AM, zhichang.yuan
<yuanzhichang@hisilicon.com> wrote:
> For arm64, there is no I/O space as other architectural platforms, such as
> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> known port addresses are used to control the corresponding target devices, for
> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> normal MMIO mode in using.
>
> To drive these devices, this patch introduces a method named indirect-IO.
> In this method the in/out pair in arch/arm64/include/asm/io.h will be
> redefined. When upper layer drivers call in/out with those known legacy port
> addresses to access the peripherals, the hooking functions corrresponding to
> those target peripherals will be called. Through this way, those upper layer
> drivers which depend on in/out can run on Hip06 without any changes.
>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
>  arch/arm64/Kconfig             |  6 +++
>  arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>  arch/arm64/include/asm/io.h    | 29 +++++++++++++
>  arch/arm64/kernel/Makefile     |  1 +
>  arch/arm64/kernel/extio.c      | 27 ++++++++++++
>  5 files changed, 157 insertions(+)

When I applied these three patches against current linus tree and
enable CONFIG_HISILICON_LPC, the following build failure[1] is
triggered when running 'make modules'.


Thanks,
Ming

[1] 'make modules' failure log

  Building modules, stage 2.
  MODPOST 2260 modules
ERROR: "inb" [drivers/watchdog/wdt_pci.ko] undefined!
ERROR: "outb" [drivers/watchdog/wdt_pci.ko] undefined!
ERROR: "outb" [drivers/watchdog/pcwd_pci.ko] undefined!
ERROR: "inb" [drivers/watchdog/pcwd_pci.ko] undefined!
ERROR: "outw" [drivers/video/vgastate.ko] undefined!
ERROR: "outb" [drivers/video/vgastate.ko] undefined!
ERROR: "inb" [drivers/video/vgastate.ko] undefined!
ERROR: "outw" [drivers/video/fbdev/vt8623fb.ko] undefined!
ERROR: "inb" [drivers/video/fbdev/vt8623fb.ko] undefined!
ERROR: "outb" [drivers/video/fbdev/vt8623fb.ko] undefined!
ERROR: "outw" [drivers/video/fbdev/tridentfb.ko] undefined!
ERROR: "inb" [drivers/video/fbdev/tridentfb.ko] undefined!
ERROR: "outb" [drivers/video/fbdev/tridentfb.ko] undefined!
ERROR: "inb" [drivers/video/fbdev/tdfxfb.ko] undefined!
.....
ERROR: "inb" [drivers/ata/pata_cmd64x.ko] undefined!
ERROR: "inb" [drivers/ata/pata_artop.ko] undefined!
scripts/Makefile.modpost:91: recipe for target '__modpost' failed
make[1]: *** [__modpost] Error 1
Makefile:1196: recipe for target 'modules' failed
make: *** [modules] Error 2


>  create mode 100644 arch/arm64/include/asm/extio.h
>  create mode 100644 arch/arm64/kernel/extio.c
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 969ef88..b44070b 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>         default 16
>
> +config ARM64_INDIRECT_PIO
> +       bool "access peripherals with legacy I/O port"
> +       help
> +         Support special accessors for ISA I/O devices. This is needed for
> +         SoCs that do not support standard read/write for the ISA range.
> +
>  config NO_IOPORT_MAP
>         def_bool y if !PCI
>
> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
> new file mode 100644
> index 0000000..6ae0787
> --- /dev/null
> +++ b/arch/arm64/include/asm/extio.h
> @@ -0,0 +1,94 @@
> +/*
> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef __LINUX_EXTIO_H
> +#define __LINUX_EXTIO_H
> +
> +struct extio_ops {
> +       unsigned long start;/* inclusive, sys io addr */
> +       unsigned long end;/* inclusive, sys io addr */
> +
> +       u64 (*pfin)(void *devobj, unsigned long ptaddr, size_t dlen);
> +       void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
> +                                       size_t dlen);
> +       u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
> +                               size_t dlen, unsigned int count);
> +       void (*pfouts)(void *devobj, unsigned long ptaddr,
> +                               const void *outbuf, size_t dlen,
> +                               unsigned int count);
> +       void *devpara;
> +};
> +
> +extern struct extio_ops *arm64_extio_ops;
> +
> +#define DECLARE_EXTIO(bw, type)                                                \
> +extern type in##bw(unsigned long addr);                                        \
> +extern void out##bw(type value, unsigned long addr);                   \
> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
> +
> +#define BUILD_EXTIO(bw, type)                                          \
> +type in##bw(unsigned long addr)                                                \
> +{                                                                      \
> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
> +                       arm64_extio_ops->end < addr)                    \
> +               return read##bw(PCI_IOBASE + addr);                     \
> +       return arm64_extio_ops->pfin ?                                  \
> +               arm64_extio_ops->pfin(arm64_extio_ops->devpara,         \
> +                       addr, sizeof(type)) : -1;                       \
> +}                                                                      \
> +                                                                       \
> +void out##bw(type value, unsigned long addr)                           \
> +{                                                                      \
> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
> +                       arm64_extio_ops->end < addr)                    \
> +               write##bw(value, PCI_IOBASE + addr);                    \
> +       else                                                            \
> +               if (arm64_extio_ops->pfout)                             \
> +                       arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> +                               addr, value, sizeof(type));             \
> +}                                                                      \
> +                                                                       \
> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)     \
> +{                                                                      \
> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
> +                       arm64_extio_ops->end < addr)                    \
> +               reads##bw(PCI_IOBASE + addr, buffer, count);            \
> +       else                                                            \
> +               if (arm64_extio_ops->pfins)                             \
> +                       arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
> +                               addr, buffer, sizeof(type), count);     \
> +}                                                                      \
> +                                                                       \
> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)      \
> +{                                                                      \
> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
> +                       arm64_extio_ops->end < addr)                    \
> +               writes##bw(PCI_IOBASE + addr, buffer, count);           \
> +       else                                                            \
> +               if (arm64_extio_ops->pfouts)                            \
> +                       arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
> +                               addr, buffer, sizeof(type), count);     \
> +}
> +
> +static inline void arm64_set_extops(struct extio_ops *ops)
> +{
> +       if (ops)
> +               WRITE_ONCE(arm64_extio_ops, ops);
> +}
> +
> +#endif /* __LINUX_EXTIO_H*/
> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> index 0bba427..136735d 100644
> --- a/arch/arm64/include/asm/io.h
> +++ b/arch/arm64/include/asm/io.h
> @@ -31,6 +31,7 @@
>  #include <asm/early_ioremap.h>
>  #include <asm/alternative.h>
>  #include <asm/cpufeature.h>
> +#include <asm/extio.h>
>
>  #include <xen/xen.h>
>
> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>  #define IO_SPACE_LIMIT         (PCI_IO_SIZE - 1)
>  #define PCI_IOBASE             ((void __iomem *)PCI_IO_START)
>
> +
> +/*
> + * redefine the in(s)b/out(s)b for indirect-IO.
> + */
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +#define inb inb
> +#define outb outb
> +#define insb insb
> +#define outsb outsb
> +/* external declaration */
> +DECLARE_EXTIO(b, u8)
> +
> +#define inw inw
> +#define outw outw
> +#define insw insw
> +#define outsw outsw
> +
> +DECLARE_EXTIO(w, u16)
> +
> +#define inl inl
> +#define outl outl
> +#define insl insl
> +#define outsl outsl
> +
> +DECLARE_EXTIO(l, u32)
> +#endif
> +
> +
>  /*
>   * String version of I/O memory access operations.
>   */
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 7d66bba..60e0482 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)            += sys32.o kuser32.o signal32.o         \
>                                            sys_compat.o entry32.o
>  arm64-obj-$(CONFIG_FUNCTION_TRACER)    += ftrace.o entry-ftrace.o
>  arm64-obj-$(CONFIG_MODULES)            += arm64ksyms.o module.o
> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO) += extio.o
>  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)  += module-plts.o
>  arm64-obj-$(CONFIG_PERF_EVENTS)                += perf_regs.o perf_callchain.o
>  arm64-obj-$(CONFIG_HW_PERF_EVENTS)     += perf_event.o
> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> new file mode 100644
> index 0000000..647b3fa
> --- /dev/null
> +++ b/arch/arm64/kernel/extio.c
> @@ -0,0 +1,27 @@
> +/*
> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/io.h>
> +
> +struct extio_ops *arm64_extio_ops;
> +
> +
> +BUILD_EXTIO(b, u8)
> +
> +BUILD_EXTIO(w, u16)
> +
> +BUILD_EXTIO(l, u32)
> --
> 1.9.1
>



-- 
Ming Lei

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-12-22  8:15     ` Ming Lei
  0 siblings, 0 replies; 286+ messages in thread
From: Ming Lei @ 2016-12-22  8:15 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: Mark Rutland, gabriele.paoloni, Benjamin Herrenschmidt,
	Will Deacon, linuxarm, Lorenzo Pieralisi, Arnd Bergmann, xuwei5,
	linux-serial, Catalin Marinas, devicetree, minyard, Liviu Dudau,
	john.garry, zourongrong, Rob Herring, Bjorn Helgaas, kantyzc,
	zhichang.yuan02, linux-arm-kernel, linux-pci,
	Linux Kernel Mailing List, Olof Johansson

Hi Guys,

On Tue, Nov 8, 2016 at 11:47 AM, zhichang.yuan
<yuanzhichang@hisilicon.com> wrote:
> For arm64, there is no I/O space as other architectural platforms, such as
> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> known port addresses are used to control the corresponding target devices, for
> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> normal MMIO mode in using.
>
> To drive these devices, this patch introduces a method named indirect-IO.
> In this method the in/out pair in arch/arm64/include/asm/io.h will be
> redefined. When upper layer drivers call in/out with those known legacy port
> addresses to access the peripherals, the hooking functions corrresponding to
> those target peripherals will be called. Through this way, those upper layer
> drivers which depend on in/out can run on Hip06 without any changes.
>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
>  arch/arm64/Kconfig             |  6 +++
>  arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>  arch/arm64/include/asm/io.h    | 29 +++++++++++++
>  arch/arm64/kernel/Makefile     |  1 +
>  arch/arm64/kernel/extio.c      | 27 ++++++++++++
>  5 files changed, 157 insertions(+)

When I applied these three patches against current linus tree and
enable CONFIG_HISILICON_LPC, the following build failure[1] is
triggered when running 'make modules'.


Thanks,
Ming

[1] 'make modules' failure log

  Building modules, stage 2.
  MODPOST 2260 modules
ERROR: "inb" [drivers/watchdog/wdt_pci.ko] undefined!
ERROR: "outb" [drivers/watchdog/wdt_pci.ko] undefined!
ERROR: "outb" [drivers/watchdog/pcwd_pci.ko] undefined!
ERROR: "inb" [drivers/watchdog/pcwd_pci.ko] undefined!
ERROR: "outw" [drivers/video/vgastate.ko] undefined!
ERROR: "outb" [drivers/video/vgastate.ko] undefined!
ERROR: "inb" [drivers/video/vgastate.ko] undefined!
ERROR: "outw" [drivers/video/fbdev/vt8623fb.ko] undefined!
ERROR: "inb" [drivers/video/fbdev/vt8623fb.ko] undefined!
ERROR: "outb" [drivers/video/fbdev/vt8623fb.ko] undefined!
ERROR: "outw" [drivers/video/fbdev/tridentfb.ko] undefined!
ERROR: "inb" [drivers/video/fbdev/tridentfb.ko] undefined!
ERROR: "outb" [drivers/video/fbdev/tridentfb.ko] undefined!
ERROR: "inb" [drivers/video/fbdev/tdfxfb.ko] undefined!
.....
ERROR: "inb" [drivers/ata/pata_cmd64x.ko] undefined!
ERROR: "inb" [drivers/ata/pata_artop.ko] undefined!
scripts/Makefile.modpost:91: recipe for target '__modpost' failed
make[1]: *** [__modpost] Error 1
Makefile:1196: recipe for target 'modules' failed
make: *** [modules] Error 2


>  create mode 100644 arch/arm64/include/asm/extio.h
>  create mode 100644 arch/arm64/kernel/extio.c
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 969ef88..b44070b 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>         default 16
>
> +config ARM64_INDIRECT_PIO
> +       bool "access peripherals with legacy I/O port"
> +       help
> +         Support special accessors for ISA I/O devices. This is needed for
> +         SoCs that do not support standard read/write for the ISA range.
> +
>  config NO_IOPORT_MAP
>         def_bool y if !PCI
>
> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
> new file mode 100644
> index 0000000..6ae0787
> --- /dev/null
> +++ b/arch/arm64/include/asm/extio.h
> @@ -0,0 +1,94 @@
> +/*
> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef __LINUX_EXTIO_H
> +#define __LINUX_EXTIO_H
> +
> +struct extio_ops {
> +       unsigned long start;/* inclusive, sys io addr */
> +       unsigned long end;/* inclusive, sys io addr */
> +
> +       u64 (*pfin)(void *devobj, unsigned long ptaddr, size_t dlen);
> +       void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
> +                                       size_t dlen);
> +       u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
> +                               size_t dlen, unsigned int count);
> +       void (*pfouts)(void *devobj, unsigned long ptaddr,
> +                               const void *outbuf, size_t dlen,
> +                               unsigned int count);
> +       void *devpara;
> +};
> +
> +extern struct extio_ops *arm64_extio_ops;
> +
> +#define DECLARE_EXTIO(bw, type)                                                \
> +extern type in##bw(unsigned long addr);                                        \
> +extern void out##bw(type value, unsigned long addr);                   \
> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
> +
> +#define BUILD_EXTIO(bw, type)                                          \
> +type in##bw(unsigned long addr)                                                \
> +{                                                                      \
> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
> +                       arm64_extio_ops->end < addr)                    \
> +               return read##bw(PCI_IOBASE + addr);                     \
> +       return arm64_extio_ops->pfin ?                                  \
> +               arm64_extio_ops->pfin(arm64_extio_ops->devpara,         \
> +                       addr, sizeof(type)) : -1;                       \
> +}                                                                      \
> +                                                                       \
> +void out##bw(type value, unsigned long addr)                           \
> +{                                                                      \
> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
> +                       arm64_extio_ops->end < addr)                    \
> +               write##bw(value, PCI_IOBASE + addr);                    \
> +       else                                                            \
> +               if (arm64_extio_ops->pfout)                             \
> +                       arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> +                               addr, value, sizeof(type));             \
> +}                                                                      \
> +                                                                       \
> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)     \
> +{                                                                      \
> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
> +                       arm64_extio_ops->end < addr)                    \
> +               reads##bw(PCI_IOBASE + addr, buffer, count);            \
> +       else                                                            \
> +               if (arm64_extio_ops->pfins)                             \
> +                       arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
> +                               addr, buffer, sizeof(type), count);     \
> +}                                                                      \
> +                                                                       \
> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)      \
> +{                                                                      \
> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
> +                       arm64_extio_ops->end < addr)                    \
> +               writes##bw(PCI_IOBASE + addr, buffer, count);           \
> +       else                                                            \
> +               if (arm64_extio_ops->pfouts)                            \
> +                       arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
> +                               addr, buffer, sizeof(type), count);     \
> +}
> +
> +static inline void arm64_set_extops(struct extio_ops *ops)
> +{
> +       if (ops)
> +               WRITE_ONCE(arm64_extio_ops, ops);
> +}
> +
> +#endif /* __LINUX_EXTIO_H*/
> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> index 0bba427..136735d 100644
> --- a/arch/arm64/include/asm/io.h
> +++ b/arch/arm64/include/asm/io.h
> @@ -31,6 +31,7 @@
>  #include <asm/early_ioremap.h>
>  #include <asm/alternative.h>
>  #include <asm/cpufeature.h>
> +#include <asm/extio.h>
>
>  #include <xen/xen.h>
>
> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>  #define IO_SPACE_LIMIT         (PCI_IO_SIZE - 1)
>  #define PCI_IOBASE             ((void __iomem *)PCI_IO_START)
>
> +
> +/*
> + * redefine the in(s)b/out(s)b for indirect-IO.
> + */
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +#define inb inb
> +#define outb outb
> +#define insb insb
> +#define outsb outsb
> +/* external declaration */
> +DECLARE_EXTIO(b, u8)
> +
> +#define inw inw
> +#define outw outw
> +#define insw insw
> +#define outsw outsw
> +
> +DECLARE_EXTIO(w, u16)
> +
> +#define inl inl
> +#define outl outl
> +#define insl insl
> +#define outsl outsl
> +
> +DECLARE_EXTIO(l, u32)
> +#endif
> +
> +
>  /*
>   * String version of I/O memory access operations.
>   */
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 7d66bba..60e0482 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)            += sys32.o kuser32.o signal32.o         \
>                                            sys_compat.o entry32.o
>  arm64-obj-$(CONFIG_FUNCTION_TRACER)    += ftrace.o entry-ftrace.o
>  arm64-obj-$(CONFIG_MODULES)            += arm64ksyms.o module.o
> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO) += extio.o
>  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)  += module-plts.o
>  arm64-obj-$(CONFIG_PERF_EVENTS)                += perf_regs.o perf_callchain.o
>  arm64-obj-$(CONFIG_HW_PERF_EVENTS)     += perf_event.o
> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> new file mode 100644
> index 0000000..647b3fa
> --- /dev/null
> +++ b/arch/arm64/kernel/extio.c
> @@ -0,0 +1,27 @@
> +/*
> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/io.h>
> +
> +struct extio_ops *arm64_extio_ops;
> +
> +
> +BUILD_EXTIO(b, u8)
> +
> +BUILD_EXTIO(w, u16)
> +
> +BUILD_EXTIO(l, u32)
> --
> 1.9.1
>



-- 
Ming Lei

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-12-22  8:15     ` Ming Lei
  0 siblings, 0 replies; 286+ messages in thread
From: Ming Lei @ 2016-12-22  8:15 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: Mark Rutland, gabriele.paoloni, Benjamin Herrenschmidt,
	Will Deacon, linuxarm, Lorenzo Pieralisi, Arnd Bergmann, xuwei5,
	linux-serial, Catalin Marinas, devicetree, minyard, Liviu Dudau,
	john.garry, zourongrong, Rob Herring, Bjorn Helgaas, kantyzc,
	zhichang.yuan02, linux-arm-kernel, linux-pci,
	Linux Kernel Mailing List, Olof Johansson

Hi Guys,

On Tue, Nov 8, 2016 at 11:47 AM, zhichang.yuan
<yuanzhichang@hisilicon.com> wrote:
> For arm64, there is no I/O space as other architectural platforms, such as
> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> known port addresses are used to control the corresponding target devices, for
> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> normal MMIO mode in using.
>
> To drive these devices, this patch introduces a method named indirect-IO.
> In this method the in/out pair in arch/arm64/include/asm/io.h will be
> redefined. When upper layer drivers call in/out with those known legacy port
> addresses to access the peripherals, the hooking functions corrresponding to
> those target peripherals will be called. Through this way, those upper layer
> drivers which depend on in/out can run on Hip06 without any changes.
>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
>  arch/arm64/Kconfig             |  6 +++
>  arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>  arch/arm64/include/asm/io.h    | 29 +++++++++++++
>  arch/arm64/kernel/Makefile     |  1 +
>  arch/arm64/kernel/extio.c      | 27 ++++++++++++
>  5 files changed, 157 insertions(+)

When I applied these three patches against current linus tree and
enable CONFIG_HISILICON_LPC, the following build failure[1] is
triggered when running 'make modules'.


Thanks,
Ming

[1] 'make modules' failure log

  Building modules, stage 2.
  MODPOST 2260 modules
ERROR: "inb" [drivers/watchdog/wdt_pci.ko] undefined!
ERROR: "outb" [drivers/watchdog/wdt_pci.ko] undefined!
ERROR: "outb" [drivers/watchdog/pcwd_pci.ko] undefined!
ERROR: "inb" [drivers/watchdog/pcwd_pci.ko] undefined!
ERROR: "outw" [drivers/video/vgastate.ko] undefined!
ERROR: "outb" [drivers/video/vgastate.ko] undefined!
ERROR: "inb" [drivers/video/vgastate.ko] undefined!
ERROR: "outw" [drivers/video/fbdev/vt8623fb.ko] undefined!
ERROR: "inb" [drivers/video/fbdev/vt8623fb.ko] undefined!
ERROR: "outb" [drivers/video/fbdev/vt8623fb.ko] undefined!
ERROR: "outw" [drivers/video/fbdev/tridentfb.ko] undefined!
ERROR: "inb" [drivers/video/fbdev/tridentfb.ko] undefined!
ERROR: "outb" [drivers/video/fbdev/tridentfb.ko] undefined!
ERROR: "inb" [drivers/video/fbdev/tdfxfb.ko] undefined!
.....
ERROR: "inb" [drivers/ata/pata_cmd64x.ko] undefined!
ERROR: "inb" [drivers/ata/pata_artop.ko] undefined!
scripts/Makefile.modpost:91: recipe for target '__modpost' failed
make[1]: *** [__modpost] Error 1
Makefile:1196: recipe for target 'modules' failed
make: *** [modules] Error 2


>  create mode 100644 arch/arm64/include/asm/extio.h
>  create mode 100644 arch/arm64/kernel/extio.c
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 969ef88..b44070b 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>         default 16
>
> +config ARM64_INDIRECT_PIO
> +       bool "access peripherals with legacy I/O port"
> +       help
> +         Support special accessors for ISA I/O devices. This is needed for
> +         SoCs that do not support standard read/write for the ISA range.
> +
>  config NO_IOPORT_MAP
>         def_bool y if !PCI
>
> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
> new file mode 100644
> index 0000000..6ae0787
> --- /dev/null
> +++ b/arch/arm64/include/asm/extio.h
> @@ -0,0 +1,94 @@
> +/*
> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef __LINUX_EXTIO_H
> +#define __LINUX_EXTIO_H
> +
> +struct extio_ops {
> +       unsigned long start;/* inclusive, sys io addr */
> +       unsigned long end;/* inclusive, sys io addr */
> +
> +       u64 (*pfin)(void *devobj, unsigned long ptaddr, size_t dlen);
> +       void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
> +                                       size_t dlen);
> +       u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
> +                               size_t dlen, unsigned int count);
> +       void (*pfouts)(void *devobj, unsigned long ptaddr,
> +                               const void *outbuf, size_t dlen,
> +                               unsigned int count);
> +       void *devpara;
> +};
> +
> +extern struct extio_ops *arm64_extio_ops;
> +
> +#define DECLARE_EXTIO(bw, type)                                                \
> +extern type in##bw(unsigned long addr);                                        \
> +extern void out##bw(type value, unsigned long addr);                   \
> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
> +
> +#define BUILD_EXTIO(bw, type)                                          \
> +type in##bw(unsigned long addr)                                                \
> +{                                                                      \
> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
> +                       arm64_extio_ops->end < addr)                    \
> +               return read##bw(PCI_IOBASE + addr);                     \
> +       return arm64_extio_ops->pfin ?                                  \
> +               arm64_extio_ops->pfin(arm64_extio_ops->devpara,         \
> +                       addr, sizeof(type)) : -1;                       \
> +}                                                                      \
> +                                                                       \
> +void out##bw(type value, unsigned long addr)                           \
> +{                                                                      \
> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
> +                       arm64_extio_ops->end < addr)                    \
> +               write##bw(value, PCI_IOBASE + addr);                    \
> +       else                                                            \
> +               if (arm64_extio_ops->pfout)                             \
> +                       arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> +                               addr, value, sizeof(type));             \
> +}                                                                      \
> +                                                                       \
> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)     \
> +{                                                                      \
> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
> +                       arm64_extio_ops->end < addr)                    \
> +               reads##bw(PCI_IOBASE + addr, buffer, count);            \
> +       else                                                            \
> +               if (arm64_extio_ops->pfins)                             \
> +                       arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
> +                               addr, buffer, sizeof(type), count);     \
> +}                                                                      \
> +                                                                       \
> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)      \
> +{                                                                      \
> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
> +                       arm64_extio_ops->end < addr)                    \
> +               writes##bw(PCI_IOBASE + addr, buffer, count);           \
> +       else                                                            \
> +               if (arm64_extio_ops->pfouts)                            \
> +                       arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
> +                               addr, buffer, sizeof(type), count);     \
> +}
> +
> +static inline void arm64_set_extops(struct extio_ops *ops)
> +{
> +       if (ops)
> +               WRITE_ONCE(arm64_extio_ops, ops);
> +}
> +
> +#endif /* __LINUX_EXTIO_H*/
> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> index 0bba427..136735d 100644
> --- a/arch/arm64/include/asm/io.h
> +++ b/arch/arm64/include/asm/io.h
> @@ -31,6 +31,7 @@
>  #include <asm/early_ioremap.h>
>  #include <asm/alternative.h>
>  #include <asm/cpufeature.h>
> +#include <asm/extio.h>
>
>  #include <xen/xen.h>
>
> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>  #define IO_SPACE_LIMIT         (PCI_IO_SIZE - 1)
>  #define PCI_IOBASE             ((void __iomem *)PCI_IO_START)
>
> +
> +/*
> + * redefine the in(s)b/out(s)b for indirect-IO.
> + */
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +#define inb inb
> +#define outb outb
> +#define insb insb
> +#define outsb outsb
> +/* external declaration */
> +DECLARE_EXTIO(b, u8)
> +
> +#define inw inw
> +#define outw outw
> +#define insw insw
> +#define outsw outsw
> +
> +DECLARE_EXTIO(w, u16)
> +
> +#define inl inl
> +#define outl outl
> +#define insl insl
> +#define outsl outsl
> +
> +DECLARE_EXTIO(l, u32)
> +#endif
> +
> +
>  /*
>   * String version of I/O memory access operations.
>   */
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 7d66bba..60e0482 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)            += sys32.o kuser32.o signal32.o         \
>                                            sys_compat.o entry32.o
>  arm64-obj-$(CONFIG_FUNCTION_TRACER)    += ftrace.o entry-ftrace.o
>  arm64-obj-$(CONFIG_MODULES)            += arm64ksyms.o module.o
> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO) += extio.o
>  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)  += module-plts.o
>  arm64-obj-$(CONFIG_PERF_EVENTS)                += perf_regs.o perf_callchain.o
>  arm64-obj-$(CONFIG_HW_PERF_EVENTS)     += perf_event.o
> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> new file mode 100644
> index 0000000..647b3fa
> --- /dev/null
> +++ b/arch/arm64/kernel/extio.c
> @@ -0,0 +1,27 @@
> +/*
> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/io.h>
> +
> +struct extio_ops *arm64_extio_ops;
> +
> +
> +BUILD_EXTIO(b, u8)
> +
> +BUILD_EXTIO(w, u16)
> +
> +BUILD_EXTIO(l, u32)
> --
> 1.9.1
>



-- 
Ming Lei

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-12-22  8:15     ` Ming Lei
  0 siblings, 0 replies; 286+ messages in thread
From: Ming Lei @ 2016-12-22  8:15 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Guys,

On Tue, Nov 8, 2016 at 11:47 AM, zhichang.yuan
<yuanzhichang@hisilicon.com> wrote:
> For arm64, there is no I/O space as other architectural platforms, such as
> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
> known port addresses are used to control the corresponding target devices, for
> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
> normal MMIO mode in using.
>
> To drive these devices, this patch introduces a method named indirect-IO.
> In this method the in/out pair in arch/arm64/include/asm/io.h will be
> redefined. When upper layer drivers call in/out with those known legacy port
> addresses to access the peripherals, the hooking functions corrresponding to
> those target peripherals will be called. Through this way, those upper layer
> drivers which depend on in/out can run on Hip06 without any changes.
>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> ---
>  arch/arm64/Kconfig             |  6 +++
>  arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>  arch/arm64/include/asm/io.h    | 29 +++++++++++++
>  arch/arm64/kernel/Makefile     |  1 +
>  arch/arm64/kernel/extio.c      | 27 ++++++++++++
>  5 files changed, 157 insertions(+)

When I applied these three patches against current linus tree and
enable CONFIG_HISILICON_LPC, the following build failure[1] is
triggered when running 'make modules'.


Thanks,
Ming

[1] 'make modules' failure log

  Building modules, stage 2.
  MODPOST 2260 modules
ERROR: "inb" [drivers/watchdog/wdt_pci.ko] undefined!
ERROR: "outb" [drivers/watchdog/wdt_pci.ko] undefined!
ERROR: "outb" [drivers/watchdog/pcwd_pci.ko] undefined!
ERROR: "inb" [drivers/watchdog/pcwd_pci.ko] undefined!
ERROR: "outw" [drivers/video/vgastate.ko] undefined!
ERROR: "outb" [drivers/video/vgastate.ko] undefined!
ERROR: "inb" [drivers/video/vgastate.ko] undefined!
ERROR: "outw" [drivers/video/fbdev/vt8623fb.ko] undefined!
ERROR: "inb" [drivers/video/fbdev/vt8623fb.ko] undefined!
ERROR: "outb" [drivers/video/fbdev/vt8623fb.ko] undefined!
ERROR: "outw" [drivers/video/fbdev/tridentfb.ko] undefined!
ERROR: "inb" [drivers/video/fbdev/tridentfb.ko] undefined!
ERROR: "outb" [drivers/video/fbdev/tridentfb.ko] undefined!
ERROR: "inb" [drivers/video/fbdev/tdfxfb.ko] undefined!
.....
ERROR: "inb" [drivers/ata/pata_cmd64x.ko] undefined!
ERROR: "inb" [drivers/ata/pata_artop.ko] undefined!
scripts/Makefile.modpost:91: recipe for target '__modpost' failed
make[1]: *** [__modpost] Error 1
Makefile:1196: recipe for target 'modules' failed
make: *** [modules] Error 2


>  create mode 100644 arch/arm64/include/asm/extio.h
>  create mode 100644 arch/arm64/kernel/extio.c
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 969ef88..b44070b 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>         default 16
>
> +config ARM64_INDIRECT_PIO
> +       bool "access peripherals with legacy I/O port"
> +       help
> +         Support special accessors for ISA I/O devices. This is needed for
> +         SoCs that do not support standard read/write for the ISA range.
> +
>  config NO_IOPORT_MAP
>         def_bool y if !PCI
>
> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
> new file mode 100644
> index 0000000..6ae0787
> --- /dev/null
> +++ b/arch/arm64/include/asm/extio.h
> @@ -0,0 +1,94 @@
> +/*
> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef __LINUX_EXTIO_H
> +#define __LINUX_EXTIO_H
> +
> +struct extio_ops {
> +       unsigned long start;/* inclusive, sys io addr */
> +       unsigned long end;/* inclusive, sys io addr */
> +
> +       u64 (*pfin)(void *devobj, unsigned long ptaddr, size_t dlen);
> +       void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
> +                                       size_t dlen);
> +       u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
> +                               size_t dlen, unsigned int count);
> +       void (*pfouts)(void *devobj, unsigned long ptaddr,
> +                               const void *outbuf, size_t dlen,
> +                               unsigned int count);
> +       void *devpara;
> +};
> +
> +extern struct extio_ops *arm64_extio_ops;
> +
> +#define DECLARE_EXTIO(bw, type)                                                \
> +extern type in##bw(unsigned long addr);                                        \
> +extern void out##bw(type value, unsigned long addr);                   \
> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
> +
> +#define BUILD_EXTIO(bw, type)                                          \
> +type in##bw(unsigned long addr)                                                \
> +{                                                                      \
> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
> +                       arm64_extio_ops->end < addr)                    \
> +               return read##bw(PCI_IOBASE + addr);                     \
> +       return arm64_extio_ops->pfin ?                                  \
> +               arm64_extio_ops->pfin(arm64_extio_ops->devpara,         \
> +                       addr, sizeof(type)) : -1;                       \
> +}                                                                      \
> +                                                                       \
> +void out##bw(type value, unsigned long addr)                           \
> +{                                                                      \
> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
> +                       arm64_extio_ops->end < addr)                    \
> +               write##bw(value, PCI_IOBASE + addr);                    \
> +       else                                                            \
> +               if (arm64_extio_ops->pfout)                             \
> +                       arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
> +                               addr, value, sizeof(type));             \
> +}                                                                      \
> +                                                                       \
> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)     \
> +{                                                                      \
> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
> +                       arm64_extio_ops->end < addr)                    \
> +               reads##bw(PCI_IOBASE + addr, buffer, count);            \
> +       else                                                            \
> +               if (arm64_extio_ops->pfins)                             \
> +                       arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
> +                               addr, buffer, sizeof(type), count);     \
> +}                                                                      \
> +                                                                       \
> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)      \
> +{                                                                      \
> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
> +                       arm64_extio_ops->end < addr)                    \
> +               writes##bw(PCI_IOBASE + addr, buffer, count);           \
> +       else                                                            \
> +               if (arm64_extio_ops->pfouts)                            \
> +                       arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
> +                               addr, buffer, sizeof(type), count);     \
> +}
> +
> +static inline void arm64_set_extops(struct extio_ops *ops)
> +{
> +       if (ops)
> +               WRITE_ONCE(arm64_extio_ops, ops);
> +}
> +
> +#endif /* __LINUX_EXTIO_H*/
> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> index 0bba427..136735d 100644
> --- a/arch/arm64/include/asm/io.h
> +++ b/arch/arm64/include/asm/io.h
> @@ -31,6 +31,7 @@
>  #include <asm/early_ioremap.h>
>  #include <asm/alternative.h>
>  #include <asm/cpufeature.h>
> +#include <asm/extio.h>
>
>  #include <xen/xen.h>
>
> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>  #define IO_SPACE_LIMIT         (PCI_IO_SIZE - 1)
>  #define PCI_IOBASE             ((void __iomem *)PCI_IO_START)
>
> +
> +/*
> + * redefine the in(s)b/out(s)b for indirect-IO.
> + */
> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> +#define inb inb
> +#define outb outb
> +#define insb insb
> +#define outsb outsb
> +/* external declaration */
> +DECLARE_EXTIO(b, u8)
> +
> +#define inw inw
> +#define outw outw
> +#define insw insw
> +#define outsw outsw
> +
> +DECLARE_EXTIO(w, u16)
> +
> +#define inl inl
> +#define outl outl
> +#define insl insl
> +#define outsl outsl
> +
> +DECLARE_EXTIO(l, u32)
> +#endif
> +
> +
>  /*
>   * String version of I/O memory access operations.
>   */
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 7d66bba..60e0482 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)            += sys32.o kuser32.o signal32.o         \
>                                            sys_compat.o entry32.o
>  arm64-obj-$(CONFIG_FUNCTION_TRACER)    += ftrace.o entry-ftrace.o
>  arm64-obj-$(CONFIG_MODULES)            += arm64ksyms.o module.o
> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO) += extio.o
>  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)  += module-plts.o
>  arm64-obj-$(CONFIG_PERF_EVENTS)                += perf_regs.o perf_callchain.o
>  arm64-obj-$(CONFIG_HW_PERF_EVENTS)     += perf_event.o
> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> new file mode 100644
> index 0000000..647b3fa
> --- /dev/null
> +++ b/arch/arm64/kernel/extio.c
> @@ -0,0 +1,27 @@
> +/*
> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/io.h>
> +
> +struct extio_ops *arm64_extio_ops;
> +
> +
> +BUILD_EXTIO(b, u8)
> +
> +BUILD_EXTIO(w, u16)
> +
> +BUILD_EXTIO(l, u32)
> --
> 1.9.1
>



-- 
Ming Lei

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-12-22  8:15     ` Ming Lei
  (?)
  (?)
@ 2016-12-23  1:43       ` zhichang.yuan
  -1 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-12-23  1:43 UTC (permalink / raw)
  To: Ming Lei
  Cc: Catalin Marinas, Will Deacon, Rob Herring, Bjorn Helgaas,
	Mark Rutland, Olof Johansson, Arnd Bergmann, linux-arm-kernel,
	Lorenzo Pieralisi, Linux Kernel Mailing List, linuxarm,
	devicetree, linux-pci, linux-serial, minyard,
	Benjamin Herrenschmidt, Liviu Dudau, zourongrong, john.garry,
	gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5

Hi,Ming,


On 2016/12/22 16:15, Ming Lei wrote:
> Hi Guys,
> 
> On Tue, Nov 8, 2016 at 11:47 AM, zhichang.yuan
> <yuanzhichang@hisilicon.com> wrote:
>> For arm64, there is no I/O space as other architectural platforms, such as
>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>> known port addresses are used to control the corresponding target devices, for
>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>> normal MMIO mode in using.
>>
>> To drive these devices, this patch introduces a method named indirect-IO.
>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>> redefined. When upper layer drivers call in/out with those known legacy port
>> addresses to access the peripherals, the hooking functions corrresponding to
>> those target peripherals will be called. Through this way, those upper layer
>> drivers which depend on in/out can run on Hip06 without any changes.
>>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
>> ---
>>  arch/arm64/Kconfig             |  6 +++
>>  arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>>  arch/arm64/include/asm/io.h    | 29 +++++++++++++
>>  arch/arm64/kernel/Makefile     |  1 +
>>  arch/arm64/kernel/extio.c      | 27 ++++++++++++
>>  5 files changed, 157 insertions(+)
> 
> When I applied these three patches against current linus tree and
> enable CONFIG_HISILICON_LPC, the following build failure[1] is
> triggered when running 'make modules'.
> 

Thanks for your report!

This patch has compilation issue on some architectures, sorry for the inconvenience caused by this!
The ongoing v6 will solve these issues.
I will trace this failure and provide a fix if you can not wait for the next version.

Could you send me your .config in private? I don't want to bother all the hacker in the mail-list.


Thanks,
Zhichang

> 
> Thanks,
> Ming
> 
> [1] 'make modules' failure log
> 
>   Building modules, stage 2.
>   MODPOST 2260 modules
> ERROR: "inb" [drivers/watchdog/wdt_pci.ko] undefined!
> ERROR: "outb" [drivers/watchdog/wdt_pci.ko] undefined!
> ERROR: "outb" [drivers/watchdog/pcwd_pci.ko] undefined!
> ERROR: "inb" [drivers/watchdog/pcwd_pci.ko] undefined!
> ERROR: "outw" [drivers/video/vgastate.ko] undefined!
> ERROR: "outb" [drivers/video/vgastate.ko] undefined!
> ERROR: "inb" [drivers/video/vgastate.ko] undefined!
> ERROR: "outw" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "outb" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "outw" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "outb" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/tdfxfb.ko] undefined!
> .....
> ERROR: "inb" [drivers/ata/pata_cmd64x.ko] undefined!
> ERROR: "inb" [drivers/ata/pata_artop.ko] undefined!
> scripts/Makefile.modpost:91: recipe for target '__modpost' failed
> make[1]: *** [__modpost] Error 1
> Makefile:1196: recipe for target 'modules' failed
> make: *** [modules] Error 2
> 
> 
>>  create mode 100644 arch/arm64/include/asm/extio.h
>>  create mode 100644 arch/arm64/kernel/extio.c
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 969ef88..b44070b 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>>         default 16
>>
>> +config ARM64_INDIRECT_PIO
>> +       bool "access peripherals with legacy I/O port"
>> +       help
>> +         Support special accessors for ISA I/O devices. This is needed for
>> +         SoCs that do not support standard read/write for the ISA range.
>> +
>>  config NO_IOPORT_MAP
>>         def_bool y if !PCI
>>
>> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
>> new file mode 100644
>> index 0000000..6ae0787
>> --- /dev/null
>> +++ b/arch/arm64/include/asm/extio.h
>> @@ -0,0 +1,94 @@
>> +/*
>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef __LINUX_EXTIO_H
>> +#define __LINUX_EXTIO_H
>> +
>> +struct extio_ops {
>> +       unsigned long start;/* inclusive, sys io addr */
>> +       unsigned long end;/* inclusive, sys io addr */
>> +
>> +       u64 (*pfin)(void *devobj, unsigned long ptaddr, size_t dlen);
>> +       void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
>> +                                       size_t dlen);
>> +       u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
>> +                               size_t dlen, unsigned int count);
>> +       void (*pfouts)(void *devobj, unsigned long ptaddr,
>> +                               const void *outbuf, size_t dlen,
>> +                               unsigned int count);
>> +       void *devpara;
>> +};
>> +
>> +extern struct extio_ops *arm64_extio_ops;
>> +
>> +#define DECLARE_EXTIO(bw, type)                                                \
>> +extern type in##bw(unsigned long addr);                                        \
>> +extern void out##bw(type value, unsigned long addr);                   \
>> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
>> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
>> +
>> +#define BUILD_EXTIO(bw, type)                                          \
>> +type in##bw(unsigned long addr)                                                \
>> +{                                                                      \
>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>> +                       arm64_extio_ops->end < addr)                    \
>> +               return read##bw(PCI_IOBASE + addr);                     \
>> +       return arm64_extio_ops->pfin ?                                  \
>> +               arm64_extio_ops->pfin(arm64_extio_ops->devpara,         \
>> +                       addr, sizeof(type)) : -1;                       \
>> +}                                                                      \
>> +                                                                       \
>> +void out##bw(type value, unsigned long addr)                           \
>> +{                                                                      \
>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>> +                       arm64_extio_ops->end < addr)                    \
>> +               write##bw(value, PCI_IOBASE + addr);                    \
>> +       else                                                            \
>> +               if (arm64_extio_ops->pfout)                             \
>> +                       arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>> +                               addr, value, sizeof(type));             \
>> +}                                                                      \
>> +                                                                       \
>> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)     \
>> +{                                                                      \
>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>> +                       arm64_extio_ops->end < addr)                    \
>> +               reads##bw(PCI_IOBASE + addr, buffer, count);            \
>> +       else                                                            \
>> +               if (arm64_extio_ops->pfins)                             \
>> +                       arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
>> +                               addr, buffer, sizeof(type), count);     \
>> +}                                                                      \
>> +                                                                       \
>> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)      \
>> +{                                                                      \
>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>> +                       arm64_extio_ops->end < addr)                    \
>> +               writes##bw(PCI_IOBASE + addr, buffer, count);           \
>> +       else                                                            \
>> +               if (arm64_extio_ops->pfouts)                            \
>> +                       arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
>> +                               addr, buffer, sizeof(type), count);     \
>> +}
>> +
>> +static inline void arm64_set_extops(struct extio_ops *ops)
>> +{
>> +       if (ops)
>> +               WRITE_ONCE(arm64_extio_ops, ops);
>> +}
>> +
>> +#endif /* __LINUX_EXTIO_H*/
>> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
>> index 0bba427..136735d 100644
>> --- a/arch/arm64/include/asm/io.h
>> +++ b/arch/arm64/include/asm/io.h
>> @@ -31,6 +31,7 @@
>>  #include <asm/early_ioremap.h>
>>  #include <asm/alternative.h>
>>  #include <asm/cpufeature.h>
>> +#include <asm/extio.h>
>>
>>  #include <xen/xen.h>
>>
>> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>  #define IO_SPACE_LIMIT         (PCI_IO_SIZE - 1)
>>  #define PCI_IOBASE             ((void __iomem *)PCI_IO_START)
>>
>> +
>> +/*
>> + * redefine the in(s)b/out(s)b for indirect-IO.
>> + */
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +#define inb inb
>> +#define outb outb
>> +#define insb insb
>> +#define outsb outsb
>> +/* external declaration */
>> +DECLARE_EXTIO(b, u8)
>> +
>> +#define inw inw
>> +#define outw outw
>> +#define insw insw
>> +#define outsw outsw
>> +
>> +DECLARE_EXTIO(w, u16)
>> +
>> +#define inl inl
>> +#define outl outl
>> +#define insl insl
>> +#define outsl outsl
>> +
>> +DECLARE_EXTIO(l, u32)
>> +#endif
>> +
>> +
>>  /*
>>   * String version of I/O memory access operations.
>>   */
>> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
>> index 7d66bba..60e0482 100644
>> --- a/arch/arm64/kernel/Makefile
>> +++ b/arch/arm64/kernel/Makefile
>> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)            += sys32.o kuser32.o signal32.o         \
>>                                            sys_compat.o entry32.o
>>  arm64-obj-$(CONFIG_FUNCTION_TRACER)    += ftrace.o entry-ftrace.o
>>  arm64-obj-$(CONFIG_MODULES)            += arm64ksyms.o module.o
>> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO) += extio.o
>>  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)  += module-plts.o
>>  arm64-obj-$(CONFIG_PERF_EVENTS)                += perf_regs.o perf_callchain.o
>>  arm64-obj-$(CONFIG_HW_PERF_EVENTS)     += perf_event.o
>> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
>> new file mode 100644
>> index 0000000..647b3fa
>> --- /dev/null
>> +++ b/arch/arm64/kernel/extio.c
>> @@ -0,0 +1,27 @@
>> +/*
>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <linux/io.h>
>> +
>> +struct extio_ops *arm64_extio_ops;
>> +
>> +
>> +BUILD_EXTIO(b, u8)
>> +
>> +BUILD_EXTIO(w, u16)
>> +
>> +BUILD_EXTIO(l, u32)
>> --
>> 1.9.1
>>
> 
> 
> 

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-12-23  1:43       ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-12-23  1:43 UTC (permalink / raw)
  To: Ming Lei
  Cc: Catalin Marinas, Will Deacon, Rob Herring, Bjorn Helgaas,
	Mark Rutland, Olof Johansson, Arnd Bergmann, linux-arm-kernel,
	Lorenzo Pieralisi, Linux Kernel Mailing List, linuxarm,
	devicetree, linux-pci, linux-serial, minyard,
	Benjamin Herrenschmidt, Liviu Dudau, zourongrong, john.garry,
	gabriele.paoloni

Hi,Ming,


On 2016/12/22 16:15, Ming Lei wrote:
> Hi Guys,
> 
> On Tue, Nov 8, 2016 at 11:47 AM, zhichang.yuan
> <yuanzhichang@hisilicon.com> wrote:
>> For arm64, there is no I/O space as other architectural platforms, such as
>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>> known port addresses are used to control the corresponding target devices, for
>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>> normal MMIO mode in using.
>>
>> To drive these devices, this patch introduces a method named indirect-IO.
>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>> redefined. When upper layer drivers call in/out with those known legacy port
>> addresses to access the peripherals, the hooking functions corrresponding to
>> those target peripherals will be called. Through this way, those upper layer
>> drivers which depend on in/out can run on Hip06 without any changes.
>>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
>> ---
>>  arch/arm64/Kconfig             |  6 +++
>>  arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>>  arch/arm64/include/asm/io.h    | 29 +++++++++++++
>>  arch/arm64/kernel/Makefile     |  1 +
>>  arch/arm64/kernel/extio.c      | 27 ++++++++++++
>>  5 files changed, 157 insertions(+)
> 
> When I applied these three patches against current linus tree and
> enable CONFIG_HISILICON_LPC, the following build failure[1] is
> triggered when running 'make modules'.
> 

Thanks for your report!

This patch has compilation issue on some architectures, sorry for the inconvenience caused by this!
The ongoing v6 will solve these issues.
I will trace this failure and provide a fix if you can not wait for the next version.

Could you send me your .config in private? I don't want to bother all the hacker in the mail-list.


Thanks,
Zhichang

> 
> Thanks,
> Ming
> 
> [1] 'make modules' failure log
> 
>   Building modules, stage 2.
>   MODPOST 2260 modules
> ERROR: "inb" [drivers/watchdog/wdt_pci.ko] undefined!
> ERROR: "outb" [drivers/watchdog/wdt_pci.ko] undefined!
> ERROR: "outb" [drivers/watchdog/pcwd_pci.ko] undefined!
> ERROR: "inb" [drivers/watchdog/pcwd_pci.ko] undefined!
> ERROR: "outw" [drivers/video/vgastate.ko] undefined!
> ERROR: "outb" [drivers/video/vgastate.ko] undefined!
> ERROR: "inb" [drivers/video/vgastate.ko] undefined!
> ERROR: "outw" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "outb" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "outw" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "outb" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/tdfxfb.ko] undefined!
> .....
> ERROR: "inb" [drivers/ata/pata_cmd64x.ko] undefined!
> ERROR: "inb" [drivers/ata/pata_artop.ko] undefined!
> scripts/Makefile.modpost:91: recipe for target '__modpost' failed
> make[1]: *** [__modpost] Error 1
> Makefile:1196: recipe for target 'modules' failed
> make: *** [modules] Error 2
> 
> 
>>  create mode 100644 arch/arm64/include/asm/extio.h
>>  create mode 100644 arch/arm64/kernel/extio.c
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 969ef88..b44070b 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>>         default 16
>>
>> +config ARM64_INDIRECT_PIO
>> +       bool "access peripherals with legacy I/O port"
>> +       help
>> +         Support special accessors for ISA I/O devices. This is needed for
>> +         SoCs that do not support standard read/write for the ISA range.
>> +
>>  config NO_IOPORT_MAP
>>         def_bool y if !PCI
>>
>> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
>> new file mode 100644
>> index 0000000..6ae0787
>> --- /dev/null
>> +++ b/arch/arm64/include/asm/extio.h
>> @@ -0,0 +1,94 @@
>> +/*
>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef __LINUX_EXTIO_H
>> +#define __LINUX_EXTIO_H
>> +
>> +struct extio_ops {
>> +       unsigned long start;/* inclusive, sys io addr */
>> +       unsigned long end;/* inclusive, sys io addr */
>> +
>> +       u64 (*pfin)(void *devobj, unsigned long ptaddr, size_t dlen);
>> +       void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
>> +                                       size_t dlen);
>> +       u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
>> +                               size_t dlen, unsigned int count);
>> +       void (*pfouts)(void *devobj, unsigned long ptaddr,
>> +                               const void *outbuf, size_t dlen,
>> +                               unsigned int count);
>> +       void *devpara;
>> +};
>> +
>> +extern struct extio_ops *arm64_extio_ops;
>> +
>> +#define DECLARE_EXTIO(bw, type)                                                \
>> +extern type in##bw(unsigned long addr);                                        \
>> +extern void out##bw(type value, unsigned long addr);                   \
>> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
>> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
>> +
>> +#define BUILD_EXTIO(bw, type)                                          \
>> +type in##bw(unsigned long addr)                                                \
>> +{                                                                      \
>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>> +                       arm64_extio_ops->end < addr)                    \
>> +               return read##bw(PCI_IOBASE + addr);                     \
>> +       return arm64_extio_ops->pfin ?                                  \
>> +               arm64_extio_ops->pfin(arm64_extio_ops->devpara,         \
>> +                       addr, sizeof(type)) : -1;                       \
>> +}                                                                      \
>> +                                                                       \
>> +void out##bw(type value, unsigned long addr)                           \
>> +{                                                                      \
>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>> +                       arm64_extio_ops->end < addr)                    \
>> +               write##bw(value, PCI_IOBASE + addr);                    \
>> +       else                                                            \
>> +               if (arm64_extio_ops->pfout)                             \
>> +                       arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>> +                               addr, value, sizeof(type));             \
>> +}                                                                      \
>> +                                                                       \
>> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)     \
>> +{                                                                      \
>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>> +                       arm64_extio_ops->end < addr)                    \
>> +               reads##bw(PCI_IOBASE + addr, buffer, count);            \
>> +       else                                                            \
>> +               if (arm64_extio_ops->pfins)                             \
>> +                       arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
>> +                               addr, buffer, sizeof(type), count);     \
>> +}                                                                      \
>> +                                                                       \
>> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)      \
>> +{                                                                      \
>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>> +                       arm64_extio_ops->end < addr)                    \
>> +               writes##bw(PCI_IOBASE + addr, buffer, count);           \
>> +       else                                                            \
>> +               if (arm64_extio_ops->pfouts)                            \
>> +                       arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
>> +                               addr, buffer, sizeof(type), count);     \
>> +}
>> +
>> +static inline void arm64_set_extops(struct extio_ops *ops)
>> +{
>> +       if (ops)
>> +               WRITE_ONCE(arm64_extio_ops, ops);
>> +}
>> +
>> +#endif /* __LINUX_EXTIO_H*/
>> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
>> index 0bba427..136735d 100644
>> --- a/arch/arm64/include/asm/io.h
>> +++ b/arch/arm64/include/asm/io.h
>> @@ -31,6 +31,7 @@
>>  #include <asm/early_ioremap.h>
>>  #include <asm/alternative.h>
>>  #include <asm/cpufeature.h>
>> +#include <asm/extio.h>
>>
>>  #include <xen/xen.h>
>>
>> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>  #define IO_SPACE_LIMIT         (PCI_IO_SIZE - 1)
>>  #define PCI_IOBASE             ((void __iomem *)PCI_IO_START)
>>
>> +
>> +/*
>> + * redefine the in(s)b/out(s)b for indirect-IO.
>> + */
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +#define inb inb
>> +#define outb outb
>> +#define insb insb
>> +#define outsb outsb
>> +/* external declaration */
>> +DECLARE_EXTIO(b, u8)
>> +
>> +#define inw inw
>> +#define outw outw
>> +#define insw insw
>> +#define outsw outsw
>> +
>> +DECLARE_EXTIO(w, u16)
>> +
>> +#define inl inl
>> +#define outl outl
>> +#define insl insl
>> +#define outsl outsl
>> +
>> +DECLARE_EXTIO(l, u32)
>> +#endif
>> +
>> +
>>  /*
>>   * String version of I/O memory access operations.
>>   */
>> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
>> index 7d66bba..60e0482 100644
>> --- a/arch/arm64/kernel/Makefile
>> +++ b/arch/arm64/kernel/Makefile
>> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)            += sys32.o kuser32.o signal32.o         \
>>                                            sys_compat.o entry32.o
>>  arm64-obj-$(CONFIG_FUNCTION_TRACER)    += ftrace.o entry-ftrace.o
>>  arm64-obj-$(CONFIG_MODULES)            += arm64ksyms.o module.o
>> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO) += extio.o
>>  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)  += module-plts.o
>>  arm64-obj-$(CONFIG_PERF_EVENTS)                += perf_regs.o perf_callchain.o
>>  arm64-obj-$(CONFIG_HW_PERF_EVENTS)     += perf_event.o
>> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
>> new file mode 100644
>> index 0000000..647b3fa
>> --- /dev/null
>> +++ b/arch/arm64/kernel/extio.c
>> @@ -0,0 +1,27 @@
>> +/*
>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <linux/io.h>
>> +
>> +struct extio_ops *arm64_extio_ops;
>> +
>> +
>> +BUILD_EXTIO(b, u8)
>> +
>> +BUILD_EXTIO(w, u16)
>> +
>> +BUILD_EXTIO(l, u32)
>> --
>> 1.9.1
>>
> 
> 
> 

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-12-23  1:43       ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-12-23  1:43 UTC (permalink / raw)
  To: Ming Lei
  Cc: Mark Rutland, gabriele.paoloni, Benjamin Herrenschmidt,
	Will Deacon, linuxarm, Lorenzo Pieralisi, Arnd Bergmann, xuwei5,
	linux-serial, Catalin Marinas, devicetree, minyard, Liviu Dudau,
	john.garry, zourongrong, Rob Herring, Bjorn Helgaas, kantyzc,
	zhichang.yuan02, linux-arm-kernel, linux-pci,
	Linux Kernel Mailing List, Olof Johansson

SGnvvIxNaW5nLAoKCk9uIDIwMTYvMTIvMjIgMTY6MTUsIE1pbmcgTGVpIHdyb3RlOgo+IEhpIEd1
eXMsCj4gCj4gT24gVHVlLCBOb3YgOCwgMjAxNiBhdCAxMTo0NyBBTSwgemhpY2hhbmcueXVhbgo+
IDx5dWFuemhpY2hhbmdAaGlzaWxpY29uLmNvbT4gd3JvdGU6Cj4+IEZvciBhcm02NCwgdGhlcmUg
aXMgbm8gSS9PIHNwYWNlIGFzIG90aGVyIGFyY2hpdGVjdHVyYWwgcGxhdGZvcm1zLCBzdWNoIGFz
Cj4+IFg4Ni4gTW9zdCBJL08gYWNjZXNzZXMgYXJlIGFjaGlldmVkIGJhc2VkIG9uIE1NSU8uIEJ1
dCBmb3Igc29tZSBhcm02NCBTb0NzLAo+PiBzdWNoIGFzIEhpcDA2LCB3aGVuIGFjY2Vzc2luZyBz
b21lIGxlZ2FjeSBJU0EgZGV2aWNlcyBjb25uZWN0ZWQgdG8gTFBDLCB0aG9zZQo+PiBrbm93biBw
b3J0IGFkZHJlc3NlcyBhcmUgdXNlZCB0byBjb250cm9sIHRoZSBjb3JyZXNwb25kaW5nIHRhcmdl
dCBkZXZpY2VzLCBmb3IKPj4gZXhhbXBsZSwgMHgyZjggaXMgZm9yIFVBUlQsIDB4ZTQgaXMgZm9y
IGlwbWktYnQuIEl0IGlzIGRpZmZlcmVudCBmcm9tIHRoZQo+PiBub3JtYWwgTU1JTyBtb2RlIGlu
IHVzaW5nLgo+Pgo+PiBUbyBkcml2ZSB0aGVzZSBkZXZpY2VzLCB0aGlzIHBhdGNoIGludHJvZHVj
ZXMgYSBtZXRob2QgbmFtZWQgaW5kaXJlY3QtSU8uCj4+IEluIHRoaXMgbWV0aG9kIHRoZSBpbi9v
dXQgcGFpciBpbiBhcmNoL2FybTY0L2luY2x1ZGUvYXNtL2lvLmggd2lsbCBiZQo+PiByZWRlZmlu
ZWQuIFdoZW4gdXBwZXIgbGF5ZXIgZHJpdmVycyBjYWxsIGluL291dCB3aXRoIHRob3NlIGtub3du
IGxlZ2FjeSBwb3J0Cj4+IGFkZHJlc3NlcyB0byBhY2Nlc3MgdGhlIHBlcmlwaGVyYWxzLCB0aGUg
aG9va2luZyBmdW5jdGlvbnMgY29ycnJlc3BvbmRpbmcgdG8KPj4gdGhvc2UgdGFyZ2V0IHBlcmlw
aGVyYWxzIHdpbGwgYmUgY2FsbGVkLiBUaHJvdWdoIHRoaXMgd2F5LCB0aG9zZSB1cHBlciBsYXll
cgo+PiBkcml2ZXJzIHdoaWNoIGRlcGVuZCBvbiBpbi9vdXQgY2FuIHJ1biBvbiBIaXAwNiB3aXRo
b3V0IGFueSBjaGFuZ2VzLgo+Pgo+PiBDYzogQ2F0YWxpbiBNYXJpbmFzIDxjYXRhbGluLm1hcmlu
YXNAYXJtLmNvbT4KPj4gQ2M6IFdpbGwgRGVhY29uIDx3aWxsLmRlYWNvbkBhcm0uY29tPgo+PiBT
aWduZWQtb2ZmLWJ5OiB6aGljaGFuZy55dWFuIDx5dWFuemhpY2hhbmdAaGlzaWxpY29uLmNvbT4K
Pj4gU2lnbmVkLW9mZi1ieTogR2FicmllbGUgUGFvbG9uaSA8Z2FicmllbGUucGFvbG9uaUBodWF3
ZWkuY29tPgo+PiAtLS0KPj4gIGFyY2gvYXJtNjQvS2NvbmZpZyAgICAgICAgICAgICB8ICA2ICsr
Kwo+PiAgYXJjaC9hcm02NC9pbmNsdWRlL2FzbS9leHRpby5oIHwgOTQgKysrKysrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKysrKysrCj4+ICBhcmNoL2FybTY0L2luY2x1ZGUvYXNtL2lv
LmggICAgfCAyOSArKysrKysrKysrKysrCj4+ICBhcmNoL2FybTY0L2tlcm5lbC9NYWtlZmlsZSAg
ICAgfCAgMSArCj4+ICBhcmNoL2FybTY0L2tlcm5lbC9leHRpby5jICAgICAgfCAyNyArKysrKysr
KysrKysKPj4gIDUgZmlsZXMgY2hhbmdlZCwgMTU3IGluc2VydGlvbnMoKykKPiAKPiBXaGVuIEkg
YXBwbGllZCB0aGVzZSB0aHJlZSBwYXRjaGVzIGFnYWluc3QgY3VycmVudCBsaW51cyB0cmVlIGFu
ZAo+IGVuYWJsZSBDT05GSUdfSElTSUxJQ09OX0xQQywgdGhlIGZvbGxvd2luZyBidWlsZCBmYWls
dXJlWzFdIGlzCj4gdHJpZ2dlcmVkIHdoZW4gcnVubmluZyAnbWFrZSBtb2R1bGVzJy4KPiAKClRo
YW5rcyBmb3IgeW91ciByZXBvcnQhCgpUaGlzIHBhdGNoIGhhcyBjb21waWxhdGlvbiBpc3N1ZSBv
biBzb21lIGFyY2hpdGVjdHVyZXMsIHNvcnJ5IGZvciB0aGUgaW5jb252ZW5pZW5jZSBjYXVzZWQg
YnkgdGhpcyEKVGhlIG9uZ29pbmcgdjYgd2lsbCBzb2x2ZSB0aGVzZSBpc3N1ZXMuCkkgd2lsbCB0
cmFjZSB0aGlzIGZhaWx1cmUgYW5kIHByb3ZpZGUgYSBmaXggaWYgeW91IGNhbiBub3Qgd2FpdCBm
b3IgdGhlIG5leHQgdmVyc2lvbi4KCkNvdWxkIHlvdSBzZW5kIG1lIHlvdXIgLmNvbmZpZyBpbiBw
cml2YXRlPyBJIGRvbid0IHdhbnQgdG8gYm90aGVyIGFsbCB0aGUgaGFja2VyIGluIHRoZSBtYWls
LWxpc3QuCgoKVGhhbmtzLApaaGljaGFuZwoKPiAKPiBUaGFua3MsCj4gTWluZwo+IAo+IFsxXSAn
bWFrZSBtb2R1bGVzJyBmYWlsdXJlIGxvZwo+IAo+ICAgQnVpbGRpbmcgbW9kdWxlcywgc3RhZ2Ug
Mi4KPiAgIE1PRFBPU1QgMjI2MCBtb2R1bGVzCj4gRVJST1I6ICJpbmIiIFtkcml2ZXJzL3dhdGNo
ZG9nL3dkdF9wY2kua29dIHVuZGVmaW5lZCEKPiBFUlJPUjogIm91dGIiIFtkcml2ZXJzL3dhdGNo
ZG9nL3dkdF9wY2kua29dIHVuZGVmaW5lZCEKPiBFUlJPUjogIm91dGIiIFtkcml2ZXJzL3dhdGNo
ZG9nL3Bjd2RfcGNpLmtvXSB1bmRlZmluZWQhCj4gRVJST1I6ICJpbmIiIFtkcml2ZXJzL3dhdGNo
ZG9nL3Bjd2RfcGNpLmtvXSB1bmRlZmluZWQhCj4gRVJST1I6ICJvdXR3IiBbZHJpdmVycy92aWRl
by92Z2FzdGF0ZS5rb10gdW5kZWZpbmVkIQo+IEVSUk9SOiAib3V0YiIgW2RyaXZlcnMvdmlkZW8v
dmdhc3RhdGUua29dIHVuZGVmaW5lZCEKPiBFUlJPUjogImluYiIgW2RyaXZlcnMvdmlkZW8vdmdh
c3RhdGUua29dIHVuZGVmaW5lZCEKPiBFUlJPUjogIm91dHciIFtkcml2ZXJzL3ZpZGVvL2ZiZGV2
L3Z0ODYyM2ZiLmtvXSB1bmRlZmluZWQhCj4gRVJST1I6ICJpbmIiIFtkcml2ZXJzL3ZpZGVvL2Zi
ZGV2L3Z0ODYyM2ZiLmtvXSB1bmRlZmluZWQhCj4gRVJST1I6ICJvdXRiIiBbZHJpdmVycy92aWRl
by9mYmRldi92dDg2MjNmYi5rb10gdW5kZWZpbmVkIQo+IEVSUk9SOiAib3V0dyIgW2RyaXZlcnMv
dmlkZW8vZmJkZXYvdHJpZGVudGZiLmtvXSB1bmRlZmluZWQhCj4gRVJST1I6ICJpbmIiIFtkcml2
ZXJzL3ZpZGVvL2ZiZGV2L3RyaWRlbnRmYi5rb10gdW5kZWZpbmVkIQo+IEVSUk9SOiAib3V0YiIg
W2RyaXZlcnMvdmlkZW8vZmJkZXYvdHJpZGVudGZiLmtvXSB1bmRlZmluZWQhCj4gRVJST1I6ICJp
bmIiIFtkcml2ZXJzL3ZpZGVvL2ZiZGV2L3RkZnhmYi5rb10gdW5kZWZpbmVkIQo+IC4uLi4uCj4g
RVJST1I6ICJpbmIiIFtkcml2ZXJzL2F0YS9wYXRhX2NtZDY0eC5rb10gdW5kZWZpbmVkIQo+IEVS
Uk9SOiAiaW5iIiBbZHJpdmVycy9hdGEvcGF0YV9hcnRvcC5rb10gdW5kZWZpbmVkIQo+IHNjcmlw
dHMvTWFrZWZpbGUubW9kcG9zdDo5MTogcmVjaXBlIGZvciB0YXJnZXQgJ19fbW9kcG9zdCcgZmFp
bGVkCj4gbWFrZVsxXTogKioqIFtfX21vZHBvc3RdIEVycm9yIDEKPiBNYWtlZmlsZToxMTk2OiBy
ZWNpcGUgZm9yIHRhcmdldCAnbW9kdWxlcycgZmFpbGVkCj4gbWFrZTogKioqIFttb2R1bGVzXSBF
cnJvciAyCj4gCj4gCj4+ICBjcmVhdGUgbW9kZSAxMDA2NDQgYXJjaC9hcm02NC9pbmNsdWRlL2Fz
bS9leHRpby5oCj4+ICBjcmVhdGUgbW9kZSAxMDA2NDQgYXJjaC9hcm02NC9rZXJuZWwvZXh0aW8u
Ywo+Pgo+PiBkaWZmIC0tZ2l0IGEvYXJjaC9hcm02NC9LY29uZmlnIGIvYXJjaC9hcm02NC9LY29u
ZmlnCj4+IGluZGV4IDk2OWVmODguLmI0NDA3MGIgMTAwNjQ0Cj4+IC0tLSBhL2FyY2gvYXJtNjQv
S2NvbmZpZwo+PiArKysgYi9hcmNoL2FybTY0L0tjb25maWcKPj4gQEAgLTE2Myw2ICsxNjMsMTIg
QEAgY29uZmlnIEFSQ0hfTU1BUF9STkRfQ09NUEFUX0JJVFNfTUlOCj4+ICBjb25maWcgQVJDSF9N
TUFQX1JORF9DT01QQVRfQklUU19NQVgKPj4gICAgICAgICBkZWZhdWx0IDE2Cj4+Cj4+ICtjb25m
aWcgQVJNNjRfSU5ESVJFQ1RfUElPCj4+ICsgICAgICAgYm9vbCAiYWNjZXNzIHBlcmlwaGVyYWxz
IHdpdGggbGVnYWN5IEkvTyBwb3J0Igo+PiArICAgICAgIGhlbHAKPj4gKyAgICAgICAgIFN1cHBv
cnQgc3BlY2lhbCBhY2Nlc3NvcnMgZm9yIElTQSBJL08gZGV2aWNlcy4gVGhpcyBpcyBuZWVkZWQg
Zm9yCj4+ICsgICAgICAgICBTb0NzIHRoYXQgZG8gbm90IHN1cHBvcnQgc3RhbmRhcmQgcmVhZC93
cml0ZSBmb3IgdGhlIElTQSByYW5nZS4KPj4gKwo+PiAgY29uZmlnIE5PX0lPUE9SVF9NQVAKPj4g
ICAgICAgICBkZWZfYm9vbCB5IGlmICFQQ0kKPj4KPj4gZGlmZiAtLWdpdCBhL2FyY2gvYXJtNjQv
aW5jbHVkZS9hc20vZXh0aW8uaCBiL2FyY2gvYXJtNjQvaW5jbHVkZS9hc20vZXh0aW8uaAo+PiBu
ZXcgZmlsZSBtb2RlIDEwMDY0NAo+PiBpbmRleCAwMDAwMDAwLi42YWUwNzg3Cj4+IC0tLSAvZGV2
L251bGwKPj4gKysrIGIvYXJjaC9hcm02NC9pbmNsdWRlL2FzbS9leHRpby5oCj4+IEBAIC0wLDAg
KzEsOTQgQEAKPj4gKy8qCj4+ICsgKiBDb3B5cmlnaHQgKEMpIDIwMTYgSGlzaWxpY29uIExpbWl0
ZWQsIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCj4+ICsgKiBBdXRob3I6IFpoaWNoYW5nIFl1YW4gPHl1
YW56aGljaGFuZ0BoaXNpbGljb24uY29tPgo+PiArICoKPj4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBm
cmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5Cj4+ICsg
KiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIHZl
cnNpb24gMiBhcwo+PiArICogcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRp
b24uCj4+ICsgKgo+PiArICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3Bl
IHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCj4+ICsgKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7
IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgo+PiArICogTUVSQ0hBTlRBQklM
SVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZQo+PiArICog
R05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KPj4gKyAqCj4+ICsg
KiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJs
aWMgTGljZW5zZQo+PiArICogYWxvbmcgd2l0aCB0aGlzIHByb2dyYW0uICBJZiBub3QsIHNlZSA8
aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uCj4+ICsgKi8KPj4gKwo+PiArI2lmbmRlZiBf
X0xJTlVYX0VYVElPX0gKPj4gKyNkZWZpbmUgX19MSU5VWF9FWFRJT19ICj4+ICsKPj4gK3N0cnVj
dCBleHRpb19vcHMgewo+PiArICAgICAgIHVuc2lnbmVkIGxvbmcgc3RhcnQ7LyogaW5jbHVzaXZl
LCBzeXMgaW8gYWRkciAqLwo+PiArICAgICAgIHVuc2lnbmVkIGxvbmcgZW5kOy8qIGluY2x1c2l2
ZSwgc3lzIGlvIGFkZHIgKi8KPj4gKwo+PiArICAgICAgIHU2NCAoKnBmaW4pKHZvaWQgKmRldm9i
aiwgdW5zaWduZWQgbG9uZyBwdGFkZHIsIHNpemVfdCBkbGVuKTsKPj4gKyAgICAgICB2b2lkICgq
cGZvdXQpKHZvaWQgKmRldm9iaiwgdW5zaWduZWQgbG9uZyBwdGFkZHIsIHUzMiBvdXR2YWwsCj4+
ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplX3QgZGxlbik7Cj4+
ICsgICAgICAgdTY0ICgqcGZpbnMpKHZvaWQgKmRldm9iaiwgdW5zaWduZWQgbG9uZyBwdGFkZHIs
IHZvaWQgKmluYnVmLAo+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemVfdCBk
bGVuLCB1bnNpZ25lZCBpbnQgY291bnQpOwo+PiArICAgICAgIHZvaWQgKCpwZm91dHMpKHZvaWQg
KmRldm9iaiwgdW5zaWduZWQgbG9uZyBwdGFkZHIsCj4+ICsgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgY29uc3Qgdm9pZCAqb3V0YnVmLCBzaXplX3QgZGxlbiwKPj4gKyAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICB1bnNpZ25lZCBpbnQgY291bnQpOwo+PiArICAgICAgIHZvaWQg
KmRldnBhcmE7Cj4+ICt9Owo+PiArCj4+ICtleHRlcm4gc3RydWN0IGV4dGlvX29wcyAqYXJtNjRf
ZXh0aW9fb3BzOwo+PiArCj4+ICsjZGVmaW5lIERFQ0xBUkVfRVhUSU8oYncsIHR5cGUpICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAo+PiArZXh0ZXJuIHR5
cGUgaW4jI2J3KHVuc2lnbmVkIGxvbmcgYWRkcik7ICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgIFwKPj4gK2V4dGVybiB2b2lkIG91dCMjYncodHlwZSB2YWx1ZSwgdW5zaWdu
ZWQgbG9uZyBhZGRyKTsgICAgICAgICAgICAgICAgICAgXAo+PiArZXh0ZXJuIHZvaWQgaW5zIyNi
dyh1bnNpZ25lZCBsb25nIGFkZHIsIHZvaWQgKmJ1ZmZlciwgdW5zaWduZWQgaW50IGNvdW50KTtc
Cj4+ICtleHRlcm4gdm9pZCBvdXRzIyNidyh1bnNpZ25lZCBsb25nIGFkZHIsIGNvbnN0IHZvaWQg
KmJ1ZmZlciwgdW5zaWduZWQgaW50IGNvdW50KTsKPj4gKwo+PiArI2RlZmluZSBCVUlMRF9FWFRJ
TyhidywgdHlwZSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCj4+
ICt0eXBlIGluIyNidyh1bnNpZ25lZCBsb25nIGFkZHIpICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgXAo+PiAreyAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCj4+ICsgICAgICAg
aWYgKCFhcm02NF9leHRpb19vcHMgfHwgYXJtNjRfZXh0aW9fb3BzLT5zdGFydCA+IGFkZHIgfHwg
ICAgICAgIFwKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgYXJtNjRfZXh0aW9fb3BzLT5lbmQg
PCBhZGRyKSAgICAgICAgICAgICAgICAgICAgXAo+PiArICAgICAgICAgICAgICAgcmV0dXJuIHJl
YWQjI2J3KFBDSV9JT0JBU0UgKyBhZGRyKTsgICAgICAgICAgICAgICAgICAgICBcCj4+ICsgICAg
ICAgcmV0dXJuIGFybTY0X2V4dGlvX29wcy0+cGZpbiA/ICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgIFwKPj4gKyAgICAgICAgICAgICAgIGFybTY0X2V4dGlvX29wcy0+cGZpbihhcm02
NF9leHRpb19vcHMtPmRldnBhcmEsICAgICAgICAgXAo+PiArICAgICAgICAgICAgICAgICAgICAg
ICBhZGRyLCBzaXplb2YodHlwZSkpIDogLTE7ICAgICAgICAgICAgICAgICAgICAgICBcCj4+ICt9
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgIFwKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAo+PiArdm9pZCBvdXQjI2J3KHR5cGUg
dmFsdWUsIHVuc2lnbmVkIGxvbmcgYWRkcikgICAgICAgICAgICAgICAgICAgICAgICAgICBcCj4+
ICt7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgIFwKPj4gKyAgICAgICBpZiAoIWFybTY0X2V4dGlvX29wcyB8fCBhcm02
NF9leHRpb19vcHMtPnN0YXJ0ID4gYWRkciB8fCAgICAgICAgXAo+PiArICAgICAgICAgICAgICAg
ICAgICAgICBhcm02NF9leHRpb19vcHMtPmVuZCA8IGFkZHIpICAgICAgICAgICAgICAgICAgICBc
Cj4+ICsgICAgICAgICAgICAgICB3cml0ZSMjYncodmFsdWUsIFBDSV9JT0JBU0UgKyBhZGRyKTsg
ICAgICAgICAgICAgICAgICAgIFwKPj4gKyAgICAgICBlbHNlICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAo+PiArICAgICAgICAgICAg
ICAgaWYgKGFybTY0X2V4dGlvX29wcy0+cGZvdXQpICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICBcCj4+ICsgICAgICAgICAgICAgICAgICAgICAgIGFybTY0X2V4dGlvX29wcy0+cGZvdXQoYXJt
NjRfZXh0aW9fb3BzLT5kZXZwYXJhLFwKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICBhZGRyLCB2YWx1ZSwgc2l6ZW9mKHR5cGUpKTsgICAgICAgICAgICAgXAo+PiArfSAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICBcCj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgIFwKPj4gK3ZvaWQgaW5zIyNidyh1bnNpZ25lZCBsb25n
IGFkZHIsIHZvaWQgKmJ1ZmZlciwgdW5zaWduZWQgaW50IGNvdW50KSAgICAgXAo+PiAreyAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICBcCj4+ICsgICAgICAgaWYgKCFhcm02NF9leHRpb19vcHMgfHwgYXJtNjRfZXh0aW9f
b3BzLT5zdGFydCA+IGFkZHIgfHwgICAgICAgIFwKPj4gKyAgICAgICAgICAgICAgICAgICAgICAg
YXJtNjRfZXh0aW9fb3BzLT5lbmQgPCBhZGRyKSAgICAgICAgICAgICAgICAgICAgXAo+PiArICAg
ICAgICAgICAgICAgcmVhZHMjI2J3KFBDSV9JT0JBU0UgKyBhZGRyLCBidWZmZXIsIGNvdW50KTsg
ICAgICAgICAgICBcCj4+ICsgICAgICAgZWxzZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKPj4gKyAgICAgICAgICAgICAgIGlmIChh
cm02NF9leHRpb19vcHMtPnBmaW5zKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAo+PiAr
ICAgICAgICAgICAgICAgICAgICAgICBhcm02NF9leHRpb19vcHMtPnBmaW5zKGFybTY0X2V4dGlv
X29wcy0+ZGV2cGFyYSxcCj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRkciwg
YnVmZmVyLCBzaXplb2YodHlwZSksIGNvdW50KTsgICAgIFwKPj4gK30gICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAo+
PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICBcCj4+ICt2b2lkIG91dHMjI2J3KHVuc2lnbmVkIGxvbmcgYWRkciwg
Y29uc3Qgdm9pZCAqYnVmZmVyLCB1bnNpZ25lZCBpbnQgY291bnQpICAgICAgXAo+PiAreyAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICBcCj4+ICsgICAgICAgaWYgKCFhcm02NF9leHRpb19vcHMgfHwgYXJtNjRfZXh0aW9f
b3BzLT5zdGFydCA+IGFkZHIgfHwgICAgICAgIFwKPj4gKyAgICAgICAgICAgICAgICAgICAgICAg
YXJtNjRfZXh0aW9fb3BzLT5lbmQgPCBhZGRyKSAgICAgICAgICAgICAgICAgICAgXAo+PiArICAg
ICAgICAgICAgICAgd3JpdGVzIyNidyhQQ0lfSU9CQVNFICsgYWRkciwgYnVmZmVyLCBjb3VudCk7
ICAgICAgICAgICBcCj4+ICsgICAgICAgZWxzZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKPj4gKyAgICAgICAgICAgICAgIGlmIChh
cm02NF9leHRpb19vcHMtPnBmb3V0cykgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAo+PiAr
ICAgICAgICAgICAgICAgICAgICAgICBhcm02NF9leHRpb19vcHMtPnBmb3V0cyhhcm02NF9leHRp
b19vcHMtPmRldnBhcmEsXAo+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkZHIs
IGJ1ZmZlciwgc2l6ZW9mKHR5cGUpLCBjb3VudCk7ICAgICBcCj4+ICt9Cj4+ICsKPj4gK3N0YXRp
YyBpbmxpbmUgdm9pZCBhcm02NF9zZXRfZXh0b3BzKHN0cnVjdCBleHRpb19vcHMgKm9wcykKPj4g
K3sKPj4gKyAgICAgICBpZiAob3BzKQo+PiArICAgICAgICAgICAgICAgV1JJVEVfT05DRShhcm02
NF9leHRpb19vcHMsIG9wcyk7Cj4+ICt9Cj4+ICsKPj4gKyNlbmRpZiAvKiBfX0xJTlVYX0VYVElP
X0gqLwo+PiBkaWZmIC0tZ2l0IGEvYXJjaC9hcm02NC9pbmNsdWRlL2FzbS9pby5oIGIvYXJjaC9h
cm02NC9pbmNsdWRlL2FzbS9pby5oCj4+IGluZGV4IDBiYmE0MjcuLjEzNjczNWQgMTAwNjQ0Cj4+
IC0tLSBhL2FyY2gvYXJtNjQvaW5jbHVkZS9hc20vaW8uaAo+PiArKysgYi9hcmNoL2FybTY0L2lu
Y2x1ZGUvYXNtL2lvLmgKPj4gQEAgLTMxLDYgKzMxLDcgQEAKPj4gICNpbmNsdWRlIDxhc20vZWFy
bHlfaW9yZW1hcC5oPgo+PiAgI2luY2x1ZGUgPGFzbS9hbHRlcm5hdGl2ZS5oPgo+PiAgI2luY2x1
ZGUgPGFzbS9jcHVmZWF0dXJlLmg+Cj4+ICsjaW5jbHVkZSA8YXNtL2V4dGlvLmg+Cj4+Cj4+ICAj
aW5jbHVkZSA8eGVuL3hlbi5oPgo+Pgo+PiBAQCAtMTQ5LDYgKzE1MCwzNCBAQCBzdGF0aWMgaW5s
aW5lIHU2NCBfX3Jhd19yZWFkcShjb25zdCB2b2xhdGlsZSB2b2lkIF9faW9tZW0gKmFkZHIpCj4+
ICAjZGVmaW5lIElPX1NQQUNFX0xJTUlUICAgICAgICAgKFBDSV9JT19TSVpFIC0gMSkKPj4gICNk
ZWZpbmUgUENJX0lPQkFTRSAgICAgICAgICAgICAoKHZvaWQgX19pb21lbSAqKVBDSV9JT19TVEFS
VCkKPj4KPj4gKwo+PiArLyoKPj4gKyAqIHJlZGVmaW5lIHRoZSBpbihzKWIvb3V0KHMpYiBmb3Ig
aW5kaXJlY3QtSU8uCj4+ICsgKi8KPj4gKyNpZmRlZiBDT05GSUdfQVJNNjRfSU5ESVJFQ1RfUElP
Cj4+ICsjZGVmaW5lIGluYiBpbmIKPj4gKyNkZWZpbmUgb3V0YiBvdXRiCj4+ICsjZGVmaW5lIGlu
c2IgaW5zYgo+PiArI2RlZmluZSBvdXRzYiBvdXRzYgo+PiArLyogZXh0ZXJuYWwgZGVjbGFyYXRp
b24gKi8KPj4gK0RFQ0xBUkVfRVhUSU8oYiwgdTgpCj4+ICsKPj4gKyNkZWZpbmUgaW53IGludwo+
PiArI2RlZmluZSBvdXR3IG91dHcKPj4gKyNkZWZpbmUgaW5zdyBpbnN3Cj4+ICsjZGVmaW5lIG91
dHN3IG91dHN3Cj4+ICsKPj4gK0RFQ0xBUkVfRVhUSU8odywgdTE2KQo+PiArCj4+ICsjZGVmaW5l
IGlubCBpbmwKPj4gKyNkZWZpbmUgb3V0bCBvdXRsCj4+ICsjZGVmaW5lIGluc2wgaW5zbAo+PiAr
I2RlZmluZSBvdXRzbCBvdXRzbAo+PiArCj4+ICtERUNMQVJFX0VYVElPKGwsIHUzMikKPj4gKyNl
bmRpZgo+PiArCj4+ICsKPj4gIC8qCj4+ICAgKiBTdHJpbmcgdmVyc2lvbiBvZiBJL08gbWVtb3J5
IGFjY2VzcyBvcGVyYXRpb25zLgo+PiAgICovCj4+IGRpZmYgLS1naXQgYS9hcmNoL2FybTY0L2tl
cm5lbC9NYWtlZmlsZSBiL2FyY2gvYXJtNjQva2VybmVsL01ha2VmaWxlCj4+IGluZGV4IDdkNjZi
YmEuLjYwZTA0ODIgMTAwNjQ0Cj4+IC0tLSBhL2FyY2gvYXJtNjQva2VybmVsL01ha2VmaWxlCj4+
ICsrKyBiL2FyY2gvYXJtNjQva2VybmVsL01ha2VmaWxlCj4+IEBAIC0zMSw2ICszMSw3IEBAIGFy
bTY0LW9iai0kKENPTkZJR19DT01QQVQpICAgICAgICAgICAgKz0gc3lzMzIubyBrdXNlcjMyLm8g
c2lnbmFsMzIubyAgICAgICAgIFwKPj4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgIHN5c19jb21wYXQubyBlbnRyeTMyLm8KPj4gIGFybTY0LW9iai0kKENPTkZJR19G
VU5DVElPTl9UUkFDRVIpICAgICs9IGZ0cmFjZS5vIGVudHJ5LWZ0cmFjZS5vCj4+ICBhcm02NC1v
YmotJChDT05GSUdfTU9EVUxFUykgICAgICAgICAgICArPSBhcm02NGtzeW1zLm8gbW9kdWxlLm8K
Pj4gK2FybTY0LW9iai0kKENPTkZJR19BUk02NF9JTkRJUkVDVF9QSU8pICs9IGV4dGlvLm8KPj4g
IGFybTY0LW9iai0kKENPTkZJR19BUk02NF9NT0RVTEVfUExUUykgICs9IG1vZHVsZS1wbHRzLm8K
Pj4gIGFybTY0LW9iai0kKENPTkZJR19QRVJGX0VWRU5UUykgICAgICAgICAgICAgICAgKz0gcGVy
Zl9yZWdzLm8gcGVyZl9jYWxsY2hhaW4ubwo+PiAgYXJtNjQtb2JqLSQoQ09ORklHX0hXX1BFUkZf
RVZFTlRTKSAgICAgKz0gcGVyZl9ldmVudC5vCj4+IGRpZmYgLS1naXQgYS9hcmNoL2FybTY0L2tl
cm5lbC9leHRpby5jIGIvYXJjaC9hcm02NC9rZXJuZWwvZXh0aW8uYwo+PiBuZXcgZmlsZSBtb2Rl
IDEwMDY0NAo+PiBpbmRleCAwMDAwMDAwLi42NDdiM2ZhCj4+IC0tLSAvZGV2L251bGwKPj4gKysr
IGIvYXJjaC9hcm02NC9rZXJuZWwvZXh0aW8uYwo+PiBAQCAtMCwwICsxLDI3IEBACj4+ICsvKgo+
PiArICogQ29weXJpZ2h0IChDKSAyMDE2IEhpc2lsaWNvbiBMaW1pdGVkLCBBbGwgUmlnaHRzIFJl
c2VydmVkLgo+PiArICogQXV0aG9yOiBaaGljaGFuZyBZdWFuIDx5dWFuemhpY2hhbmdAaGlzaWxp
Y29uLmNvbT4KPj4gKyAqCj4+ICsgKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91
IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeQo+PiArICogaXQgdW5kZXIgdGhlIHRl
cm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSB2ZXJzaW9uIDIgYXMKPj4gKyAq
IHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLgo+PiArICoKPj4gKyAq
IFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUg
dXNlZnVsLAo+PiArICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhl
IGltcGxpZWQgd2FycmFudHkgb2YKPj4gKyAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZP
UiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUKPj4gKyAqIEdOVSBHZW5lcmFsIFB1Ymxp
YyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCj4+ICsgKgo+PiArICogWW91IHNob3VsZCBoYXZl
IHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKPj4gKyAq
IGFsb25nIHdpdGggdGhpcyBwcm9ncmFtLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9y
Zy9saWNlbnNlcy8+Lgo+PiArICovCj4+ICsKPj4gKyNpbmNsdWRlIDxsaW51eC9pby5oPgo+PiAr
Cj4+ICtzdHJ1Y3QgZXh0aW9fb3BzICphcm02NF9leHRpb19vcHM7Cj4+ICsKPj4gKwo+PiArQlVJ
TERfRVhUSU8oYiwgdTgpCj4+ICsKPj4gK0JVSUxEX0VYVElPKHcsIHUxNikKPj4gKwo+PiArQlVJ
TERfRVhUSU8obCwgdTMyKQo+PiAtLQo+PiAxLjkuMQo+Pgo+IAo+IAo+IAoKCl9fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmxpbnV4LWFybS1rZXJuZWwgbWFp
bGluZyBsaXN0CmxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlz
dHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LWFybS1rZXJuZWwK

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-12-23  1:43       ` zhichang.yuan
  0 siblings, 0 replies; 286+ messages in thread
From: zhichang.yuan @ 2016-12-23  1:43 UTC (permalink / raw)
  To: linux-arm-kernel

Hi?Ming,


On 2016/12/22 16:15, Ming Lei wrote:
> Hi Guys,
> 
> On Tue, Nov 8, 2016 at 11:47 AM, zhichang.yuan
> <yuanzhichang@hisilicon.com> wrote:
>> For arm64, there is no I/O space as other architectural platforms, such as
>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>> known port addresses are used to control the corresponding target devices, for
>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>> normal MMIO mode in using.
>>
>> To drive these devices, this patch introduces a method named indirect-IO.
>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>> redefined. When upper layer drivers call in/out with those known legacy port
>> addresses to access the peripherals, the hooking functions corrresponding to
>> those target peripherals will be called. Through this way, those upper layer
>> drivers which depend on in/out can run on Hip06 without any changes.
>>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
>> ---
>>  arch/arm64/Kconfig             |  6 +++
>>  arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>>  arch/arm64/include/asm/io.h    | 29 +++++++++++++
>>  arch/arm64/kernel/Makefile     |  1 +
>>  arch/arm64/kernel/extio.c      | 27 ++++++++++++
>>  5 files changed, 157 insertions(+)
> 
> When I applied these three patches against current linus tree and
> enable CONFIG_HISILICON_LPC, the following build failure[1] is
> triggered when running 'make modules'.
> 

Thanks for your report!

This patch has compilation issue on some architectures, sorry for the inconvenience caused by this!
The ongoing v6 will solve these issues.
I will trace this failure and provide a fix if you can not wait for the next version.

Could you send me your .config in private? I don't want to bother all the hacker in the mail-list.


Thanks,
Zhichang

> 
> Thanks,
> Ming
> 
> [1] 'make modules' failure log
> 
>   Building modules, stage 2.
>   MODPOST 2260 modules
> ERROR: "inb" [drivers/watchdog/wdt_pci.ko] undefined!
> ERROR: "outb" [drivers/watchdog/wdt_pci.ko] undefined!
> ERROR: "outb" [drivers/watchdog/pcwd_pci.ko] undefined!
> ERROR: "inb" [drivers/watchdog/pcwd_pci.ko] undefined!
> ERROR: "outw" [drivers/video/vgastate.ko] undefined!
> ERROR: "outb" [drivers/video/vgastate.ko] undefined!
> ERROR: "inb" [drivers/video/vgastate.ko] undefined!
> ERROR: "outw" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "outb" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "outw" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "outb" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/tdfxfb.ko] undefined!
> .....
> ERROR: "inb" [drivers/ata/pata_cmd64x.ko] undefined!
> ERROR: "inb" [drivers/ata/pata_artop.ko] undefined!
> scripts/Makefile.modpost:91: recipe for target '__modpost' failed
> make[1]: *** [__modpost] Error 1
> Makefile:1196: recipe for target 'modules' failed
> make: *** [modules] Error 2
> 
> 
>>  create mode 100644 arch/arm64/include/asm/extio.h
>>  create mode 100644 arch/arm64/kernel/extio.c
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 969ef88..b44070b 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>>         default 16
>>
>> +config ARM64_INDIRECT_PIO
>> +       bool "access peripherals with legacy I/O port"
>> +       help
>> +         Support special accessors for ISA I/O devices. This is needed for
>> +         SoCs that do not support standard read/write for the ISA range.
>> +
>>  config NO_IOPORT_MAP
>>         def_bool y if !PCI
>>
>> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
>> new file mode 100644
>> index 0000000..6ae0787
>> --- /dev/null
>> +++ b/arch/arm64/include/asm/extio.h
>> @@ -0,0 +1,94 @@
>> +/*
>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef __LINUX_EXTIO_H
>> +#define __LINUX_EXTIO_H
>> +
>> +struct extio_ops {
>> +       unsigned long start;/* inclusive, sys io addr */
>> +       unsigned long end;/* inclusive, sys io addr */
>> +
>> +       u64 (*pfin)(void *devobj, unsigned long ptaddr, size_t dlen);
>> +       void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
>> +                                       size_t dlen);
>> +       u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
>> +                               size_t dlen, unsigned int count);
>> +       void (*pfouts)(void *devobj, unsigned long ptaddr,
>> +                               const void *outbuf, size_t dlen,
>> +                               unsigned int count);
>> +       void *devpara;
>> +};
>> +
>> +extern struct extio_ops *arm64_extio_ops;
>> +
>> +#define DECLARE_EXTIO(bw, type)                                                \
>> +extern type in##bw(unsigned long addr);                                        \
>> +extern void out##bw(type value, unsigned long addr);                   \
>> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
>> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
>> +
>> +#define BUILD_EXTIO(bw, type)                                          \
>> +type in##bw(unsigned long addr)                                                \
>> +{                                                                      \
>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>> +                       arm64_extio_ops->end < addr)                    \
>> +               return read##bw(PCI_IOBASE + addr);                     \
>> +       return arm64_extio_ops->pfin ?                                  \
>> +               arm64_extio_ops->pfin(arm64_extio_ops->devpara,         \
>> +                       addr, sizeof(type)) : -1;                       \
>> +}                                                                      \
>> +                                                                       \
>> +void out##bw(type value, unsigned long addr)                           \
>> +{                                                                      \
>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>> +                       arm64_extio_ops->end < addr)                    \
>> +               write##bw(value, PCI_IOBASE + addr);                    \
>> +       else                                                            \
>> +               if (arm64_extio_ops->pfout)                             \
>> +                       arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>> +                               addr, value, sizeof(type));             \
>> +}                                                                      \
>> +                                                                       \
>> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)     \
>> +{                                                                      \
>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>> +                       arm64_extio_ops->end < addr)                    \
>> +               reads##bw(PCI_IOBASE + addr, buffer, count);            \
>> +       else                                                            \
>> +               if (arm64_extio_ops->pfins)                             \
>> +                       arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
>> +                               addr, buffer, sizeof(type), count);     \
>> +}                                                                      \
>> +                                                                       \
>> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)      \
>> +{                                                                      \
>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>> +                       arm64_extio_ops->end < addr)                    \
>> +               writes##bw(PCI_IOBASE + addr, buffer, count);           \
>> +       else                                                            \
>> +               if (arm64_extio_ops->pfouts)                            \
>> +                       arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
>> +                               addr, buffer, sizeof(type), count);     \
>> +}
>> +
>> +static inline void arm64_set_extops(struct extio_ops *ops)
>> +{
>> +       if (ops)
>> +               WRITE_ONCE(arm64_extio_ops, ops);
>> +}
>> +
>> +#endif /* __LINUX_EXTIO_H*/
>> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
>> index 0bba427..136735d 100644
>> --- a/arch/arm64/include/asm/io.h
>> +++ b/arch/arm64/include/asm/io.h
>> @@ -31,6 +31,7 @@
>>  #include <asm/early_ioremap.h>
>>  #include <asm/alternative.h>
>>  #include <asm/cpufeature.h>
>> +#include <asm/extio.h>
>>
>>  #include <xen/xen.h>
>>
>> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>  #define IO_SPACE_LIMIT         (PCI_IO_SIZE - 1)
>>  #define PCI_IOBASE             ((void __iomem *)PCI_IO_START)
>>
>> +
>> +/*
>> + * redefine the in(s)b/out(s)b for indirect-IO.
>> + */
>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>> +#define inb inb
>> +#define outb outb
>> +#define insb insb
>> +#define outsb outsb
>> +/* external declaration */
>> +DECLARE_EXTIO(b, u8)
>> +
>> +#define inw inw
>> +#define outw outw
>> +#define insw insw
>> +#define outsw outsw
>> +
>> +DECLARE_EXTIO(w, u16)
>> +
>> +#define inl inl
>> +#define outl outl
>> +#define insl insl
>> +#define outsl outsl
>> +
>> +DECLARE_EXTIO(l, u32)
>> +#endif
>> +
>> +
>>  /*
>>   * String version of I/O memory access operations.
>>   */
>> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
>> index 7d66bba..60e0482 100644
>> --- a/arch/arm64/kernel/Makefile
>> +++ b/arch/arm64/kernel/Makefile
>> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)            += sys32.o kuser32.o signal32.o         \
>>                                            sys_compat.o entry32.o
>>  arm64-obj-$(CONFIG_FUNCTION_TRACER)    += ftrace.o entry-ftrace.o
>>  arm64-obj-$(CONFIG_MODULES)            += arm64ksyms.o module.o
>> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO) += extio.o
>>  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)  += module-plts.o
>>  arm64-obj-$(CONFIG_PERF_EVENTS)                += perf_regs.o perf_callchain.o
>>  arm64-obj-$(CONFIG_HW_PERF_EVENTS)     += perf_event.o
>> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
>> new file mode 100644
>> index 0000000..647b3fa
>> --- /dev/null
>> +++ b/arch/arm64/kernel/extio.c
>> @@ -0,0 +1,27 @@
>> +/*
>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <linux/io.h>
>> +
>> +struct extio_ops *arm64_extio_ops;
>> +
>> +
>> +BUILD_EXTIO(b, u8)
>> +
>> +BUILD_EXTIO(w, u16)
>> +
>> +BUILD_EXTIO(l, u32)
>> --
>> 1.9.1
>>
> 
> 
> 

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-12-23  1:43       ` zhichang.yuan
  (?)
  (?)
@ 2016-12-23  7:24         ` Ming Lei
  -1 siblings, 0 replies; 286+ messages in thread
From: Ming Lei @ 2016-12-23  7:24 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: Catalin Marinas, Will Deacon, Rob Herring, Bjorn Helgaas,
	Mark Rutland, Olof Johansson, Arnd Bergmann, linux-arm-kernel,
	Lorenzo Pieralisi, Linux Kernel Mailing List, linuxarm,
	devicetree, linux-pci, linux-serial, Corey Minyard,
	Benjamin Herrenschmidt, Liviu Dudau, Zou Rongrong, john.garry,
	gabriele.paoloni, zhichang.yuan02, kantyzc, xuwei5

[-- Attachment #1: Type: text/plain, Size: 13571 bytes --]

On Fri, Dec 23, 2016 at 9:43 AM, zhichang.yuan
<yuanzhichang@hisilicon.com> wrote:
> Hi,Ming,
>
>
> On 2016/12/22 16:15, Ming Lei wrote:
>> Hi Guys,
>>
>> On Tue, Nov 8, 2016 at 11:47 AM, zhichang.yuan
>> <yuanzhichang@hisilicon.com> wrote:
>>> For arm64, there is no I/O space as other architectural platforms, such as
>>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>>> known port addresses are used to control the corresponding target devices, for
>>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>>> normal MMIO mode in using.
>>>
>>> To drive these devices, this patch introduces a method named indirect-IO.
>>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>>> redefined. When upper layer drivers call in/out with those known legacy port
>>> addresses to access the peripherals, the hooking functions corrresponding to
>>> those target peripherals will be called. Through this way, those upper layer
>>> drivers which depend on in/out can run on Hip06 without any changes.
>>>
>>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>>> Cc: Will Deacon <will.deacon@arm.com>
>>> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
>>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
>>> ---
>>>  arch/arm64/Kconfig             |  6 +++
>>>  arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>>>  arch/arm64/include/asm/io.h    | 29 +++++++++++++
>>>  arch/arm64/kernel/Makefile     |  1 +
>>>  arch/arm64/kernel/extio.c      | 27 ++++++++++++
>>>  5 files changed, 157 insertions(+)
>>
>> When I applied these three patches against current linus tree and
>> enable CONFIG_HISILICON_LPC, the following build failure[1] is
>> triggered when running 'make modules'.
>>
>
> Thanks for your report!
>
> This patch has compilation issue on some architectures, sorry for the inconvenience caused by this!
> The ongoing v6 will solve these issues.
> I will trace this failure and provide a fix if you can not wait for the next version.
>
> Could you send me your .config in private? I don't want to bother all the hacker in the mail-list.
>

Sure, please see the config in attachment.

>
> Thanks,
> Zhichang
>
>>
>> Thanks,
>> Ming
>>
>> [1] 'make modules' failure log
>>
>>   Building modules, stage 2.
>>   MODPOST 2260 modules
>> ERROR: "inb" [drivers/watchdog/wdt_pci.ko] undefined!
>> ERROR: "outb" [drivers/watchdog/wdt_pci.ko] undefined!
>> ERROR: "outb" [drivers/watchdog/pcwd_pci.ko] undefined!
>> ERROR: "inb" [drivers/watchdog/pcwd_pci.ko] undefined!
>> ERROR: "outw" [drivers/video/vgastate.ko] undefined!
>> ERROR: "outb" [drivers/video/vgastate.ko] undefined!
>> ERROR: "inb" [drivers/video/vgastate.ko] undefined!
>> ERROR: "outw" [drivers/video/fbdev/vt8623fb.ko] undefined!
>> ERROR: "inb" [drivers/video/fbdev/vt8623fb.ko] undefined!
>> ERROR: "outb" [drivers/video/fbdev/vt8623fb.ko] undefined!
>> ERROR: "outw" [drivers/video/fbdev/tridentfb.ko] undefined!
>> ERROR: "inb" [drivers/video/fbdev/tridentfb.ko] undefined!
>> ERROR: "outb" [drivers/video/fbdev/tridentfb.ko] undefined!
>> ERROR: "inb" [drivers/video/fbdev/tdfxfb.ko] undefined!
>> .....
>> ERROR: "inb" [drivers/ata/pata_cmd64x.ko] undefined!
>> ERROR: "inb" [drivers/ata/pata_artop.ko] undefined!
>> scripts/Makefile.modpost:91: recipe for target '__modpost' failed
>> make[1]: *** [__modpost] Error 1
>> Makefile:1196: recipe for target 'modules' failed
>> make: *** [modules] Error 2
>>
>>
>>>  create mode 100644 arch/arm64/include/asm/extio.h
>>>  create mode 100644 arch/arm64/kernel/extio.c
>>>
>>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>>> index 969ef88..b44070b 100644
>>> --- a/arch/arm64/Kconfig
>>> +++ b/arch/arm64/Kconfig
>>> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>>>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>>>         default 16
>>>
>>> +config ARM64_INDIRECT_PIO
>>> +       bool "access peripherals with legacy I/O port"
>>> +       help
>>> +         Support special accessors for ISA I/O devices. This is needed for
>>> +         SoCs that do not support standard read/write for the ISA range.
>>> +
>>>  config NO_IOPORT_MAP
>>>         def_bool y if !PCI
>>>
>>> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
>>> new file mode 100644
>>> index 0000000..6ae0787
>>> --- /dev/null
>>> +++ b/arch/arm64/include/asm/extio.h
>>> @@ -0,0 +1,94 @@
>>> +/*
>>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#ifndef __LINUX_EXTIO_H
>>> +#define __LINUX_EXTIO_H
>>> +
>>> +struct extio_ops {
>>> +       unsigned long start;/* inclusive, sys io addr */
>>> +       unsigned long end;/* inclusive, sys io addr */
>>> +
>>> +       u64 (*pfin)(void *devobj, unsigned long ptaddr, size_t dlen);
>>> +       void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
>>> +                                       size_t dlen);
>>> +       u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
>>> +                               size_t dlen, unsigned int count);
>>> +       void (*pfouts)(void *devobj, unsigned long ptaddr,
>>> +                               const void *outbuf, size_t dlen,
>>> +                               unsigned int count);
>>> +       void *devpara;
>>> +};
>>> +
>>> +extern struct extio_ops *arm64_extio_ops;
>>> +
>>> +#define DECLARE_EXTIO(bw, type)                                                \
>>> +extern type in##bw(unsigned long addr);                                        \
>>> +extern void out##bw(type value, unsigned long addr);                   \
>>> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
>>> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
>>> +
>>> +#define BUILD_EXTIO(bw, type)                                          \
>>> +type in##bw(unsigned long addr)                                                \
>>> +{                                                                      \
>>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>>> +                       arm64_extio_ops->end < addr)                    \
>>> +               return read##bw(PCI_IOBASE + addr);                     \
>>> +       return arm64_extio_ops->pfin ?                                  \
>>> +               arm64_extio_ops->pfin(arm64_extio_ops->devpara,         \
>>> +                       addr, sizeof(type)) : -1;                       \
>>> +}                                                                      \
>>> +                                                                       \
>>> +void out##bw(type value, unsigned long addr)                           \
>>> +{                                                                      \
>>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>>> +                       arm64_extio_ops->end < addr)                    \
>>> +               write##bw(value, PCI_IOBASE + addr);                    \
>>> +       else                                                            \
>>> +               if (arm64_extio_ops->pfout)                             \
>>> +                       arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>>> +                               addr, value, sizeof(type));             \
>>> +}                                                                      \
>>> +                                                                       \
>>> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)     \
>>> +{                                                                      \
>>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>>> +                       arm64_extio_ops->end < addr)                    \
>>> +               reads##bw(PCI_IOBASE + addr, buffer, count);            \
>>> +       else                                                            \
>>> +               if (arm64_extio_ops->pfins)                             \
>>> +                       arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
>>> +                               addr, buffer, sizeof(type), count);     \
>>> +}                                                                      \
>>> +                                                                       \
>>> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)      \
>>> +{                                                                      \
>>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>>> +                       arm64_extio_ops->end < addr)                    \
>>> +               writes##bw(PCI_IOBASE + addr, buffer, count);           \
>>> +       else                                                            \
>>> +               if (arm64_extio_ops->pfouts)                            \
>>> +                       arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
>>> +                               addr, buffer, sizeof(type), count);     \
>>> +}
>>> +
>>> +static inline void arm64_set_extops(struct extio_ops *ops)
>>> +{
>>> +       if (ops)
>>> +               WRITE_ONCE(arm64_extio_ops, ops);
>>> +}
>>> +
>>> +#endif /* __LINUX_EXTIO_H*/
>>> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
>>> index 0bba427..136735d 100644
>>> --- a/arch/arm64/include/asm/io.h
>>> +++ b/arch/arm64/include/asm/io.h
>>> @@ -31,6 +31,7 @@
>>>  #include <asm/early_ioremap.h>
>>>  #include <asm/alternative.h>
>>>  #include <asm/cpufeature.h>
>>> +#include <asm/extio.h>
>>>
>>>  #include <xen/xen.h>
>>>
>>> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>>  #define IO_SPACE_LIMIT         (PCI_IO_SIZE - 1)
>>>  #define PCI_IOBASE             ((void __iomem *)PCI_IO_START)
>>>
>>> +
>>> +/*
>>> + * redefine the in(s)b/out(s)b for indirect-IO.
>>> + */
>>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>>> +#define inb inb
>>> +#define outb outb
>>> +#define insb insb
>>> +#define outsb outsb
>>> +/* external declaration */
>>> +DECLARE_EXTIO(b, u8)
>>> +
>>> +#define inw inw
>>> +#define outw outw
>>> +#define insw insw
>>> +#define outsw outsw
>>> +
>>> +DECLARE_EXTIO(w, u16)
>>> +
>>> +#define inl inl
>>> +#define outl outl
>>> +#define insl insl
>>> +#define outsl outsl
>>> +
>>> +DECLARE_EXTIO(l, u32)
>>> +#endif
>>> +
>>> +
>>>  /*
>>>   * String version of I/O memory access operations.
>>>   */
>>> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
>>> index 7d66bba..60e0482 100644
>>> --- a/arch/arm64/kernel/Makefile
>>> +++ b/arch/arm64/kernel/Makefile
>>> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)            += sys32.o kuser32.o signal32.o         \
>>>                                            sys_compat.o entry32.o
>>>  arm64-obj-$(CONFIG_FUNCTION_TRACER)    += ftrace.o entry-ftrace.o
>>>  arm64-obj-$(CONFIG_MODULES)            += arm64ksyms.o module.o
>>> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO) += extio.o
>>>  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)  += module-plts.o
>>>  arm64-obj-$(CONFIG_PERF_EVENTS)                += perf_regs.o perf_callchain.o
>>>  arm64-obj-$(CONFIG_HW_PERF_EVENTS)     += perf_event.o
>>> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
>>> new file mode 100644
>>> index 0000000..647b3fa
>>> --- /dev/null
>>> +++ b/arch/arm64/kernel/extio.c
>>> @@ -0,0 +1,27 @@
>>> +/*
>>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#include <linux/io.h>
>>> +
>>> +struct extio_ops *arm64_extio_ops;
>>> +
>>> +
>>> +BUILD_EXTIO(b, u8)
>>> +
>>> +BUILD_EXTIO(w, u16)
>>> +
>>> +BUILD_EXTIO(l, u32)
>>> --
>>> 1.9.1
>>>
>>
>>
>>
>



Thanks,
Ming Lei

[-- Attachment #2: config.tar.gz --]
[-- Type: application/x-gzip, Size: 37193 bytes --]

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-12-23  7:24         ` Ming Lei
  0 siblings, 0 replies; 286+ messages in thread
From: Ming Lei @ 2016-12-23  7:24 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: Catalin Marinas, Will Deacon, Rob Herring, Bjorn Helgaas,
	Mark Rutland, Olof Johansson, Arnd Bergmann, linux-arm-kernel,
	Lorenzo Pieralisi, Linux Kernel Mailing List, linuxarm,
	devicetree, linux-pci, linux-serial, Corey Minyard,
	Benjamin Herrenschmidt, Liviu Dudau, Zou Rongrong, john.garry,
	gabriele.

[-- Attachment #1: Type: text/plain, Size: 13571 bytes --]

On Fri, Dec 23, 2016 at 9:43 AM, zhichang.yuan
<yuanzhichang@hisilicon.com> wrote:
> Hi,Ming,
>
>
> On 2016/12/22 16:15, Ming Lei wrote:
>> Hi Guys,
>>
>> On Tue, Nov 8, 2016 at 11:47 AM, zhichang.yuan
>> <yuanzhichang@hisilicon.com> wrote:
>>> For arm64, there is no I/O space as other architectural platforms, such as
>>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>>> known port addresses are used to control the corresponding target devices, for
>>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>>> normal MMIO mode in using.
>>>
>>> To drive these devices, this patch introduces a method named indirect-IO.
>>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>>> redefined. When upper layer drivers call in/out with those known legacy port
>>> addresses to access the peripherals, the hooking functions corrresponding to
>>> those target peripherals will be called. Through this way, those upper layer
>>> drivers which depend on in/out can run on Hip06 without any changes.
>>>
>>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>>> Cc: Will Deacon <will.deacon@arm.com>
>>> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
>>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
>>> ---
>>>  arch/arm64/Kconfig             |  6 +++
>>>  arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>>>  arch/arm64/include/asm/io.h    | 29 +++++++++++++
>>>  arch/arm64/kernel/Makefile     |  1 +
>>>  arch/arm64/kernel/extio.c      | 27 ++++++++++++
>>>  5 files changed, 157 insertions(+)
>>
>> When I applied these three patches against current linus tree and
>> enable CONFIG_HISILICON_LPC, the following build failure[1] is
>> triggered when running 'make modules'.
>>
>
> Thanks for your report!
>
> This patch has compilation issue on some architectures, sorry for the inconvenience caused by this!
> The ongoing v6 will solve these issues.
> I will trace this failure and provide a fix if you can not wait for the next version.
>
> Could you send me your .config in private? I don't want to bother all the hacker in the mail-list.
>

Sure, please see the config in attachment.

>
> Thanks,
> Zhichang
>
>>
>> Thanks,
>> Ming
>>
>> [1] 'make modules' failure log
>>
>>   Building modules, stage 2.
>>   MODPOST 2260 modules
>> ERROR: "inb" [drivers/watchdog/wdt_pci.ko] undefined!
>> ERROR: "outb" [drivers/watchdog/wdt_pci.ko] undefined!
>> ERROR: "outb" [drivers/watchdog/pcwd_pci.ko] undefined!
>> ERROR: "inb" [drivers/watchdog/pcwd_pci.ko] undefined!
>> ERROR: "outw" [drivers/video/vgastate.ko] undefined!
>> ERROR: "outb" [drivers/video/vgastate.ko] undefined!
>> ERROR: "inb" [drivers/video/vgastate.ko] undefined!
>> ERROR: "outw" [drivers/video/fbdev/vt8623fb.ko] undefined!
>> ERROR: "inb" [drivers/video/fbdev/vt8623fb.ko] undefined!
>> ERROR: "outb" [drivers/video/fbdev/vt8623fb.ko] undefined!
>> ERROR: "outw" [drivers/video/fbdev/tridentfb.ko] undefined!
>> ERROR: "inb" [drivers/video/fbdev/tridentfb.ko] undefined!
>> ERROR: "outb" [drivers/video/fbdev/tridentfb.ko] undefined!
>> ERROR: "inb" [drivers/video/fbdev/tdfxfb.ko] undefined!
>> .....
>> ERROR: "inb" [drivers/ata/pata_cmd64x.ko] undefined!
>> ERROR: "inb" [drivers/ata/pata_artop.ko] undefined!
>> scripts/Makefile.modpost:91: recipe for target '__modpost' failed
>> make[1]: *** [__modpost] Error 1
>> Makefile:1196: recipe for target 'modules' failed
>> make: *** [modules] Error 2
>>
>>
>>>  create mode 100644 arch/arm64/include/asm/extio.h
>>>  create mode 100644 arch/arm64/kernel/extio.c
>>>
>>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>>> index 969ef88..b44070b 100644
>>> --- a/arch/arm64/Kconfig
>>> +++ b/arch/arm64/Kconfig
>>> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>>>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>>>         default 16
>>>
>>> +config ARM64_INDIRECT_PIO
>>> +       bool "access peripherals with legacy I/O port"
>>> +       help
>>> +         Support special accessors for ISA I/O devices. This is needed for
>>> +         SoCs that do not support standard read/write for the ISA range.
>>> +
>>>  config NO_IOPORT_MAP
>>>         def_bool y if !PCI
>>>
>>> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
>>> new file mode 100644
>>> index 0000000..6ae0787
>>> --- /dev/null
>>> +++ b/arch/arm64/include/asm/extio.h
>>> @@ -0,0 +1,94 @@
>>> +/*
>>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#ifndef __LINUX_EXTIO_H
>>> +#define __LINUX_EXTIO_H
>>> +
>>> +struct extio_ops {
>>> +       unsigned long start;/* inclusive, sys io addr */
>>> +       unsigned long end;/* inclusive, sys io addr */
>>> +
>>> +       u64 (*pfin)(void *devobj, unsigned long ptaddr, size_t dlen);
>>> +       void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
>>> +                                       size_t dlen);
>>> +       u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
>>> +                               size_t dlen, unsigned int count);
>>> +       void (*pfouts)(void *devobj, unsigned long ptaddr,
>>> +                               const void *outbuf, size_t dlen,
>>> +                               unsigned int count);
>>> +       void *devpara;
>>> +};
>>> +
>>> +extern struct extio_ops *arm64_extio_ops;
>>> +
>>> +#define DECLARE_EXTIO(bw, type)                                                \
>>> +extern type in##bw(unsigned long addr);                                        \
>>> +extern void out##bw(type value, unsigned long addr);                   \
>>> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
>>> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
>>> +
>>> +#define BUILD_EXTIO(bw, type)                                          \
>>> +type in##bw(unsigned long addr)                                                \
>>> +{                                                                      \
>>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>>> +                       arm64_extio_ops->end < addr)                    \
>>> +               return read##bw(PCI_IOBASE + addr);                     \
>>> +       return arm64_extio_ops->pfin ?                                  \
>>> +               arm64_extio_ops->pfin(arm64_extio_ops->devpara,         \
>>> +                       addr, sizeof(type)) : -1;                       \
>>> +}                                                                      \
>>> +                                                                       \
>>> +void out##bw(type value, unsigned long addr)                           \
>>> +{                                                                      \
>>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>>> +                       arm64_extio_ops->end < addr)                    \
>>> +               write##bw(value, PCI_IOBASE + addr);                    \
>>> +       else                                                            \
>>> +               if (arm64_extio_ops->pfout)                             \
>>> +                       arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>>> +                               addr, value, sizeof(type));             \
>>> +}                                                                      \
>>> +                                                                       \
>>> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)     \
>>> +{                                                                      \
>>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>>> +                       arm64_extio_ops->end < addr)                    \
>>> +               reads##bw(PCI_IOBASE + addr, buffer, count);            \
>>> +       else                                                            \
>>> +               if (arm64_extio_ops->pfins)                             \
>>> +                       arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
>>> +                               addr, buffer, sizeof(type), count);     \
>>> +}                                                                      \
>>> +                                                                       \
>>> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)      \
>>> +{                                                                      \
>>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>>> +                       arm64_extio_ops->end < addr)                    \
>>> +               writes##bw(PCI_IOBASE + addr, buffer, count);           \
>>> +       else                                                            \
>>> +               if (arm64_extio_ops->pfouts)                            \
>>> +                       arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
>>> +                               addr, buffer, sizeof(type), count);     \
>>> +}
>>> +
>>> +static inline void arm64_set_extops(struct extio_ops *ops)
>>> +{
>>> +       if (ops)
>>> +               WRITE_ONCE(arm64_extio_ops, ops);
>>> +}
>>> +
>>> +#endif /* __LINUX_EXTIO_H*/
>>> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
>>> index 0bba427..136735d 100644
>>> --- a/arch/arm64/include/asm/io.h
>>> +++ b/arch/arm64/include/asm/io.h
>>> @@ -31,6 +31,7 @@
>>>  #include <asm/early_ioremap.h>
>>>  #include <asm/alternative.h>
>>>  #include <asm/cpufeature.h>
>>> +#include <asm/extio.h>
>>>
>>>  #include <xen/xen.h>
>>>
>>> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>>  #define IO_SPACE_LIMIT         (PCI_IO_SIZE - 1)
>>>  #define PCI_IOBASE             ((void __iomem *)PCI_IO_START)
>>>
>>> +
>>> +/*
>>> + * redefine the in(s)b/out(s)b for indirect-IO.
>>> + */
>>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>>> +#define inb inb
>>> +#define outb outb
>>> +#define insb insb
>>> +#define outsb outsb
>>> +/* external declaration */
>>> +DECLARE_EXTIO(b, u8)
>>> +
>>> +#define inw inw
>>> +#define outw outw
>>> +#define insw insw
>>> +#define outsw outsw
>>> +
>>> +DECLARE_EXTIO(w, u16)
>>> +
>>> +#define inl inl
>>> +#define outl outl
>>> +#define insl insl
>>> +#define outsl outsl
>>> +
>>> +DECLARE_EXTIO(l, u32)
>>> +#endif
>>> +
>>> +
>>>  /*
>>>   * String version of I/O memory access operations.
>>>   */
>>> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
>>> index 7d66bba..60e0482 100644
>>> --- a/arch/arm64/kernel/Makefile
>>> +++ b/arch/arm64/kernel/Makefile
>>> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)            += sys32.o kuser32.o signal32.o         \
>>>                                            sys_compat.o entry32.o
>>>  arm64-obj-$(CONFIG_FUNCTION_TRACER)    += ftrace.o entry-ftrace.o
>>>  arm64-obj-$(CONFIG_MODULES)            += arm64ksyms.o module.o
>>> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO) += extio.o
>>>  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)  += module-plts.o
>>>  arm64-obj-$(CONFIG_PERF_EVENTS)                += perf_regs.o perf_callchain.o
>>>  arm64-obj-$(CONFIG_HW_PERF_EVENTS)     += perf_event.o
>>> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
>>> new file mode 100644
>>> index 0000000..647b3fa
>>> --- /dev/null
>>> +++ b/arch/arm64/kernel/extio.c
>>> @@ -0,0 +1,27 @@
>>> +/*
>>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#include <linux/io.h>
>>> +
>>> +struct extio_ops *arm64_extio_ops;
>>> +
>>> +
>>> +BUILD_EXTIO(b, u8)
>>> +
>>> +BUILD_EXTIO(w, u16)
>>> +
>>> +BUILD_EXTIO(l, u32)
>>> --
>>> 1.9.1
>>>
>>
>>
>>
>



Thanks,
Ming Lei

[-- Attachment #2: config.tar.gz --]
[-- Type: application/x-gzip, Size: 37193 bytes --]

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-12-23  7:24         ` Ming Lei
  0 siblings, 0 replies; 286+ messages in thread
From: Ming Lei @ 2016-12-23  7:24 UTC (permalink / raw)
  To: zhichang.yuan
  Cc: Mark Rutland, gabriele.paoloni, Benjamin Herrenschmidt,
	Will Deacon, linuxarm, Lorenzo Pieralisi, Arnd Bergmann, xuwei5,
	linux-serial, Catalin Marinas, devicetree, Corey Minyard,
	Liviu Dudau, john.garry, Zou Rongrong, Rob Herring,
	Bjorn Helgaas, kantyzc, zhichang.yuan02, linux-arm-kernel,
	linux-pci, Linux Kernel Mailing List, Olof Johansson

[-- Attachment #1: Type: text/plain, Size: 13571 bytes --]

On Fri, Dec 23, 2016 at 9:43 AM, zhichang.yuan
<yuanzhichang@hisilicon.com> wrote:
> Hi,Ming,
>
>
> On 2016/12/22 16:15, Ming Lei wrote:
>> Hi Guys,
>>
>> On Tue, Nov 8, 2016 at 11:47 AM, zhichang.yuan
>> <yuanzhichang@hisilicon.com> wrote:
>>> For arm64, there is no I/O space as other architectural platforms, such as
>>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>>> known port addresses are used to control the corresponding target devices, for
>>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>>> normal MMIO mode in using.
>>>
>>> To drive these devices, this patch introduces a method named indirect-IO.
>>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>>> redefined. When upper layer drivers call in/out with those known legacy port
>>> addresses to access the peripherals, the hooking functions corrresponding to
>>> those target peripherals will be called. Through this way, those upper layer
>>> drivers which depend on in/out can run on Hip06 without any changes.
>>>
>>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>>> Cc: Will Deacon <will.deacon@arm.com>
>>> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
>>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
>>> ---
>>>  arch/arm64/Kconfig             |  6 +++
>>>  arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>>>  arch/arm64/include/asm/io.h    | 29 +++++++++++++
>>>  arch/arm64/kernel/Makefile     |  1 +
>>>  arch/arm64/kernel/extio.c      | 27 ++++++++++++
>>>  5 files changed, 157 insertions(+)
>>
>> When I applied these three patches against current linus tree and
>> enable CONFIG_HISILICON_LPC, the following build failure[1] is
>> triggered when running 'make modules'.
>>
>
> Thanks for your report!
>
> This patch has compilation issue on some architectures, sorry for the inconvenience caused by this!
> The ongoing v6 will solve these issues.
> I will trace this failure and provide a fix if you can not wait for the next version.
>
> Could you send me your .config in private? I don't want to bother all the hacker in the mail-list.
>

Sure, please see the config in attachment.

>
> Thanks,
> Zhichang
>
>>
>> Thanks,
>> Ming
>>
>> [1] 'make modules' failure log
>>
>>   Building modules, stage 2.
>>   MODPOST 2260 modules
>> ERROR: "inb" [drivers/watchdog/wdt_pci.ko] undefined!
>> ERROR: "outb" [drivers/watchdog/wdt_pci.ko] undefined!
>> ERROR: "outb" [drivers/watchdog/pcwd_pci.ko] undefined!
>> ERROR: "inb" [drivers/watchdog/pcwd_pci.ko] undefined!
>> ERROR: "outw" [drivers/video/vgastate.ko] undefined!
>> ERROR: "outb" [drivers/video/vgastate.ko] undefined!
>> ERROR: "inb" [drivers/video/vgastate.ko] undefined!
>> ERROR: "outw" [drivers/video/fbdev/vt8623fb.ko] undefined!
>> ERROR: "inb" [drivers/video/fbdev/vt8623fb.ko] undefined!
>> ERROR: "outb" [drivers/video/fbdev/vt8623fb.ko] undefined!
>> ERROR: "outw" [drivers/video/fbdev/tridentfb.ko] undefined!
>> ERROR: "inb" [drivers/video/fbdev/tridentfb.ko] undefined!
>> ERROR: "outb" [drivers/video/fbdev/tridentfb.ko] undefined!
>> ERROR: "inb" [drivers/video/fbdev/tdfxfb.ko] undefined!
>> .....
>> ERROR: "inb" [drivers/ata/pata_cmd64x.ko] undefined!
>> ERROR: "inb" [drivers/ata/pata_artop.ko] undefined!
>> scripts/Makefile.modpost:91: recipe for target '__modpost' failed
>> make[1]: *** [__modpost] Error 1
>> Makefile:1196: recipe for target 'modules' failed
>> make: *** [modules] Error 2
>>
>>
>>>  create mode 100644 arch/arm64/include/asm/extio.h
>>>  create mode 100644 arch/arm64/kernel/extio.c
>>>
>>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>>> index 969ef88..b44070b 100644
>>> --- a/arch/arm64/Kconfig
>>> +++ b/arch/arm64/Kconfig
>>> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>>>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>>>         default 16
>>>
>>> +config ARM64_INDIRECT_PIO
>>> +       bool "access peripherals with legacy I/O port"
>>> +       help
>>> +         Support special accessors for ISA I/O devices. This is needed for
>>> +         SoCs that do not support standard read/write for the ISA range.
>>> +
>>>  config NO_IOPORT_MAP
>>>         def_bool y if !PCI
>>>
>>> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
>>> new file mode 100644
>>> index 0000000..6ae0787
>>> --- /dev/null
>>> +++ b/arch/arm64/include/asm/extio.h
>>> @@ -0,0 +1,94 @@
>>> +/*
>>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#ifndef __LINUX_EXTIO_H
>>> +#define __LINUX_EXTIO_H
>>> +
>>> +struct extio_ops {
>>> +       unsigned long start;/* inclusive, sys io addr */
>>> +       unsigned long end;/* inclusive, sys io addr */
>>> +
>>> +       u64 (*pfin)(void *devobj, unsigned long ptaddr, size_t dlen);
>>> +       void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
>>> +                                       size_t dlen);
>>> +       u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
>>> +                               size_t dlen, unsigned int count);
>>> +       void (*pfouts)(void *devobj, unsigned long ptaddr,
>>> +                               const void *outbuf, size_t dlen,
>>> +                               unsigned int count);
>>> +       void *devpara;
>>> +};
>>> +
>>> +extern struct extio_ops *arm64_extio_ops;
>>> +
>>> +#define DECLARE_EXTIO(bw, type)                                                \
>>> +extern type in##bw(unsigned long addr);                                        \
>>> +extern void out##bw(type value, unsigned long addr);                   \
>>> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
>>> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
>>> +
>>> +#define BUILD_EXTIO(bw, type)                                          \
>>> +type in##bw(unsigned long addr)                                                \
>>> +{                                                                      \
>>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>>> +                       arm64_extio_ops->end < addr)                    \
>>> +               return read##bw(PCI_IOBASE + addr);                     \
>>> +       return arm64_extio_ops->pfin ?                                  \
>>> +               arm64_extio_ops->pfin(arm64_extio_ops->devpara,         \
>>> +                       addr, sizeof(type)) : -1;                       \
>>> +}                                                                      \
>>> +                                                                       \
>>> +void out##bw(type value, unsigned long addr)                           \
>>> +{                                                                      \
>>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>>> +                       arm64_extio_ops->end < addr)                    \
>>> +               write##bw(value, PCI_IOBASE + addr);                    \
>>> +       else                                                            \
>>> +               if (arm64_extio_ops->pfout)                             \
>>> +                       arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>>> +                               addr, value, sizeof(type));             \
>>> +}                                                                      \
>>> +                                                                       \
>>> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)     \
>>> +{                                                                      \
>>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>>> +                       arm64_extio_ops->end < addr)                    \
>>> +               reads##bw(PCI_IOBASE + addr, buffer, count);            \
>>> +       else                                                            \
>>> +               if (arm64_extio_ops->pfins)                             \
>>> +                       arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
>>> +                               addr, buffer, sizeof(type), count);     \
>>> +}                                                                      \
>>> +                                                                       \
>>> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)      \
>>> +{                                                                      \
>>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>>> +                       arm64_extio_ops->end < addr)                    \
>>> +               writes##bw(PCI_IOBASE + addr, buffer, count);           \
>>> +       else                                                            \
>>> +               if (arm64_extio_ops->pfouts)                            \
>>> +                       arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
>>> +                               addr, buffer, sizeof(type), count);     \
>>> +}
>>> +
>>> +static inline void arm64_set_extops(struct extio_ops *ops)
>>> +{
>>> +       if (ops)
>>> +               WRITE_ONCE(arm64_extio_ops, ops);
>>> +}
>>> +
>>> +#endif /* __LINUX_EXTIO_H*/
>>> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
>>> index 0bba427..136735d 100644
>>> --- a/arch/arm64/include/asm/io.h
>>> +++ b/arch/arm64/include/asm/io.h
>>> @@ -31,6 +31,7 @@
>>>  #include <asm/early_ioremap.h>
>>>  #include <asm/alternative.h>
>>>  #include <asm/cpufeature.h>
>>> +#include <asm/extio.h>
>>>
>>>  #include <xen/xen.h>
>>>
>>> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>>  #define IO_SPACE_LIMIT         (PCI_IO_SIZE - 1)
>>>  #define PCI_IOBASE             ((void __iomem *)PCI_IO_START)
>>>
>>> +
>>> +/*
>>> + * redefine the in(s)b/out(s)b for indirect-IO.
>>> + */
>>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>>> +#define inb inb
>>> +#define outb outb
>>> +#define insb insb
>>> +#define outsb outsb
>>> +/* external declaration */
>>> +DECLARE_EXTIO(b, u8)
>>> +
>>> +#define inw inw
>>> +#define outw outw
>>> +#define insw insw
>>> +#define outsw outsw
>>> +
>>> +DECLARE_EXTIO(w, u16)
>>> +
>>> +#define inl inl
>>> +#define outl outl
>>> +#define insl insl
>>> +#define outsl outsl
>>> +
>>> +DECLARE_EXTIO(l, u32)
>>> +#endif
>>> +
>>> +
>>>  /*
>>>   * String version of I/O memory access operations.
>>>   */
>>> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
>>> index 7d66bba..60e0482 100644
>>> --- a/arch/arm64/kernel/Makefile
>>> +++ b/arch/arm64/kernel/Makefile
>>> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)            += sys32.o kuser32.o signal32.o         \
>>>                                            sys_compat.o entry32.o
>>>  arm64-obj-$(CONFIG_FUNCTION_TRACER)    += ftrace.o entry-ftrace.o
>>>  arm64-obj-$(CONFIG_MODULES)            += arm64ksyms.o module.o
>>> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO) += extio.o
>>>  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)  += module-plts.o
>>>  arm64-obj-$(CONFIG_PERF_EVENTS)                += perf_regs.o perf_callchain.o
>>>  arm64-obj-$(CONFIG_HW_PERF_EVENTS)     += perf_event.o
>>> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
>>> new file mode 100644
>>> index 0000000..647b3fa
>>> --- /dev/null
>>> +++ b/arch/arm64/kernel/extio.c
>>> @@ -0,0 +1,27 @@
>>> +/*
>>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#include <linux/io.h>
>>> +
>>> +struct extio_ops *arm64_extio_ops;
>>> +
>>> +
>>> +BUILD_EXTIO(b, u8)
>>> +
>>> +BUILD_EXTIO(w, u16)
>>> +
>>> +BUILD_EXTIO(l, u32)
>>> --
>>> 1.9.1
>>>
>>
>>
>>
>



Thanks,
Ming Lei

[-- Attachment #2: config.tar.gz --]
[-- Type: application/x-gzip, Size: 37193 bytes --]

[-- Attachment #3: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2016-12-23  7:24         ` Ming Lei
  0 siblings, 0 replies; 286+ messages in thread
From: Ming Lei @ 2016-12-23  7:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Dec 23, 2016 at 9:43 AM, zhichang.yuan
<yuanzhichang@hisilicon.com> wrote:
> Hi?Ming,
>
>
> On 2016/12/22 16:15, Ming Lei wrote:
>> Hi Guys,
>>
>> On Tue, Nov 8, 2016 at 11:47 AM, zhichang.yuan
>> <yuanzhichang@hisilicon.com> wrote:
>>> For arm64, there is no I/O space as other architectural platforms, such as
>>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>>> known port addresses are used to control the corresponding target devices, for
>>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>>> normal MMIO mode in using.
>>>
>>> To drive these devices, this patch introduces a method named indirect-IO.
>>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>>> redefined. When upper layer drivers call in/out with those known legacy port
>>> addresses to access the peripherals, the hooking functions corrresponding to
>>> those target peripherals will be called. Through this way, those upper layer
>>> drivers which depend on in/out can run on Hip06 without any changes.
>>>
>>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>>> Cc: Will Deacon <will.deacon@arm.com>
>>> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
>>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
>>> ---
>>>  arch/arm64/Kconfig             |  6 +++
>>>  arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>>>  arch/arm64/include/asm/io.h    | 29 +++++++++++++
>>>  arch/arm64/kernel/Makefile     |  1 +
>>>  arch/arm64/kernel/extio.c      | 27 ++++++++++++
>>>  5 files changed, 157 insertions(+)
>>
>> When I applied these three patches against current linus tree and
>> enable CONFIG_HISILICON_LPC, the following build failure[1] is
>> triggered when running 'make modules'.
>>
>
> Thanks for your report!
>
> This patch has compilation issue on some architectures, sorry for the inconvenience caused by this!
> The ongoing v6 will solve these issues.
> I will trace this failure and provide a fix if you can not wait for the next version.
>
> Could you send me your .config in private? I don't want to bother all the hacker in the mail-list.
>

Sure, please see the config in attachment.

>
> Thanks,
> Zhichang
>
>>
>> Thanks,
>> Ming
>>
>> [1] 'make modules' failure log
>>
>>   Building modules, stage 2.
>>   MODPOST 2260 modules
>> ERROR: "inb" [drivers/watchdog/wdt_pci.ko] undefined!
>> ERROR: "outb" [drivers/watchdog/wdt_pci.ko] undefined!
>> ERROR: "outb" [drivers/watchdog/pcwd_pci.ko] undefined!
>> ERROR: "inb" [drivers/watchdog/pcwd_pci.ko] undefined!
>> ERROR: "outw" [drivers/video/vgastate.ko] undefined!
>> ERROR: "outb" [drivers/video/vgastate.ko] undefined!
>> ERROR: "inb" [drivers/video/vgastate.ko] undefined!
>> ERROR: "outw" [drivers/video/fbdev/vt8623fb.ko] undefined!
>> ERROR: "inb" [drivers/video/fbdev/vt8623fb.ko] undefined!
>> ERROR: "outb" [drivers/video/fbdev/vt8623fb.ko] undefined!
>> ERROR: "outw" [drivers/video/fbdev/tridentfb.ko] undefined!
>> ERROR: "inb" [drivers/video/fbdev/tridentfb.ko] undefined!
>> ERROR: "outb" [drivers/video/fbdev/tridentfb.ko] undefined!
>> ERROR: "inb" [drivers/video/fbdev/tdfxfb.ko] undefined!
>> .....
>> ERROR: "inb" [drivers/ata/pata_cmd64x.ko] undefined!
>> ERROR: "inb" [drivers/ata/pata_artop.ko] undefined!
>> scripts/Makefile.modpost:91: recipe for target '__modpost' failed
>> make[1]: *** [__modpost] Error 1
>> Makefile:1196: recipe for target 'modules' failed
>> make: *** [modules] Error 2
>>
>>
>>>  create mode 100644 arch/arm64/include/asm/extio.h
>>>  create mode 100644 arch/arm64/kernel/extio.c
>>>
>>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>>> index 969ef88..b44070b 100644
>>> --- a/arch/arm64/Kconfig
>>> +++ b/arch/arm64/Kconfig
>>> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>>>  config ARCH_MMAP_RND_COMPAT_BITS_MAX
>>>         default 16
>>>
>>> +config ARM64_INDIRECT_PIO
>>> +       bool "access peripherals with legacy I/O port"
>>> +       help
>>> +         Support special accessors for ISA I/O devices. This is needed for
>>> +         SoCs that do not support standard read/write for the ISA range.
>>> +
>>>  config NO_IOPORT_MAP
>>>         def_bool y if !PCI
>>>
>>> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
>>> new file mode 100644
>>> index 0000000..6ae0787
>>> --- /dev/null
>>> +++ b/arch/arm64/include/asm/extio.h
>>> @@ -0,0 +1,94 @@
>>> +/*
>>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#ifndef __LINUX_EXTIO_H
>>> +#define __LINUX_EXTIO_H
>>> +
>>> +struct extio_ops {
>>> +       unsigned long start;/* inclusive, sys io addr */
>>> +       unsigned long end;/* inclusive, sys io addr */
>>> +
>>> +       u64 (*pfin)(void *devobj, unsigned long ptaddr, size_t dlen);
>>> +       void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
>>> +                                       size_t dlen);
>>> +       u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
>>> +                               size_t dlen, unsigned int count);
>>> +       void (*pfouts)(void *devobj, unsigned long ptaddr,
>>> +                               const void *outbuf, size_t dlen,
>>> +                               unsigned int count);
>>> +       void *devpara;
>>> +};
>>> +
>>> +extern struct extio_ops *arm64_extio_ops;
>>> +
>>> +#define DECLARE_EXTIO(bw, type)                                                \
>>> +extern type in##bw(unsigned long addr);                                        \
>>> +extern void out##bw(type value, unsigned long addr);                   \
>>> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
>>> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
>>> +
>>> +#define BUILD_EXTIO(bw, type)                                          \
>>> +type in##bw(unsigned long addr)                                                \
>>> +{                                                                      \
>>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>>> +                       arm64_extio_ops->end < addr)                    \
>>> +               return read##bw(PCI_IOBASE + addr);                     \
>>> +       return arm64_extio_ops->pfin ?                                  \
>>> +               arm64_extio_ops->pfin(arm64_extio_ops->devpara,         \
>>> +                       addr, sizeof(type)) : -1;                       \
>>> +}                                                                      \
>>> +                                                                       \
>>> +void out##bw(type value, unsigned long addr)                           \
>>> +{                                                                      \
>>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>>> +                       arm64_extio_ops->end < addr)                    \
>>> +               write##bw(value, PCI_IOBASE + addr);                    \
>>> +       else                                                            \
>>> +               if (arm64_extio_ops->pfout)                             \
>>> +                       arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>>> +                               addr, value, sizeof(type));             \
>>> +}                                                                      \
>>> +                                                                       \
>>> +void ins##bw(unsigned long addr, void *buffer, unsigned int count)     \
>>> +{                                                                      \
>>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>>> +                       arm64_extio_ops->end < addr)                    \
>>> +               reads##bw(PCI_IOBASE + addr, buffer, count);            \
>>> +       else                                                            \
>>> +               if (arm64_extio_ops->pfins)                             \
>>> +                       arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
>>> +                               addr, buffer, sizeof(type), count);     \
>>> +}                                                                      \
>>> +                                                                       \
>>> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count)      \
>>> +{                                                                      \
>>> +       if (!arm64_extio_ops || arm64_extio_ops->start > addr ||        \
>>> +                       arm64_extio_ops->end < addr)                    \
>>> +               writes##bw(PCI_IOBASE + addr, buffer, count);           \
>>> +       else                                                            \
>>> +               if (arm64_extio_ops->pfouts)                            \
>>> +                       arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
>>> +                               addr, buffer, sizeof(type), count);     \
>>> +}
>>> +
>>> +static inline void arm64_set_extops(struct extio_ops *ops)
>>> +{
>>> +       if (ops)
>>> +               WRITE_ONCE(arm64_extio_ops, ops);
>>> +}
>>> +
>>> +#endif /* __LINUX_EXTIO_H*/
>>> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
>>> index 0bba427..136735d 100644
>>> --- a/arch/arm64/include/asm/io.h
>>> +++ b/arch/arm64/include/asm/io.h
>>> @@ -31,6 +31,7 @@
>>>  #include <asm/early_ioremap.h>
>>>  #include <asm/alternative.h>
>>>  #include <asm/cpufeature.h>
>>> +#include <asm/extio.h>
>>>
>>>  #include <xen/xen.h>
>>>
>>> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>>  #define IO_SPACE_LIMIT         (PCI_IO_SIZE - 1)
>>>  #define PCI_IOBASE             ((void __iomem *)PCI_IO_START)
>>>
>>> +
>>> +/*
>>> + * redefine the in(s)b/out(s)b for indirect-IO.
>>> + */
>>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>>> +#define inb inb
>>> +#define outb outb
>>> +#define insb insb
>>> +#define outsb outsb
>>> +/* external declaration */
>>> +DECLARE_EXTIO(b, u8)
>>> +
>>> +#define inw inw
>>> +#define outw outw
>>> +#define insw insw
>>> +#define outsw outsw
>>> +
>>> +DECLARE_EXTIO(w, u16)
>>> +
>>> +#define inl inl
>>> +#define outl outl
>>> +#define insl insl
>>> +#define outsl outsl
>>> +
>>> +DECLARE_EXTIO(l, u32)
>>> +#endif
>>> +
>>> +
>>>  /*
>>>   * String version of I/O memory access operations.
>>>   */
>>> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
>>> index 7d66bba..60e0482 100644
>>> --- a/arch/arm64/kernel/Makefile
>>> +++ b/arch/arm64/kernel/Makefile
>>> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)            += sys32.o kuser32.o signal32.o         \
>>>                                            sys_compat.o entry32.o
>>>  arm64-obj-$(CONFIG_FUNCTION_TRACER)    += ftrace.o entry-ftrace.o
>>>  arm64-obj-$(CONFIG_MODULES)            += arm64ksyms.o module.o
>>> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO) += extio.o
>>>  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)  += module-plts.o
>>>  arm64-obj-$(CONFIG_PERF_EVENTS)                += perf_regs.o perf_callchain.o
>>>  arm64-obj-$(CONFIG_HW_PERF_EVENTS)     += perf_event.o
>>> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
>>> new file mode 100644
>>> index 0000000..647b3fa
>>> --- /dev/null
>>> +++ b/arch/arm64/kernel/extio.c
>>> @@ -0,0 +1,27 @@
>>> +/*
>>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#include <linux/io.h>
>>> +
>>> +struct extio_ops *arm64_extio_ops;
>>> +
>>> +
>>> +BUILD_EXTIO(b, u8)
>>> +
>>> +BUILD_EXTIO(w, u16)
>>> +
>>> +BUILD_EXTIO(l, u32)
>>> --
>>> 1.9.1
>>>
>>
>>
>>
>



Thanks,
Ming Lei
-------------- next part --------------
A non-text attachment was scrubbed...
Name: config.tar.gz
Type: application/x-gzip
Size: 37193 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161223/4f3c2eff/attachment-0001.bin>

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2016-12-22  8:15     ` Ming Lei
  (?)
  (?)
@ 2017-01-06 11:43       ` Arnd Bergmann
  -1 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2017-01-06 11:43 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Ming Lei, zhichang.yuan, Mark Rutland, gabriele.paoloni,
	Benjamin Herrenschmidt, Will Deacon, linuxarm, Lorenzo Pieralisi,
	xuwei5, linux-serial, Catalin Marinas, devicetree, minyard,
	Liviu Dudau, john.garry, zourongrong, Rob Herring, Bjorn Helgaas,
	kantyzc, zhichang.yuan02, linux-pci, Linux Kernel Mailing List,
	Olof Johansson

On Thursday, December 22, 2016 4:15:57 PM CET Ming Lei wrote:
> ERROR: "inb" [drivers/watchdog/wdt_pci.ko] undefined!
> ERROR: "outb" [drivers/watchdog/wdt_pci.ko] undefined!
> ERROR: "outb" [drivers/watchdog/pcwd_pci.ko] undefined!
> ERROR: "inb" [drivers/watchdog/pcwd_pci.ko] undefined!
> ERROR: "outw" [drivers/video/vgastate.ko] undefined!
> ERROR: "outb" [drivers/video/vgastate.ko] undefined!
> ERROR: "inb" [drivers/video/vgastate.ko] undefined!
> ERROR: "outw" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "outb" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "outw" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "outb" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/tdfxfb.ko] undefined!
> 

In case you haven't figured it out by now, the new code is simply
missing a few "EXPORT_SYMBOL" lines.

	Arnd

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2017-01-06 11:43       ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2017-01-06 11:43 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Mark Rutland, Benjamin Herrenschmidt, gabriele.paoloni,
	Catalin Marinas, Will Deacon, linuxarm, Lorenzo Pieralisi,
	Ming Lei, xuwei5, linux-serial, linux-pci, devicetree, minyard,
	Liviu Dudau, john.garry, Olof Johansson, Rob Herring,
	Bjorn Helgaas, kantyzc, zhichang.yuan02,
	Linux Kernel Mailing List, zhichang.yuan, zourongrong

On Thursday, December 22, 2016 4:15:57 PM CET Ming Lei wrote:
> ERROR: "inb" [drivers/watchdog/wdt_pci.ko] undefined!
> ERROR: "outb" [drivers/watchdog/wdt_pci.ko] undefined!
> ERROR: "outb" [drivers/watchdog/pcwd_pci.ko] undefined!
> ERROR: "inb" [drivers/watchdog/pcwd_pci.ko] undefined!
> ERROR: "outw" [drivers/video/vgastate.ko] undefined!
> ERROR: "outb" [drivers/video/vgastate.ko] undefined!
> ERROR: "inb" [drivers/video/vgastate.ko] undefined!
> ERROR: "outw" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "outb" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "outw" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "outb" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/tdfxfb.ko] undefined!
> 

In case you haven't figured it out by now, the new code is simply
missing a few "EXPORT_SYMBOL" lines.

	Arnd

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

* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2017-01-06 11:43       ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2017-01-06 11:43 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Mark Rutland, Benjamin Herrenschmidt, gabriele.paoloni,
	Catalin Marinas, Will Deacon, linuxarm, Lorenzo Pieralisi,
	Ming Lei, xuwei5, linux-serial, linux-pci, devicetree, minyard,
	Liviu Dudau, john.garry, Olof Johansson, Rob Herring,
	Bjorn Helgaas, kantyzc, zhichang.yuan02,
	Linux Kernel Mailing List, zhichang.yuan, zourongrong

On Thursday, December 22, 2016 4:15:57 PM CET Ming Lei wrote:
> ERROR: "inb" [drivers/watchdog/wdt_pci.ko] undefined!
> ERROR: "outb" [drivers/watchdog/wdt_pci.ko] undefined!
> ERROR: "outb" [drivers/watchdog/pcwd_pci.ko] undefined!
> ERROR: "inb" [drivers/watchdog/pcwd_pci.ko] undefined!
> ERROR: "outw" [drivers/video/vgastate.ko] undefined!
> ERROR: "outb" [drivers/video/vgastate.ko] undefined!
> ERROR: "inb" [drivers/video/vgastate.ko] undefined!
> ERROR: "outw" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "outb" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "outw" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "outb" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/tdfxfb.ko] undefined!
> 

In case you haven't figured it out by now, the new code is simply
missing a few "EXPORT_SYMBOL" lines.

	Arnd


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
@ 2017-01-06 11:43       ` Arnd Bergmann
  0 siblings, 0 replies; 286+ messages in thread
From: Arnd Bergmann @ 2017-01-06 11:43 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday, December 22, 2016 4:15:57 PM CET Ming Lei wrote:
> ERROR: "inb" [drivers/watchdog/wdt_pci.ko] undefined!
> ERROR: "outb" [drivers/watchdog/wdt_pci.ko] undefined!
> ERROR: "outb" [drivers/watchdog/pcwd_pci.ko] undefined!
> ERROR: "inb" [drivers/watchdog/pcwd_pci.ko] undefined!
> ERROR: "outw" [drivers/video/vgastate.ko] undefined!
> ERROR: "outb" [drivers/video/vgastate.ko] undefined!
> ERROR: "inb" [drivers/video/vgastate.ko] undefined!
> ERROR: "outw" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "outb" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "outw" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "outb" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/tdfxfb.ko] undefined!
> 

In case you haven't figured it out by now, the new code is simply
missing a few "EXPORT_SYMBOL" lines.

	Arnd

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

* 答复: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
  2017-01-06 11:43       ` Arnd Bergmann
                         ` (2 preceding siblings ...)
  (?)
@ 2017-01-07  1:25       ` Yuanzhichang
  -1 siblings, 0 replies; 286+ messages in thread
From: Yuanzhichang @ 2017-01-07  1:25 UTC (permalink / raw)
  To: arnd, linux-arm-kernel
  Cc: tom.leiming, mark.rutland, Gabriele Paoloni, benh, will.deacon,
	Linuxarm, lorenzo.pieralisi, xuwei (O),
	linux-serial, catalin.marinas, devicetree, minyard, liviu.dudau,
	John Garry, zourongrong, robh+dt, bhelgaas, kantyzc,
	zhichang.yuan02, linux-pci, linux-kernel, olof

[-- Attachment #1: Type: text/plain, Size: 1819 bytes --]

Hi, Arnd,
Thanks for your points!
l had sent a private fix patch to Ming before, he tested and said it was OK.
All these will be covered in the coming V6.

Ming, thanks for your work too!

Best,
Zhichang

Sent from HUAWEI AnyOffice
发件人:Arnd Bergmann
收件人:linux-arm-kernel@lists.infradead.org
抄送:Ming Lei,袁志昌,Mark Rutland,Gabriele Paoloni,Benjamin Herrenschmidt,Will Deacon,Linuxarm,Lorenzo Pieralisi,徐威,linux-serial@vger.kernel.org,Catalin Marinas,devicetree@vger.kernel.org,minyard@acm.org,Liviu Dudau,John Garry,zourongrong@gmail.com,Rob Herring,Bjorn Helgaas,kantyzc@163.com,zhichang.yuan02@gmail.com,linux-pci@vger.kernel.org,Linux Kernel Mailing List,Olof Johansson
时间:2017-01-06 19:43:58
主题:Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced

On Thursday, December 22, 2016 4:15:57 PM CET Ming Lei wrote:
> ERROR: "inb" [drivers/watchdog/wdt_pci.ko] undefined!
> ERROR: "outb" [drivers/watchdog/wdt_pci.ko] undefined!
> ERROR: "outb" [drivers/watchdog/pcwd_pci.ko] undefined!
> ERROR: "inb" [drivers/watchdog/pcwd_pci.ko] undefined!
> ERROR: "outw" [drivers/video/vgastate.ko] undefined!
> ERROR: "outb" [drivers/video/vgastate.ko] undefined!
> ERROR: "inb" [drivers/video/vgastate.ko] undefined!
> ERROR: "outw" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "outb" [drivers/video/fbdev/vt8623fb.ko] undefined!
> ERROR: "outw" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "outb" [drivers/video/fbdev/tridentfb.ko] undefined!
> ERROR: "inb" [drivers/video/fbdev/tdfxfb.ko] undefined!
>

In case you haven't figured it out by now, the new code is simply
missing a few "EXPORT_SYMBOL" lines.

        Arnd


[-- Attachment #2: Type: text/html, Size: 3013 bytes --]

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

end of thread, other threads:[~2017-01-07  1:25 UTC | newest]

Thread overview: 286+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-08  3:47 [PATCH V5 0/3] ARM64 LPC: legacy ISA I/O support zhichang.yuan
2016-11-08  3:47 ` zhichang.yuan
2016-11-08  3:47 ` zhichang.yuan
2016-11-08  3:47 ` [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced zhichang.yuan
2016-11-08  3:47   ` zhichang.yuan
2016-11-08  3:47   ` zhichang.yuan
2016-11-08 12:03   ` Mark Rutland
2016-11-08 12:03     ` Mark Rutland
2016-11-08 12:03     ` Mark Rutland
2016-11-08 16:09     ` Arnd Bergmann
2016-11-08 16:09       ` Arnd Bergmann
2016-11-08 16:09       ` Arnd Bergmann
2016-11-08 16:09       ` Arnd Bergmann
2016-11-08 16:15       ` Arnd Bergmann
2016-11-08 16:15         ` Arnd Bergmann
2016-11-08 23:16     ` Benjamin Herrenschmidt
2016-11-08 23:16       ` Benjamin Herrenschmidt
2016-11-08 23:16       ` Benjamin Herrenschmidt
2016-11-10  8:33       ` zhichang.yuan
2016-11-10  8:33         ` zhichang.yuan
2016-11-10  8:33         ` zhichang.yuan
2016-11-10 11:22       ` Mark Rutland
2016-11-10 11:22         ` Mark Rutland
2016-11-10 19:32         ` Benjamin Herrenschmidt
2016-11-10 19:32           ` Benjamin Herrenschmidt
2016-11-10 19:32           ` Benjamin Herrenschmidt
2016-11-10 19:32           ` Benjamin Herrenschmidt
2016-11-11 10:07           ` zhichang.yuan
2016-11-11 10:07             ` zhichang.yuan
2016-11-11 10:07             ` zhichang.yuan
2016-11-18  9:20             ` Arnd Bergmann
2016-11-18  9:20               ` Arnd Bergmann
2016-11-18  9:20               ` Arnd Bergmann
2016-11-18 11:12               ` zhichang.yuan
2016-11-18 11:12                 ` zhichang.yuan
2016-11-18 11:12                 ` zhichang.yuan
2016-11-18 11:38                 ` Arnd Bergmann
2016-11-18 11:38                   ` Arnd Bergmann
2016-11-21 12:58       ` John Garry
2016-11-21 12:58         ` John Garry
2016-11-21 12:58         ` John Garry
2016-11-08 16:12   ` Will Deacon
2016-11-08 16:12     ` Will Deacon
2016-11-08 16:12     ` Will Deacon
2016-11-08 16:33     ` John Garry
2016-11-08 16:33       ` John Garry
2016-11-08 16:33       ` John Garry
2016-11-08 16:33       ` John Garry
2016-11-08 16:49       ` Will Deacon
2016-11-08 16:49         ` Will Deacon
2016-11-08 17:05         ` John Garry
2016-11-08 17:05           ` John Garry
2016-11-08 17:05           ` John Garry
2016-11-08 22:35         ` Arnd Bergmann
2016-11-08 22:35           ` Arnd Bergmann
2016-11-08 22:35           ` Arnd Bergmann
2016-11-09 11:29           ` John Garry
2016-11-09 11:29             ` John Garry
2016-11-09 11:29             ` John Garry
2016-11-09 21:33             ` Arnd Bergmann
2016-11-09 21:33               ` Arnd Bergmann
2016-11-09 21:33               ` Arnd Bergmann
2016-12-22  8:15   ` Ming Lei
2016-12-22  8:15     ` Ming Lei
2016-12-22  8:15     ` Ming Lei
2016-12-22  8:15     ` Ming Lei
2016-12-23  1:43     ` zhichang.yuan
2016-12-23  1:43       ` zhichang.yuan
2016-12-23  1:43       ` zhichang.yuan
2016-12-23  1:43       ` zhichang.yuan
2016-12-23  7:24       ` Ming Lei
2016-12-23  7:24         ` Ming Lei
2016-12-23  7:24         ` Ming Lei
2016-12-23  7:24         ` Ming Lei
2017-01-06 11:43     ` Arnd Bergmann
2017-01-06 11:43       ` Arnd Bergmann
2017-01-06 11:43       ` Arnd Bergmann
2017-01-06 11:43       ` Arnd Bergmann
2017-01-07  1:25       ` 答复: " Yuanzhichang
2016-11-08  3:47 ` [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA zhichang.yuan
2016-11-08  3:47   ` zhichang.yuan
2016-11-08  3:47   ` zhichang.yuan
2016-11-08  5:17   ` kbuild test robot
2016-11-08  5:17     ` kbuild test robot
2016-11-08  5:17     ` kbuild test robot
2016-11-08  5:17     ` kbuild test robot
2016-11-08  5:27   ` kbuild test robot
2016-11-08  5:27     ` kbuild test robot
2016-11-08  5:27     ` kbuild test robot
2016-11-08 11:49   ` Mark Rutland
2016-11-08 11:49     ` Mark Rutland
2016-11-08 16:19     ` Arnd Bergmann
2016-11-08 16:19       ` Arnd Bergmann
2016-11-08 16:19       ` Arnd Bergmann
2016-11-08 17:10       ` Mark Rutland
2016-11-08 17:10         ` Mark Rutland
2016-11-08 17:10         ` Mark Rutland
2016-11-09 13:54       ` One Thousand Gnomes
2016-11-09 13:54         ` One Thousand Gnomes
2016-11-09 14:51         ` Gabriele Paoloni
2016-11-09 14:51           ` Gabriele Paoloni
2016-11-09 14:51           ` Gabriele Paoloni
2016-11-09 14:51           ` Gabriele Paoloni
2016-11-09 21:38         ` Arnd Bergmann
2016-11-09 21:38           ` Arnd Bergmann
2016-11-09 21:38           ` Arnd Bergmann
2016-11-14 11:11           ` One Thousand Gnomes
2016-11-14 11:11             ` One Thousand Gnomes
2016-11-14 11:11             ` One Thousand Gnomes
2016-11-18  9:22             ` Arnd Bergmann
2016-11-18  9:22               ` Arnd Bergmann
2016-11-18  9:22               ` Arnd Bergmann
2016-11-18  9:22               ` Arnd Bergmann
2016-11-08 23:12     ` Benjamin Herrenschmidt
2016-11-08 23:12       ` Benjamin Herrenschmidt
2016-11-08 23:12       ` Benjamin Herrenschmidt
2016-11-08 23:12       ` Benjamin Herrenschmidt
2016-11-09 11:20       ` Mark Rutland
2016-11-09 11:20         ` Mark Rutland
2016-11-10  7:08         ` Benjamin Herrenschmidt
2016-11-10  7:08           ` Benjamin Herrenschmidt
2016-11-10  7:08           ` Benjamin Herrenschmidt
2016-11-09 11:39   ` liviu.dudau
2016-11-09 11:39     ` liviu.dudau at arm.com
2016-11-09 11:39     ` liviu.dudau-5wv7dgnIgG8
2016-11-09 16:16     ` Gabriele Paoloni
2016-11-09 16:16       ` Gabriele Paoloni
2016-11-09 16:16       ` Gabriele Paoloni
2016-11-09 16:16       ` Gabriele Paoloni
2016-11-09 16:50       ` liviu.dudau
2016-11-09 16:50         ` liviu.dudau at arm.com
2016-11-09 16:50         ` liviu.dudau
2016-11-09 16:50         ` liviu.dudau-5wv7dgnIgG8
2016-11-10  6:24         ` zhichang.yuan
2016-11-10  6:24           ` zhichang.yuan
2016-11-10  6:24           ` zhichang.yuan
2016-11-10  6:24           ` zhichang.yuan
2016-11-10 16:06         ` Gabriele Paoloni
2016-11-10 16:06           ` Gabriele Paoloni
2016-11-10 16:06           ` Gabriele Paoloni
2016-11-10 16:06           ` Gabriele Paoloni
2016-11-11 10:37           ` liviu.dudau
2016-11-11 10:37             ` liviu.dudau at arm.com
2016-11-11 10:37             ` liviu.dudau
2016-11-11 10:37             ` liviu.dudau
2016-11-08  3:47 ` [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06 zhichang.yuan
2016-11-08  3:47   ` zhichang.yuan
2016-11-08  3:47   ` zhichang.yuan
2016-11-08  6:11   ` kbuild test robot
2016-11-08  6:11     ` kbuild test robot
2016-11-08  6:11     ` kbuild test robot
2016-11-08 16:24   ` Arnd Bergmann
2016-11-08 16:24     ` Arnd Bergmann
2016-11-09 12:10     ` Gabriele Paoloni
2016-11-09 12:10       ` Gabriele Paoloni
2016-11-09 12:10       ` Gabriele Paoloni
2016-11-09 12:10       ` Gabriele Paoloni
2016-11-09 21:34       ` Arnd Bergmann
2016-11-09 21:34         ` Arnd Bergmann
2016-11-09 21:34         ` Arnd Bergmann
2016-11-09 21:34         ` Arnd Bergmann
2016-11-10  6:40         ` zhichang.yuan
2016-11-10  6:40           ` zhichang.yuan
2016-11-10  6:40           ` zhichang.yuan
2016-11-10  9:12           ` Arnd Bergmann
2016-11-10  9:12             ` Arnd Bergmann
2016-11-10  9:12             ` Arnd Bergmann
2016-11-10 12:36             ` zhichang.yuan
2016-11-10 12:36               ` zhichang.yuan
2016-11-10 12:36               ` zhichang.yuan
2016-11-18 11:46               ` Arnd Bergmann
2016-11-18 11:46                 ` Arnd Bergmann
2016-11-18 11:46                 ` Arnd Bergmann
2016-11-18 11:46                 ` Arnd Bergmann
2016-11-10 15:36             ` Gabriele Paoloni
2016-11-10 15:36               ` Gabriele Paoloni
2016-11-10 15:36               ` Gabriele Paoloni
2016-11-10 15:36               ` Gabriele Paoloni
2016-11-10 16:07               ` Arnd Bergmann
2016-11-10 16:07                 ` Arnd Bergmann
2016-11-10 16:07                 ` Arnd Bergmann
2016-11-10 16:07                 ` Arnd Bergmann
2016-11-11 10:09                 ` zhichang.yuan
2016-11-11 10:09                   ` zhichang.yuan
2016-11-11 10:09                   ` zhichang.yuan
2016-11-11 10:09                   ` zhichang.yuan
2016-11-11 10:48                 ` liviu.dudau
2016-11-11 10:48                   ` liviu.dudau at arm.com
2016-11-11 10:48                   ` liviu.dudau
2016-11-11 10:48                   ` liviu.dudau
2016-11-11 13:39                 ` Gabriele Paoloni
2016-11-11 13:39                   ` Gabriele Paoloni
2016-11-11 13:39                   ` Gabriele Paoloni
2016-11-11 13:39                   ` Gabriele Paoloni
2016-11-11 14:45                   ` liviu.dudau
2016-11-11 14:45                     ` liviu.dudau at arm.com
2016-11-11 14:45                     ` liviu.dudau
2016-11-11 14:45                     ` liviu.dudau-5wv7dgnIgG8
2016-11-11 15:53                     ` Gabriele Paoloni
2016-11-11 15:53                       ` Gabriele Paoloni
2016-11-11 15:53                       ` Gabriele Paoloni
2016-11-11 15:53                       ` Gabriele Paoloni
2016-11-11 18:16                       ` liviu.dudau
2016-11-11 18:16                         ` liviu.dudau at arm.com
2016-11-11 18:16                         ` liviu.dudau
2016-11-11 18:16                         ` liviu.dudau
2016-11-14  8:26                         ` Gabriele Paoloni
2016-11-14  8:26                           ` Gabriele Paoloni
2016-11-14  8:26                           ` Gabriele Paoloni
2016-11-14  8:26                           ` Gabriele Paoloni
2016-11-14 11:26                           ` liviu.dudau
2016-11-14 11:26                             ` liviu.dudau at arm.com
2016-11-14 11:26                             ` liviu.dudau
2016-11-14 11:26                             ` liviu.dudau
2016-11-18 10:17                             ` Arnd Bergmann
2016-11-18 10:17                               ` Arnd Bergmann
2016-11-18 10:17                               ` Arnd Bergmann
2016-11-18 10:17                               ` Arnd Bergmann
2016-11-18 12:07                               ` Gabriele Paoloni
2016-11-18 12:07                                 ` Gabriele Paoloni
2016-11-18 12:07                                 ` Gabriele Paoloni
2016-11-18 12:07                                 ` Gabriele Paoloni
2016-11-18 12:24                                 ` Arnd Bergmann
2016-11-18 12:24                                   ` Arnd Bergmann
2016-11-18 12:24                                   ` Arnd Bergmann
2016-11-18 12:24                                   ` Arnd Bergmann
2016-11-18 12:53                                   ` Gabriele Paoloni
2016-11-18 12:53                                     ` Gabriele Paoloni
2016-11-18 12:53                                     ` Gabriele Paoloni
2016-11-18 12:53                                     ` Gabriele Paoloni
2016-11-18 13:42                                     ` Arnd Bergmann
2016-11-18 13:42                                       ` Arnd Bergmann
2016-11-18 13:42                                       ` Arnd Bergmann
2016-11-18 16:18                                       ` Gabriele Paoloni
2016-11-18 16:18                                         ` Gabriele Paoloni
2016-11-18 16:18                                         ` Gabriele Paoloni
2016-11-18 16:18                                         ` Gabriele Paoloni
2016-11-18 16:34                                         ` Arnd Bergmann
2016-11-18 16:34                                           ` Arnd Bergmann
2016-11-18 16:34                                           ` Arnd Bergmann
2016-11-18 16:34                                           ` Arnd Bergmann
2016-11-18 17:03                                           ` Gabriele Paoloni
2016-11-18 17:03                                             ` Gabriele Paoloni
2016-11-18 17:03                                             ` Gabriele Paoloni
2016-11-18 17:03                                             ` Gabriele Paoloni
2016-11-23 14:16                                             ` Arnd Bergmann
2016-11-23 14:16                                               ` Arnd Bergmann
2016-11-23 14:16                                               ` Arnd Bergmann
2016-11-23 14:16                                               ` Arnd Bergmann
2016-11-23 15:22                                               ` Gabriele Paoloni
2016-11-23 15:22                                                 ` Gabriele Paoloni
2016-11-23 15:22                                                 ` Gabriele Paoloni
2016-11-23 15:22                                                 ` Gabriele Paoloni
2016-11-23 17:07                                                 ` Arnd Bergmann
2016-11-23 17:07                                                   ` Arnd Bergmann
2016-11-23 17:07                                                   ` Arnd Bergmann
2016-11-23 17:07                                                   ` Arnd Bergmann
2016-11-23 23:23                                                   ` Arnd Bergmann
2016-11-23 23:23                                                     ` Arnd Bergmann
2016-11-23 23:23                                                     ` Arnd Bergmann
2016-11-24  9:12                                                     ` zhichang.yuan
2016-11-24  9:12                                                       ` zhichang.yuan
2016-11-24  9:12                                                       ` zhichang.yuan
2016-11-24 10:24                                                       ` Arnd Bergmann
2016-11-24 10:24                                                         ` Arnd Bergmann
2016-11-24 10:24                                                         ` Arnd Bergmann
2016-11-24 10:24                                                         ` Arnd Bergmann
2016-11-25  8:46                                                     ` Gabriele Paoloni
2016-11-25  8:46                                                       ` Gabriele Paoloni
2016-11-25  8:46                                                       ` Gabriele Paoloni
2016-11-25  8:46                                                       ` Gabriele Paoloni
2016-11-25 12:03                                                       ` Arnd Bergmann
2016-11-25 12:03                                                         ` Arnd Bergmann
2016-11-25 12:03                                                         ` Arnd Bergmann
2016-11-25 12:03                                                         ` Arnd Bergmann
2016-11-25 16:27                                                         ` Gabriele Paoloni
2016-11-25 16:27                                                           ` Gabriele Paoloni
2016-11-25 16:27                                                           ` Gabriele Paoloni
2016-11-25 16:27                                                           ` Gabriele Paoloni
2016-11-11 16:54                     ` zhichang.yuan
2016-11-11 16:54                       ` zhichang.yuan
2016-11-11 16:54                       ` zhichang.yuan
2016-11-11 16:54                       ` zhichang.yuan
2016-11-14 11:06         ` One Thousand Gnomes
2016-11-14 11:06           ` One Thousand Gnomes
2016-11-14 11:06           ` One Thousand Gnomes

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.