* [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 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 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: 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 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
* 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
* [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 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
* 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
* [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 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
* 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 @ 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 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
* [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 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
* 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
* [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 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
* 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 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
* [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 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
* 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 (?) @ 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
* [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 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
* 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
* [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 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
* 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
* [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 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
* 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 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
* [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 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
* 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
* [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: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
* 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
* [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 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
* 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 @ 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
* [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 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
* 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
* [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 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
* 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
* [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 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
* 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
* [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 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
* 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
* [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 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
* 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 (?) (?) @ 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
* [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 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
* 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 (?) (?) @ 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
* [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-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
* 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-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
* [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
* 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
* 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
* 答复: [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
* [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: 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 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
* 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
* [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: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
* 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: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
* [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 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
* 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 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
* [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 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
* 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
* [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 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
* 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
* [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 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 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
* [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 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
* 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
* [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 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
* 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
* [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 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
* 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-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
* [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 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
* 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 @ 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 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
* [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 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
* 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
* [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 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
* 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
* [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 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
* 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 (?) (?) @ 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
* [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 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
* 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 (?) (?) @ 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
* [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 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
* 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 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
* [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 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
* 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 (?) (?) @ 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
* [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 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
* 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
* [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: 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
* [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
* 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
* [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 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
* 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 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
* [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 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
* 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 (?) (?) @ 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
* [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 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
* 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 (?) @ 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
* [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 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
* 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
* [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 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
* 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
* [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 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
* 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
* [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 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
* 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-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
* [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 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
* 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 (?) (?) @ 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
* [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 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
* 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 (?) (?) @ 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
* [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 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
* 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-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
* [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-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
* 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-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
* [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 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
* 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 (?) (?) @ 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
* [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 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
* 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 (?) (?) @ 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
* [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 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
* 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 (?) (?) @ 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
* [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 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
* 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 (?) (?) @ 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
* [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-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
* 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 (?) (?) @ 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
* [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 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
* 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-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 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 (?) (?) @ 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
* [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 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
* 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 (?) (?) @ 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
* [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 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
* 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 (?) (?) @ 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
* [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 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
* 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 (?) @ 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
* [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 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
* 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
* [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 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
* 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 (?) (?) @ 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
* [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 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
* 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 (?) (?) @ 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
* [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 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
* 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 (?) (?) @ 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
* [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 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
* 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 (?) (?) @ 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
* [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 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
* 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 (?) (?) @ 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
* [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 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
* 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 (?) @ 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
* [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 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
* 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
* [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 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
* 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
* [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-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
* 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-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
* [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 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
* 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 (?) (?) @ 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
* [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 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
* 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 (?) (?) @ 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
* [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 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
* 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-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
* [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 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
* 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-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
* [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 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
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.