Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1598822 > unrolled thread
| Started by | "zhichang.yuan" <yuanzhichang@hisilicon.com> |
|---|---|
| First post | 2017-03-13 03:20 +0100 |
| Last post | 2017-03-15 14:30 +0100 |
| Articles | 13 — 5 participants |
Back to article view | Back to linux.kernel
[PATCH V7 0/7] LPC: legacy ISA I/O support "zhichang.yuan" <yuanzhichang@hisilicon.com> - 2017-03-13 03:20 +0100
[PATCH V7 1/7] LIBIO: Introduce a generic PIO mapping method "zhichang.yuan" <yuanzhichang@hisilicon.com> - 2017-03-13 03:30 +0100
[PATCH V7 5/7] ACPI: Delay the enumeration on the devices whose dependency has not met "zhichang.yuan" <yuanzhichang@hisilicon.com> - 2017-03-13 03:30 +0100
Re: [PATCH V7 5/7] ACPI: Delay the enumeration on the devices whose dependency has not met "Rafael J. Wysocki" <rjw@rjwysocki.net> - 2017-03-13 22:40 +0100
RE: [PATCH V7 5/7] ACPI: Delay the enumeration on the devices whose dependency has not met Gabriele Paoloni <gabriele.paoloni@huawei.com> - 2017-03-14 09:20 +0100
Re: [PATCH V7 5/7] ACPI: Delay the enumeration on the devices whose dependency has not met "zhichang.yuan" <yuanzhichang@hisilicon.com> - 2017-03-16 03:30 +0100
Re: [PATCH V7 5/7] ACPI: Delay the enumeration on the devices whose dependency has not met Arnd Bergmann <arnd@arndb.de> - 2017-03-16 11:20 +0100
Re: [PATCH V7 5/7] ACPI: Delay the enumeration on the devices whose dependency has not met "zhichang.yuan" <zhichang.yuan02@gmail.com> - 2017-03-16 16:00 +0100
RE: [PATCH V7 5/7] ACPI: Delay the enumeration on the devices whose dependency has not met Gabriele Paoloni <gabriele.paoloni@huawei.com> - 2017-03-16 17:20 +0100
RE: [PATCH V7 5/7] ACPI: Delay the enumeration on the devices whose dependency has not met Gabriele Paoloni <gabriele.paoloni@huawei.com> - 2017-03-24 01:50 +0100
Re: [PATCH V7 0/7] LPC: legacy ISA I/O support Arnd Bergmann <arnd@arndb.de> - 2017-03-14 09:40 +0100
Re: [PATCH V7 0/7] LPC: legacy ISA I/O support "zhichang.yuan" <yuanzhichang@hisilicon.com> - 2017-03-15 05:10 +0100
Re: [PATCH V7 0/7] LPC: legacy ISA I/O support Arnd Bergmann <arnd@arndb.de> - 2017-03-15 14:30 +0100
| From | "zhichang.yuan" <yuanzhichang@hisilicon.com> |
|---|---|
| Date | 2017-03-13 03:20 +0100 |
| Subject | [PATCH V7 0/7] LPC: legacy ISA I/O support |
| Message-ID | <tknKx-1UO-3@gated-at.bofh.it> |
This patchset supports the IPMI-bt device attached to the Low-Pin-Count
interface implemented on Hisilicon Hip06/Hip07 SoC.
-----------
| LPC host|
| |
-----------
|
_____________V_______________LPC
| |
V V
------------
| BT(ipmi)|
------------
When master accesses those peripherals beneath the Hip06/Hip07 LPC, a specific
LPC driver is needed to make LPC host generate the standard LPC I/O cycles with
the target peripherals'I/O port addresses. But on curent arm64 world, there is
no real I/O accesses. All the I/O operations through in/out pair are based on
MMIO which is not satisfied the I/O mechanism on Hip06/Hip07 LPC.
To solve this issue and keep the relevant existing peripherals' driver
untouched, this patchset implements:
- introduces a generic I/O space management framwork, LIBIO, to support I/O
operations of both MMIO buses and the host controllers which access their
peripherals with host local I/O addresses;
- redefines the in/out accessors to provide unified interfaces for MMIO and
legacy I/O. Based on the LIBIO, the calling of in/out() from upper-layer
drivers, such as ipmi-si, will be redirected to the corresponding
device-specific I/O hooks to perfrom the I/O accesses.
Based on this patch-set, all the I/O accesses to Hip06/Hip07 LPC peripherals
can be supported without any changes on the existing ipmi-si driver.
Changes from V6:
- According to the comments from Bjorn and Alex, merge PCI IO and indirect-IO
into a generic I/O space management, LIBIO;
- Adopted the '_DEP' to replace the platform bus notifier. In this way, we
can ensure the LPC peripherals' I/O resources had been translated to
logical IO before the LPC peripheral enumeration;
- Replaced the rwlock with rcu list based on Alex's suggestion;
- Applied relaxed write/read to LPC driver;
- Some bugs fixing and some optimazations based on the comments of V6;
Changes from V5:
- Made the extio driver more generic and locate in lib/;
- Supported multiple indirect-IO bus instances;
- Extended the pci_register_io_range() to support indirect-IO, then dropped
the I/O reservation used in previous patchset;
- Reimplemented the ACPI LPC support;
- Fixed some bugs, including the compile error on other archs, the module
building failure found by Ming Lei, etc;
Changes from V4:
- Some revises based on the comments from Bjorn, Rob on V4;
- Fixed the compile error on some platforms, such as openrisc;
Changes from V3:
- UART support deferred to a separate patchset; This patchset only support
ipmi device under LPC;
- LPC bus I/O range is fixed to 0 ~ (PCIBIOS_MIN_IO - 1), which is separeted
from PCI/PCIE PIO space;
- Based on Arnd's remarks, removed the ranges property from Hip06 lpc dts and
added a new fixup function, of_isa_indirect_io(), to get the I/O address
directly from LPC dts configurations;
- Support in(w,l)/out(w,l) for Hip06 lpc I/O;
- Decouple the header file dependency on the gerenic io.h by defining in/out
as normal functions in c file;
- removed unused macro definitions in the LPC driver;
Changes from V2:
- Support the PIO retrieval from the linux PIO generated by
pci_address_to_pio. This method replace the 4K PIO reservation in V2;
- Support the flat-tree earlycon;
- Some revises based on Arnd's remarks;
- Make sure the linux PIO range allocated to Hip06 LPC peripherals starts
from non-ZERO;
Changes from V1:
- Support the ACPI LPC device;
- Optimize the dts LPC driver in ISA compatible mode;
- Reserve the IO range below 4K in avoid the possible conflict with PCI host
IO ranges;
- Support the LPC uart and relevant earlycon;
v6 thread here: https://lkml.org/lkml/2017/1/24/25
v5 thread here: https://lkml.org/lkml/2016/11/7/955
v4 thread here: https://lkml.org/lkml/2016/10/20/149
v3 thread here: https://lkml.org/lkml/2016/9/14/326
v2 thread here: https://lkml.org/lkml/2016/9/7/356
v1 thread here: https://lkml.org/lkml/2015/12/29/154
Signed-off-by: Zhichang Yuan <yuanzhichang@hisilicon.com>
zhichang.yuan (7):
LIBIO: Introduce a generic PIO mapping method
PCI: Apply the new generic I/O management on PCI IO hosts
OF: Add missing I/O range exception for indirect-IO devices
LPC: Support the device-tree LPC host on Hip06/Hip07
ACPI: Delay the enumeration on the devices whose dependency has not
met
LIBIO: Support the dynamically logical PIO registration of ACPI host
I/O
LPC: Add the ACPI LPC support
.../arm/hisilicon/hisilicon-low-pin-count.txt | 33 ++
MAINTAINERS | 8 +
arch/arm64/boot/dts/hisilicon/hip06-d03.dts | 4 +
arch/arm64/boot/dts/hisilicon/hip06.dtsi | 14 +
arch/arm64/boot/dts/hisilicon/hip07-d05.dts | 4 +
arch/arm64/boot/dts/hisilicon/hip07.dtsi | 14 +
drivers/acpi/battery.c | 3 -
drivers/acpi/pci_root.c | 8 +-
drivers/acpi/scan.c | 3 +
drivers/bus/Kconfig | 8 +
drivers/bus/Makefile | 1 +
drivers/bus/hisi_lpc.c | 608 +++++++++++++++++++++
drivers/of/address.c | 94 +++-
drivers/pci/pci.c | 96 +---
include/asm-generic/io.h | 50 ++
include/linux/io.h | 1 +
include/linux/libio.h | 98 ++++
include/linux/pci.h | 3 +-
lib/Kconfig | 14 +
lib/Makefile | 2 +
lib/libio.c | 548 +++++++++++++++++++
21 files changed, 1514 insertions(+), 100 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
create mode 100644 drivers/bus/hisi_lpc.c
create mode 100644 include/linux/libio.h
create mode 100644 lib/libio.c
--
1.9.1
[toc] | [next] | [standalone]
| From | "zhichang.yuan" <yuanzhichang@hisilicon.com> |
|---|---|
| Date | 2017-03-13 03:30 +0100 |
| Subject | [PATCH V7 1/7] LIBIO: Introduce a generic PIO mapping method |
| Message-ID | <tknUd-1XV-3@gated-at.bofh.it> |
| In reply to | #1598822 |
In commit 41f8bba7f55(of/pci: Add pci_register_io_range() and
pci_pio_to_address()), a new I/O space management was supported. With that
driver, the I/O ranges configured for PCI/PCIE hosts on some architectures can
be mapped to logical PIO, converted easily between CPU address and the
corresponding logicial PIO. Based on this, PCI I/O devices can be accessed in a
memory read/write way through the unified in/out accessors.
But on some archs/platforms, there are bus hosts which access I/O peripherals
with host-local I/O port addresses rather than memory addresses after
memory-mapped.
To support those devices, a more generic I/O mapping method is introduced here.
Through this patch, both the CPU addresses and the host-local port can be
mapped into logical PIO, then all the I/O accesses to either PCI MMIO devices or
host-local I/O peripherals can be unified into the existing I/O accessors
defined asm-generic/io.h and be redirected to the right device-specific hooks
based on the input logical PIO.
Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
include/asm-generic/io.h | 50 ++++++++
include/linux/io.h | 1 +
include/linux/libio.h | 94 ++++++++++++++
lib/Kconfig | 14 ++
lib/Makefile | 2 +
lib/libio.c | 324 +++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 485 insertions(+)
create mode 100644 include/linux/libio.h
create mode 100644 lib/libio.c
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index 7ef015e..91a7ed4 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -21,6 +21,8 @@
#include <asm-generic/pci_iomap.h>
+#include <linux/libio.h>
+
#ifndef mmiowb
#define mmiowb() do {} while (0)
#endif
@@ -358,51 +360,75 @@ static inline void writesq(volatile void __iomem *addr, const void *buffer,
*/
#ifndef inb
+#ifdef CONFIG_LIBIO
+#define inb libio_inb
+#else
#define inb inb
static inline u8 inb(unsigned long addr)
{
return readb(PCI_IOBASE + addr);
}
+#endif /* CONFIG_LIBIO */
#endif
#ifndef inw
+#ifdef CONFIG_LIBIO
+#define inw libio_inw
+#else
#define inw inw
static inline u16 inw(unsigned long addr)
{
return readw(PCI_IOBASE + addr);
}
+#endif /* CONFIG_LIBIO */
#endif
#ifndef inl
+#ifdef CONFIG_LIBIO
+#define inl libio_inl
+#else
#define inl inl
static inline u32 inl(unsigned long addr)
{
return readl(PCI_IOBASE + addr);
}
+#endif /* CONFIG_LIBIO */
#endif
#ifndef outb
+#ifdef CONFIG_LIBIO
+#define outb libio_outb
+#else
#define outb outb
static inline void outb(u8 value, unsigned long addr)
{
writeb(value, PCI_IOBASE + addr);
}
+#endif /* CONFIG_LIBIO */
#endif
#ifndef outw
+#ifdef CONFIG_LIBIO
+#define outw libio_outw
+#else
#define outw outw
static inline void outw(u16 value, unsigned long addr)
{
writew(value, PCI_IOBASE + addr);
}
+#endif /* CONFIG_LIBIO */
#endif
#ifndef outl
+#ifdef CONFIG_LIBIO
+#define outl libio_outl
+#else
#define outl outl
static inline void outl(u32 value, unsigned long addr)
{
writel(value, PCI_IOBASE + addr);
}
+#endif /* CONFIG_LIBIO */
#endif
#ifndef inb_p
@@ -459,54 +485,78 @@ static inline void outl_p(u32 value, unsigned long addr)
*/
#ifndef insb
+#ifdef CONFIG_LIBIO
+#define insb libio_insb
+#else
#define insb insb
static inline void insb(unsigned long addr, void *buffer, unsigned int count)
{
readsb(PCI_IOBASE + addr, buffer, count);
}
+#endif /* CONFIG_LIBIO */
#endif
#ifndef insw
+#ifdef CONFIG_LIBIO
+#define insw libio_insw
+#else
#define insw insw
static inline void insw(unsigned long addr, void *buffer, unsigned int count)
{
readsw(PCI_IOBASE + addr, buffer, count);
}
+#endif /* CONFIG_LIBIO */
#endif
#ifndef insl
+#ifdef CONFIG_LIBIO
+#define insl libio_insl
+#else
#define insl insl
static inline void insl(unsigned long addr, void *buffer, unsigned int count)
{
readsl(PCI_IOBASE + addr, buffer, count);
}
+#endif /* CONFIG_LIBIO */
#endif
#ifndef outsb
+#ifdef CONFIG_LIBIO
+#define outsb libio_outsb
+#else
#define outsb outsb
static inline void outsb(unsigned long addr, const void *buffer,
unsigned int count)
{
writesb(PCI_IOBASE + addr, buffer, count);
}
+#endif /* CONFIG_LIBIO */
#endif
#ifndef outsw
+#ifdef CONFIG_LIBIO
+#define outsw libio_outsw
+#else
#define outsw outsw
static inline void outsw(unsigned long addr, const void *buffer,
unsigned int count)
{
writesw(PCI_IOBASE + addr, buffer, count);
}
+#endif /* CONFIG_LIBIO */
#endif
#ifndef outsl
+#ifdef CONFIG_LIBIO
+#define outsl libio_outsl
+#else
#define outsl outsl
static inline void outsl(unsigned long addr, const void *buffer,
unsigned int count)
{
writesl(PCI_IOBASE + addr, buffer, count);
}
+#endif /* CONFIG_LIBIO */
#endif
#ifndef insb_p
diff --git a/include/linux/io.h b/include/linux/io.h
index 82ef36e..51ec1aa 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -24,6 +24,7 @@
#include <linux/err.h>
#include <asm/io.h>
#include <asm/page.h>
+#include <linux/libio.h>
struct device;
struct resource;
diff --git a/include/linux/libio.h b/include/linux/libio.h
new file mode 100644
index 0000000..91038aa
--- /dev/null
+++ b/include/linux/libio.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2017 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_LIBIO_H
+#define __LINUX_LIBIO_H
+
+#ifdef __KERNEL__
+
+#include <linux/fwnode.h>
+
+/* This is compatible to PCI MMIO. */
+#define IO_CPU_MMIO 0x01
+/* All hosts where there are no CPU addr */
+#define IO_HOST_INDIRECT 0x02
+
+struct libio_range {
+ struct list_head list;
+ struct fwnode_handle *node;
+ resource_size_t size; /* range size populated */
+ resource_size_t io_start; /* logical pio start. inclusive */
+ resource_size_t hw_start;
+ unsigned long flags;
+ void *devpara; /* private parameter of the host device */
+ struct libio_ops *ops; /* ops operating on this node */
+};
+
+struct libio_ops {
+ u32 (*pfin)(void *devobj, unsigned long ptaddr, size_t dlen);
+ void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
+ size_t dlen);
+ u32 (*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);
+};
+
+extern u8 libio_inb(unsigned long addr);
+extern void libio_outb(u8 value, unsigned long addr);
+extern void libio_outw(u16 value, unsigned long addr);
+extern void libio_outl(u32 value, unsigned long addr);
+extern u16 libio_inw(unsigned long addr);
+extern u32 libio_inl(unsigned long addr);
+extern void libio_outb(u8 value, unsigned long addr);
+extern void libio_outw(u16 value, unsigned long addr);
+extern void libio_outl(u32 value, unsigned long addr);
+extern void libio_insb(unsigned long addr, void *buffer, unsigned int count);
+extern void libio_insl(unsigned long addr, void *buffer, unsigned int count);
+extern void libio_insw(unsigned long addr, void *buffer, unsigned int count);
+extern void libio_outsb(unsigned long addr, const void *buffer,
+ unsigned int count);
+extern void libio_outsw(unsigned long addr, const void *buffer,
+ unsigned int count);
+extern void libio_outsl(unsigned long addr, const void *buffer,
+ unsigned int count);
+#ifdef CONFIG_LIBIO
+extern struct libio_range
+*find_io_range_from_fwnode(struct fwnode_handle *fwnode);
+extern unsigned long libio_translate_hwaddr(struct fwnode_handle *fwnode,
+ resource_size_t hw_addr);
+#else
+static inline struct libio_range
+*find_io_range_from_fwnode(struct fwnode_handle *fwnode)
+{
+ return NULL;
+}
+
+static inline unsigned long libio_translate_hwaddr(struct fwnode_handle *fwnode,
+ resource_size_t hw_addr)
+{
+ return -1;
+}
+#endif
+
+extern struct libio_range *register_libio_range(struct libio_range *newrange);
+extern resource_size_t libio_to_hwaddr(unsigned long pio);
+
+extern unsigned long libio_translate_cpuaddr(resource_size_t hw_addr);
+
+#endif /* __KERNEL__ */
+#endif /* __LINUX_LIBIO_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index 0c8b78a..ba9787d5 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -59,6 +59,20 @@ config ARCH_USE_CMPXCHG_LOCKREF
config ARCH_HAS_FAST_MULTIPLIER
bool
+config LIBIO
+ bool "Generic logical IO management"
+ def_bool y if PCI && (ARM || ARC || UNICORE32 || SPARC || S390 || CRIS || BLACKFIN || XTENSA || ARM64)
+ help
+ For some architectures, there are no IO space. To support the
+ accesses to legacy I/O devices on those architectures, kernel
+ implemented the memory mapped I/O mechanism based on bridge bus
+ supports. But for some buses which do not support MMIO, the
+ peripherals there should be accessed with device-specific way.
+ To abstract those different I/O accesses into unified I/O accessors,
+ this option provide a generic I/O space management way after mapping
+ the device I/O to system logical/fake I/O and help to hide all the
+ hardware detail.
+
config CRC_CCITT
tristate "CRC-CCITT functions"
help
diff --git a/lib/Makefile b/lib/Makefile
index 320ac46a..9c4cd24 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -77,6 +77,8 @@ obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o
obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
+obj-$(CONFIG_LIBIO) += libio.o
+
obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
obj-$(CONFIG_BTREE) += btree.o
diff --git a/lib/libio.c b/lib/libio.c
new file mode 100644
index 0000000..e42f50b
--- /dev/null
+++ b/lib/libio.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2017 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/of.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/rculist.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+
+/* A list of all the IO hosts registered. ONLY THE HOST nodes. */
+static LIST_HEAD(io_range_list);
+static DEFINE_MUTEX(io_range_mutex);
+
+/*
+ * allocate a free range for this registration.
+ *
+ * @new_range: point to the node awaiting this registration.
+ * part of the fields are as input parameters. This node
+ * is allocated and initialized by caller;
+ * @prev: points to the last node before the return;
+ *
+ * return 0 for success, other are fail.
+ */
+static int libio_alloc_range(struct libio_range *new_range,
+ struct list_head **prev)
+{
+ struct libio_range *entry;
+ unsigned long align = 1;
+ unsigned long tmp_start;
+ unsigned long idle_start, idle_end;
+
+ if (new_range->flags & IO_CPU_MMIO)
+ align = PAGE_SIZE;
+ idle_start = 0;
+ *prev = &io_range_list;
+ list_for_each_entry_rcu(entry, &io_range_list, list) {
+ if (idle_start > entry->io_start) {
+ WARN(1, "skip an invalid io range during traversal!\n");
+ goto nextentry;
+ }
+ /* set the end edge. */
+ if (idle_start == entry->io_start) {
+ struct libio_range *next;
+
+ idle_start = entry->io_start + entry->size;
+ next = list_next_or_null_rcu(&io_range_list,
+ &entry->list, struct libio_range, list);
+ if (next) {
+ entry = next;
+ } else {
+ *prev = &entry->list;
+ break;
+ }
+ }
+ idle_end = entry->io_start - 1;
+
+ /* contiguous range... */
+ if (idle_start > idle_end)
+ goto nextentry;
+
+ tmp_start = idle_start;
+ idle_start = ALIGN(idle_start, align);
+ if (idle_start >= tmp_start &&
+ idle_start + new_range->size <= idle_end) {
+ new_range->io_start = idle_start;
+ *prev = &entry->list;
+ return 0;
+ }
+
+nextentry:
+ idle_start = entry->io_start + entry->size;
+ *prev = &entry->list;
+ }
+ /* check the last free gap... */
+ idle_end = IO_SPACE_LIMIT;
+
+ tmp_start = idle_start;
+ idle_start = ALIGN(idle_start, align);
+ if (idle_start >= tmp_start &&
+ idle_start + new_range->size <= idle_end) {
+ new_range->io_start = idle_start;
+ return 0;
+ }
+
+ return -EBUSY;
+}
+
+/*
+ * traverse the io_range_list to find the registered node whose device node
+ * and/or physical IO address match to.
+ */
+struct libio_range *find_io_range_from_fwnode(struct fwnode_handle *fwnode)
+{
+ struct libio_range *range;
+
+ list_for_each_entry_rcu(range, &io_range_list, list) {
+ if (range->node == fwnode)
+ return range;
+ }
+ return NULL;
+}
+
+/*
+ * Search a io_range registered which match the fwnode and addr.
+ *
+ * @fwnode: the host fwnode which must be valid;
+ * @start: the start hardware address of this search;
+ * @end: the end hardware address of this search. can be equal to @start;
+ *
+ * return NULL when there is no matched node; IS_ERR() means ERROR;
+ * valid virtual address represent a matched node was found.
+ */
+static struct libio_range *
+libio_find_range_byaddr(struct fwnode_handle *fwnode,
+ resource_size_t start, resource_size_t end)
+{
+ struct libio_range *entry;
+
+ list_for_each_entry_rcu(entry, &io_range_list, list) {
+ if (entry->node != fwnode)
+ continue;
+ /* without any overlap with current range */
+ if (start >= entry->hw_start + entry->size ||
+ end < entry->hw_start)
+ continue;
+ /* overlap is not supported now. */
+ if (start < entry->hw_start ||
+ end >= entry->hw_start + entry->size)
+ return ERR_PTR(-EBUSY);
+ /* had been registered. */
+ return entry;
+ }
+
+ return NULL;
+}
+
+/*
+ * register a io range node in the io range list.
+ *
+ * @newrange: pointer to the io range to be registered.
+ *
+ * return 'newrange' when success, ERR_VALUE() is for failures.
+ * specially, return a valid pointer which is not equal to 'newrange' when
+ * the io range had been registered before.
+ */
+struct libio_range *register_libio_range(struct libio_range *newrange)
+{
+ int err;
+ struct libio_range *range;
+ struct list_head *prev;
+
+ if (!newrange || !newrange->node || !newrange->size)
+ return ERR_PTR(-EINVAL);
+
+ mutex_lock(&io_range_mutex);
+ range = libio_find_range_byaddr(newrange->node, newrange->hw_start,
+ newrange->hw_start + newrange->size - 1);
+ if (range) {
+ if (!IS_ERR(range))
+ pr_info("the request IO range had been registered!\n");
+ else
+ pr_err("registering IO[%pa - sz%pa) got failed!\n",
+ &newrange->hw_start, &newrange->size);
+ return range;
+ }
+
+ err = libio_alloc_range(newrange, &prev);
+ if (!err)
+ /* the bus IO range list is ordered by pio. */
+ list_add_rcu(&newrange->list, prev);
+ else
+ pr_err("can't find free %pa logical IO range!\n",
+ &newrange->size);
+
+ mutex_unlock(&io_range_mutex);
+ return err ? ERR_PTR(err) : newrange;
+}
+
+/*
+ * Translate the input logical pio to the corresponding hardware address.
+ * The input pio should be unique in the whole logical PIO space.
+ */
+resource_size_t libio_to_hwaddr(unsigned long pio)
+{
+ struct libio_range *range;
+
+ list_for_each_entry_rcu(range, &io_range_list, list) {
+ if (pio < range->io_start)
+ break;
+
+ if (pio < range->io_start + range->size)
+ return pio - range->io_start + range->hw_start;
+ }
+
+ return -1;
+}
+
+/*
+ * This function is generic for translating a hardware address to logical PIO.
+ * @hw_addr: the hardware address of host, can be CPU address or host-local
+ * address;
+ */
+unsigned long
+libio_translate_hwaddr(struct fwnode_handle *fwnode, resource_size_t addr)
+{
+ struct libio_range *range;
+
+ range = libio_find_range_byaddr(fwnode, addr, addr);
+ if (!range)
+ return -1;
+
+ return addr - range->hw_start + range->io_start;
+}
+
+unsigned long
+libio_translate_cpuaddr(resource_size_t addr)
+{
+ struct libio_range *range;
+
+ list_for_each_entry_rcu(range, &io_range_list, list) {
+ if (!(range->flags & IO_CPU_MMIO))
+ continue;
+ if (addr >= range->hw_start &&
+ addr < range->hw_start + range->size)
+ return addr - range->hw_start + range->io_start;
+ }
+ return -1;
+}
+
+#ifdef PCI_IOBASE
+static struct libio_range *find_io_range(unsigned long pio)
+{
+ struct libio_range *range;
+
+ list_for_each_entry_rcu(range, &io_range_list, list) {
+ if (range->io_start > pio)
+ return NULL;
+ if (pio < range->io_start + range->size)
+ return range;
+ }
+ return NULL;
+}
+
+#define BUILD_IO(bw, type) \
+type libio_in##bw(unsigned long addr) \
+{ \
+ struct libio_range *entry = find_io_range(addr); \
+ \
+ if (entry && entry->ops) \
+ return entry->ops->pfin(entry->devpara, \
+ addr, sizeof(type)); \
+ return read##bw(PCI_IOBASE + addr); \
+} \
+ \
+void libio_out##bw(type value, unsigned long addr) \
+{ \
+ struct libio_range *entry = find_io_range(addr); \
+ \
+ if (entry && entry->ops) \
+ entry->ops->pfout(entry->devpara, \
+ addr, value, sizeof(type)); \
+ else \
+ write##bw(value, PCI_IOBASE + addr); \
+} \
+ \
+void libio_ins##bw(unsigned long addr, void *buffer, unsigned int count)\
+{ \
+ struct libio_range *entry = find_io_range(addr); \
+ \
+ if (entry && entry->ops) \
+ entry->ops->pfins(entry->devpara, \
+ addr, buffer, sizeof(type), count); \
+ else \
+ reads##bw(PCI_IOBASE + addr, buffer, count); \
+} \
+ \
+void libio_outs##bw(unsigned long addr, const void *buffer, \
+ unsigned int count) \
+{ \
+ struct libio_range *entry = find_io_range(addr); \
+ \
+ if (entry && entry->ops) \
+ entry->ops->pfouts(entry->devpara, \
+ addr, buffer, sizeof(type), count); \
+ else \
+ writes##bw(PCI_IOBASE + addr, buffer, count); \
+}
+
+BUILD_IO(b, u8)
+
+EXPORT_SYMBOL(libio_inb);
+EXPORT_SYMBOL(libio_outb);
+EXPORT_SYMBOL(libio_insb);
+EXPORT_SYMBOL(libio_outsb);
+
+BUILD_IO(w, u16)
+
+EXPORT_SYMBOL(libio_inw);
+EXPORT_SYMBOL(libio_outw);
+EXPORT_SYMBOL(libio_insw);
+EXPORT_SYMBOL(libio_outsw);
+
+BUILD_IO(l, u32)
+
+EXPORT_SYMBOL(libio_inl);
+EXPORT_SYMBOL(libio_outl);
+EXPORT_SYMBOL(libio_insl);
+EXPORT_SYMBOL(libio_outsl);
+#endif /* PCI_IOBASE */
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | "zhichang.yuan" <yuanzhichang@hisilicon.com> |
|---|---|
| Date | 2017-03-13 03:30 +0100 |
| Subject | [PATCH V7 5/7] ACPI: Delay the enumeration on the devices whose dependency has not met |
| Message-ID | <tknUe-1XV-7@gated-at.bofh.it> |
| In reply to | #1598822 |
In commit 40e7fcb1929(ACPI: Add _DEP support to fix battery issue on Asus
T100TA), the '_DEP' was supported to solve the dependency of Asus battery. But
this patch is specific to Asus battery device.
In the real world, there are other devices which need the dependency to play the
role on the enumeration order. For example, all the Hip06 LPC
periperals(IPMI-BT, uart, etc) must be scanned after the LPC host driver
finished the probing. So, it makes sense to add a checking whether the ACPI
device meet all the dependencies during its enumeration slot, if not, the
enumeration will be delayed till all dependency master finish their work.
This patch adds the dependency checking in ACPI enumeration, also the
corresponding handling to retrigger the Hip06 LPC peripherals' scanning.
Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
---
drivers/acpi/battery.c | 3 ---
drivers/acpi/scan.c | 3 +++
drivers/bus/hisi_lpc.c | 12 +++++++++++-
3 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 4ef1e46..e8d1af1 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -1210,9 +1210,6 @@ static int acpi_battery_add(struct acpi_device *device)
if (!device)
return -EINVAL;
- if (device->dep_unmet)
- return -EPROBE_DEFER;
-
battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
if (!battery)
return -ENOMEM;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 1926918..97721b1 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1843,6 +1843,9 @@ static void acpi_bus_attach(struct acpi_device *device)
if (device->handler)
goto ok;
+ if (device->dep_unmet)
+ return;
+
if (!device->flags.initialized) {
device->flags.power_manageable =
device->power.states[ACPI_STATE_D0].flags.valid;
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
index 03cf19a..345ea12 100644
--- a/drivers/bus/hisi_lpc.c
+++ b/drivers/bus/hisi_lpc.c
@@ -516,8 +516,18 @@ static int hisilpc_probe(struct platform_device *pdev)
/*
* It is time to start the children scannings....
+ * For ACPI children, the corresponding devices will be created after
+ * retriggering the ACPI scanning by removing the dependency blocking.
*/
- if (!has_acpi_companion(dev)) {
+ if (has_acpi_companion(dev)) {
+ struct acpi_device *adev;
+
+ adev = to_acpi_device_node(dev->fwnode);
+ if (!adev)
+ ret = -ENODEV;
+ else
+ acpi_walk_dep_device_list(adev->handle);
+ } else {
ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
if (ret)
dev_err(dev, "OF: enumerate LPC bus fail(%d)\n", ret);
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | "Rafael J. Wysocki" <rjw@rjwysocki.net> |
|---|---|
| Date | 2017-03-13 22:40 +0100 |
| Subject | Re: [PATCH V7 5/7] ACPI: Delay the enumeration on the devices whose dependency has not met |
| Message-ID | <tkFR7-6IY-13@gated-at.bofh.it> |
| In reply to | #1598826 |
On Monday, March 13, 2017 10:42:41 AM zhichang.yuan wrote: > In commit 40e7fcb1929(ACPI: Add _DEP support to fix battery issue on Asus > T100TA), the '_DEP' was supported to solve the dependency of Asus battery. But > this patch is specific to Asus battery device. > In the real world, there are other devices which need the dependency to play the > role on the enumeration order. For example, all the Hip06 LPC > periperals(IPMI-BT, uart, etc) must be scanned after the LPC host driver > finished the probing. So, it makes sense to add a checking whether the ACPI > device meet all the dependencies during its enumeration slot, if not, the > enumeration will be delayed till all dependency master finish their work. > > This patch adds the dependency checking in ACPI enumeration, also the > corresponding handling to retrigger the Hip06 LPC peripherals' scanning. AFAICS, _DEP is generally abused in the wild and cannot be made generic. Sorry. Thanks, Rafael
[toc] | [prev] | [next] | [standalone]
| From | Gabriele Paoloni <gabriele.paoloni@huawei.com> |
|---|---|
| Date | 2017-03-14 09:20 +0100 |
| Subject | RE: [PATCH V7 5/7] ACPI: Delay the enumeration on the devices whose dependency has not met |
| Message-ID | <tkPQt-5JY-7@gated-at.bofh.it> |
| In reply to | #1599842 |
Hi Rafael Many thanks for your review > -----Original Message----- > From: Rafael J. Wysocki [mailto:rjw@rjwysocki.net] > Sent: 13 March 2017 21:25 > To: Yuanzhichang > Cc: catalin.marinas@arm.com; will.deacon@arm.com; robh+dt@kernel.org; > frowand.list@gmail.com; bhelgaas@google.com; rafael@kernel.org; > mark.rutland@arm.com; arnd@arndb.de; linux-arm- > kernel@lists.infradead.org; linux-acpi@vger.kernel.org; > lorenzo.pieralisi@arm.com; benh@kernel.crashing.org; linux- > kernel@vger.kernel.org; Linuxarm; devicetree@vger.kernel.org; linux- > pci@vger.kernel.org; linux-serial@vger.kernel.org; minyard@acm.org; > liviu.dudau@arm.com; zourongrong@gmail.com; John Garry; Gabriele > Paoloni; zhichang.yuan02@gmail.com; kantyzc@163.com; xuwei (O) > Subject: Re: [PATCH V7 5/7] ACPI: Delay the enumeration on the devices > whose dependency has not met > > On Monday, March 13, 2017 10:42:41 AM zhichang.yuan wrote: > > In commit 40e7fcb1929(ACPI: Add _DEP support to fix battery issue on > Asus > > T100TA), the '_DEP' was supported to solve the dependency of Asus > battery. But > > this patch is specific to Asus battery device. > > In the real world, there are other devices which need the dependency > to play the > > role on the enumeration order. For example, all the Hip06 LPC > > periperals(IPMI-BT, uart, etc) must be scanned after the LPC host > driver > > finished the probing. So, it makes sense to add a checking whether > the ACPI > > device meet all the dependencies during its enumeration slot, if not, > the > > enumeration will be delayed till all dependency master finish their > work. > > > > This patch adds the dependency checking in ACPI enumeration, also the > > corresponding handling to retrigger the Hip06 LPC peripherals' > scanning. > > AFAICS, _DEP is generally abused in the wild and cannot be made > generic. Sorry. Another option here would be to revert this patch and add a dependency check in the probe functions of the LPC possible children nodes (e.g. in the IPMI driver: http://elixir.free-electrons.com/source/drivers/char/ipmi/ipmi_si_intf.c?v=4.10#L2683 ) we could add if (device->dep_unmet) return -EPROBE_DEFER; as we now have in acpi/battery.c... I think this should not make any difference for current shipped FW that has got no DEP method... What do you think? Many Thanks Gab > > Thanks, > Rafael
[toc] | [prev] | [next] | [standalone]
| From | "zhichang.yuan" <yuanzhichang@hisilicon.com> |
|---|---|
| Date | 2017-03-16 03:30 +0100 |
| Subject | Re: [PATCH V7 5/7] ACPI: Delay the enumeration on the devices whose dependency has not met |
| Message-ID | <tltkR-8jX-7@gated-at.bofh.it> |
| In reply to | #1599842 |
Hi, Rafael, Thanks for your review! On 2017/3/14 5:24, Rafael J. Wysocki wrote: > On Monday, March 13, 2017 10:42:41 AM zhichang.yuan wrote: >> In commit 40e7fcb1929(ACPI: Add _DEP support to fix battery issue on Asus >> T100TA), the '_DEP' was supported to solve the dependency of Asus battery. But >> this patch is specific to Asus battery device. >> In the real world, there are other devices which need the dependency to play the >> role on the enumeration order. For example, all the Hip06 LPC >> periperals(IPMI-BT, uart, etc) must be scanned after the LPC host driver >> finished the probing. So, it makes sense to add a checking whether the ACPI >> device meet all the dependencies during its enumeration slot, if not, the >> enumeration will be delayed till all dependency master finish their work. >> >> This patch adds the dependency checking in ACPI enumeration, also the >> corresponding handling to retrigger the Hip06 LPC peripherals' scanning. > > AFAICS, _DEP is generally abused in the wild and cannot be made generic. Sorry. > From the ACPI specification, _DEP is for operation region accesses. You are right... How about we add a ACPI handler for our LPC bus?? Just like amba. In this way, we also can solve the issue about LPC enumeration order. Thanks, Zhichang > Thanks, > Rafael > > > . >
[toc] | [prev] | [next] | [standalone]
| From | Arnd Bergmann <arnd@arndb.de> |
|---|---|
| Date | 2017-03-16 11:20 +0100 |
| Subject | Re: [PATCH V7 5/7] ACPI: Delay the enumeration on the devices whose dependency has not met |
| Message-ID | <tlAFI-5fe-15@gated-at.bofh.it> |
| In reply to | #1601881 |
On Thu, Mar 16, 2017 at 3:21 AM, zhichang.yuan
<yuanzhichang@hisilicon.com> wrote:
> Hi, Rafael,
>
> Thanks for your review!
>
> On 2017/3/14 5:24, Rafael J. Wysocki wrote:
>> On Monday, March 13, 2017 10:42:41 AM zhichang.yuan wrote:
>>> In commit 40e7fcb1929(ACPI: Add _DEP support to fix battery issue on Asus
>>> T100TA), the '_DEP' was supported to solve the dependency of Asus battery. But
>>> this patch is specific to Asus battery device.
>>> In the real world, there are other devices which need the dependency to play the
>>> role on the enumeration order. For example, all the Hip06 LPC
>>> periperals(IPMI-BT, uart, etc) must be scanned after the LPC host driver
>>> finished the probing. So, it makes sense to add a checking whether the ACPI
>>> device meet all the dependencies during its enumeration slot, if not, the
>>> enumeration will be delayed till all dependency master finish their work.
>>>
>>> This patch adds the dependency checking in ACPI enumeration, also the
>>> corresponding handling to retrigger the Hip06 LPC peripherals' scanning.
>>
>> AFAICS, _DEP is generally abused in the wild and cannot be made generic. Sorry.
>>
>
> From the ACPI specification, _DEP is for operation region accesses.
> You are right...
>
> How about we add a ACPI handler for our LPC bus?? Just like amba.
> In this way, we also can solve the issue about LPC enumeration order.
As far as I can tell, PCI and LPC have exactly the same requirement here,
so whatever you end up doing for one should be used for the other as well.
Arnd
[toc] | [prev] | [next] | [standalone]
| From | "zhichang.yuan" <zhichang.yuan02@gmail.com> |
|---|---|
| Date | 2017-03-16 16:00 +0100 |
| Subject | Re: [PATCH V7 5/7] ACPI: Delay the enumeration on the devices whose dependency has not met |
| Message-ID | <tlF2I-8g9-69@gated-at.bofh.it> |
| In reply to | #1602158 |
Hi, Arnd, On 03/16/2017 06:13 PM, Arnd Bergmann wrote: > On Thu, Mar 16, 2017 at 3:21 AM, zhichang.yuan > <yuanzhichang@hisilicon.com> wrote: >> Hi, Rafael, >> >> Thanks for your review! >> >> On 2017/3/14 5:24, Rafael J. Wysocki wrote: >>> On Monday, March 13, 2017 10:42:41 AM zhichang.yuan wrote: >>>> In commit 40e7fcb1929(ACPI: Add _DEP support to fix battery issue on Asus >>>> T100TA), the '_DEP' was supported to solve the dependency of Asus battery. But >>>> this patch is specific to Asus battery device. >>>> In the real world, there are other devices which need the dependency to play the >>>> role on the enumeration order. For example, all the Hip06 LPC >>>> periperals(IPMI-BT, uart, etc) must be scanned after the LPC host driver >>>> finished the probing. So, it makes sense to add a checking whether the ACPI >>>> device meet all the dependencies during its enumeration slot, if not, the >>>> enumeration will be delayed till all dependency master finish their work. >>>> >>>> This patch adds the dependency checking in ACPI enumeration, also the >>>> corresponding handling to retrigger the Hip06 LPC peripherals' scanning. >>> >>> AFAICS, _DEP is generally abused in the wild and cannot be made generic. Sorry. >>> >> >> From the ACPI specification, _DEP is for operation region accesses. >> You are right... >> >> How about we add a ACPI handler for our LPC bus?? Just like amba. >> In this way, we also can solve the issue about LPC enumeration order. > > As far as I can tell, PCI and LPC have exactly the same requirement here, > so whatever you end up doing for one should be used for the other as well. > Thanks for your remind! To some extend, our LPC is similar to PCI. We also need to setup the host resources before scanning the children. For PCI, there is an ACPI handler of pci_root_handler. Although our LPC is not so complicated and powerful as PCI(for example, LPC can't probe downside devices), I think, we can still make LPC host ready to work in its own ACPI handler callback.... Cheers, Zhichang > Arnd >
[toc] | [prev] | [next] | [standalone]
| From | Gabriele Paoloni <gabriele.paoloni@huawei.com> |
|---|---|
| Date | 2017-03-16 17:20 +0100 |
| Subject | RE: [PATCH V7 5/7] ACPI: Delay the enumeration on the devices whose dependency has not met |
| Message-ID | <tlGi5-RT-9@gated-at.bofh.it> |
| In reply to | #1602158 |
Hi Arnd > -----Original Message----- > From: arndbergmann@gmail.com [mailto:arndbergmann@gmail.com] On Behalf > Of Arnd Bergmann > Sent: 16 March 2017 10:13 > To: Yuanzhichang > Cc: Rafael J. Wysocki; Catalin Marinas; Will Deacon; Rob Herring; Frank > Rowand; Bjorn Helgaas; Rafael Wysocki; Mark Rutland; Linux ARM; ACPI > Devel Maling List; Lorenzo Pieralisi; Benjamin Herrenschmidt; Linux > Kernel Mailing List; Linuxarm; devicetree@vger.kernel.org; linux-pci; > linux-serial@vger.kernel.org; Corey Minyard; liviu.dudau@arm.com; Zou > Rongrong; John Garry; Gabriele Paoloni; zhichang.yuan02@gmail.com; > kantyzc@163.com; xuwei (O) > Subject: Re: [PATCH V7 5/7] ACPI: Delay the enumeration on the devices > whose dependency has not met > > On Thu, Mar 16, 2017 at 3:21 AM, zhichang.yuan > <yuanzhichang@hisilicon.com> wrote: > > Hi, Rafael, > > > > Thanks for your review! > > > > On 2017/3/14 5:24, Rafael J. Wysocki wrote: > >> On Monday, March 13, 2017 10:42:41 AM zhichang.yuan wrote: > >>> In commit 40e7fcb1929(ACPI: Add _DEP support to fix battery issue > on Asus > >>> T100TA), the '_DEP' was supported to solve the dependency of Asus > battery. But > >>> this patch is specific to Asus battery device. > >>> In the real world, there are other devices which need the > dependency to play the > >>> role on the enumeration order. For example, all the Hip06 LPC > >>> periperals(IPMI-BT, uart, etc) must be scanned after the LPC host > driver > >>> finished the probing. So, it makes sense to add a checking whether > the ACPI > >>> device meet all the dependencies during its enumeration slot, if > not, the > >>> enumeration will be delayed till all dependency master finish their > work. > >>> > >>> This patch adds the dependency checking in ACPI enumeration, also > the > >>> corresponding handling to retrigger the Hip06 LPC peripherals' > scanning. > >> > >> AFAICS, _DEP is generally abused in the wild and cannot be made > generic. Sorry. > >> > > > > From the ACPI specification, _DEP is for operation region accesses. > > You are right... > > > > How about we add a ACPI handler for our LPC bus?? Just like amba. > > In this way, we also can solve the issue about LPC enumeration order. > > As far as I can tell, PCI and LPC have exactly the same requirement > here, > so whatever you end up doing for one should be used for the other as > well. Well as you know PCI has got his own handler, identified by his own namespace id "PNP0A03". Now when you say "you end up doing for one should be used for the other" are you saying that we should introduce a new class of devices? i.e. should we have an ACPI namespace identifier for non-PCI IO Host Controllers? Otherwise, if my understanding is correct, having a specific new ACPI handler for HiSilicon LPC would mean to adding another function_init() in the list of acpi handlers inits in acpi_scan_init(). But then every vendor would declare his own one...is this really correct? Many Thanks Gab > > Arnd
[toc] | [prev] | [next] | [standalone]
| From | Gabriele Paoloni <gabriele.paoloni@huawei.com> |
|---|---|
| Date | 2017-03-24 01:50 +0100 |
| Subject | RE: [PATCH V7 5/7] ACPI: Delay the enumeration on the devices whose dependency has not met |
| Message-ID | <tolAu-1Sz-11@gated-at.bofh.it> |
| In reply to | #1602610 |
Hi Arnd > -----Original Message----- > From: linuxarm-bounces@huawei.com [mailto:linuxarm-bounces@huawei.com] > On Behalf Of Gabriele Paoloni > Sent: 16 March 2017 16:14 > To: Arnd Bergmann; Yuanzhichang > Cc: Mark Rutland; Benjamin Herrenschmidt; Rafael Wysocki; linux-pci; > Will Deacon; Linuxarm; Frank Rowand; Lorenzo Pieralisi; ACPI Devel > Maling List; linux-serial@vger.kernel.org; Catalin Marinas; > devicetree@vger.kernel.org; Corey Minyard; liviu.dudau@arm.com; Rob > Herring; Bjorn Helgaas; kantyzc@163.com; zhichang.yuan02@gmail.com; > Linux ARM; Rafael J. Wysocki; Linux Kernel Mailing List; Zou Rongrong > Subject: RE: [PATCH V7 5/7] ACPI: Delay the enumeration on the devices > whose dependency has not met > > Hi Arnd > > > -----Original Message----- > > From: arndbergmann@gmail.com [mailto:arndbergmann@gmail.com] On > Behalf > > Of Arnd Bergmann > > Sent: 16 March 2017 10:13 > > To: Yuanzhichang > > Cc: Rafael J. Wysocki; Catalin Marinas; Will Deacon; Rob Herring; > Frank > > Rowand; Bjorn Helgaas; Rafael Wysocki; Mark Rutland; Linux ARM; ACPI > > Devel Maling List; Lorenzo Pieralisi; Benjamin Herrenschmidt; Linux > > Kernel Mailing List; Linuxarm; devicetree@vger.kernel.org; linux-pci; > > linux-serial@vger.kernel.org; Corey Minyard; liviu.dudau@arm.com; Zou > > Rongrong; John Garry; Gabriele Paoloni; zhichang.yuan02@gmail.com; > > kantyzc@163.com; xuwei (O) > > Subject: Re: [PATCH V7 5/7] ACPI: Delay the enumeration on the > devices > > whose dependency has not met > > > > On Thu, Mar 16, 2017 at 3:21 AM, zhichang.yuan > > <yuanzhichang@hisilicon.com> wrote: > > > Hi, Rafael, > > > > > > Thanks for your review! > > > > > > On 2017/3/14 5:24, Rafael J. Wysocki wrote: > > >> On Monday, March 13, 2017 10:42:41 AM zhichang.yuan wrote: > > >>> In commit 40e7fcb1929(ACPI: Add _DEP support to fix battery issue > > on Asus > > >>> T100TA), the '_DEP' was supported to solve the dependency of Asus > > battery. But > > >>> this patch is specific to Asus battery device. > > >>> In the real world, there are other devices which need the > > dependency to play the > > >>> role on the enumeration order. For example, all the Hip06 LPC > > >>> periperals(IPMI-BT, uart, etc) must be scanned after the LPC host > > driver > > >>> finished the probing. So, it makes sense to add a checking > whether > > the ACPI > > >>> device meet all the dependencies during its enumeration slot, if > > not, the > > >>> enumeration will be delayed till all dependency master finish > their > > work. > > >>> > > >>> This patch adds the dependency checking in ACPI enumeration, also > > the > > >>> corresponding handling to retrigger the Hip06 LPC peripherals' > > scanning. > > >> > > >> AFAICS, _DEP is generally abused in the wild and cannot be made > > generic. Sorry. > > >> > > > > > > From the ACPI specification, _DEP is for operation region accesses. > > > You are right... > > > > > > How about we add a ACPI handler for our LPC bus?? Just like amba. > > > In this way, we also can solve the issue about LPC enumeration > order. > > > > As far as I can tell, PCI and LPC have exactly the same requirement > > here, > > so whatever you end up doing for one should be used for the other as > > well. > > Well as you know PCI has got his own handler, identified by his own > namespace id "PNP0A03". > Now when you say "you end up doing for one should be used for the > other" > are you saying that we should introduce a new class of devices? > i.e. should we have an ACPI namespace identifier for non-PCI IO Host > Controllers? > > Otherwise, if my understanding is correct, having a specific new ACPI > handler for HiSilicon LPC would mean to adding another function_init() > in the list of acpi handlers inits in acpi_scan_init(). > > But then every vendor would declare his own one...is this really > correct? Do you have any feedback on this? Otherwise I think that maybe we could consider moving back to the arch_initcall approach as proposed in V6: https://lkml.org/lkml/2017/1/24/28 Thanks Gab > > Many Thanks > Gab > > > > > Arnd > _______________________________________________ > linuxarm mailing list > linuxarm@huawei.com > http://rnd-openeuler.huawei.com/mailman/listinfo/linuxarm
[toc] | [prev] | [next] | [standalone]
| From | Arnd Bergmann <arnd@arndb.de> |
|---|---|
| Date | 2017-03-14 09:40 +0100 |
| Message-ID | <tkQ9Q-5Sw-15@gated-at.bofh.it> |
| In reply to | #1598822 |
On Mon, Mar 13, 2017 at 3:42 AM, zhichang.yuan
<yuanzhichang@hisilicon.com> wrote:
> This patchset supports the IPMI-bt device attached to the Low-Pin-Count
> interface implemented on Hisilicon Hip06/Hip07 SoC.
> -----------
> | LPC host|
> | |
> -----------
> |
> _____________V_______________LPC
> | |
> V V
> ------------
> | BT(ipmi)|
> ------------
>
> When master accesses those peripherals beneath the Hip06/Hip07 LPC, a specific
> LPC driver is needed to make LPC host generate the standard LPC I/O cycles with
> the target peripherals'I/O port addresses. But on curent arm64 world, there is
> no real I/O accesses. All the I/O operations through in/out pair are based on
> MMIO which is not satisfied the I/O mechanism on Hip06/Hip07 LPC.
> To solve this issue and keep the relevant existing peripherals' driver
> untouched, this patchset implements:
> - introduces a generic I/O space management framwork, LIBIO, to support I/O
> operations of both MMIO buses and the host controllers which access their
> peripherals with host local I/O addresses;
> - redefines the in/out accessors to provide unified interfaces for MMIO and
> legacy I/O. Based on the LIBIO, the calling of in/out() from upper-layer
> drivers, such as ipmi-si, will be redirected to the corresponding
> device-specific I/O hooks to perfrom the I/O accesses.
> Based on this patch-set, all the I/O accesses to Hip06/Hip07 LPC peripherals
> can be supported without any changes on the existing ipmi-si driver.
Thanks for reposting this. I have a few high-level comments first, based on
the walk through the code I did with Gabriele and John last week:
- I think the libio framework is more generic than it needs to be, but as
Alex really liked it this way and it was done like this based on his earlier
comments, I think that's ok.
- after we went back and forth on the ACPI implementation, we concluded
that it is correct to do the same as on DT and completely abstract the
number space for I/O ports. No code should rely on a Linux port number
to have any particular relation to the physical address or the the address
on a PCI or LPC bus.
- The name "libio" still needs to be changed, this is way too generic, as
"I/O" can refer to many things in the kernel, and almost none of them
are related to x86 programmed I/O ports in any way. My suggestion
would be "generic_ioport", or possibly "libioport", "libpio" or "pci_io". Any
of them would work for me, or someone else could come up with a better
name that describes what it is.
- I'm pretty sure the current implementation is broken for the ioport_map
function that tries to turn an IORESOURCE_IO number into a pointer.
Forcing CONFIG_GENERIC_IOMAP on would solve this, but also
make all MMIO operations slower, which we probably don't want.
It's probably enough to add a check in ioport_map() to see if the range
is mapped into a virtual address or not.
- We could simplify the lookup a bit by using the trick from arch/ia64
of using an array instead of linked list for walking the port numbers.
There, the upper bits of the port number refer to an address space
number while the lower bits refer to the bus address within that
address space. This should work just as well as the current
implementation but would be a little easier to understand. Maybe
Bjorn can comment on this too, as I think he was involved with the
ia64 implementation.
Arnd
[toc] | [prev] | [next] | [standalone]
| From | "zhichang.yuan" <yuanzhichang@hisilicon.com> |
|---|---|
| Date | 2017-03-15 05:10 +0100 |
| Message-ID | <tl8q6-25n-9@gated-at.bofh.it> |
| In reply to | #1600124 |
Hi, Arnd,
Many thanks for your review!
On 2017/3/14 16:39, Arnd Bergmann wrote:
> On Mon, Mar 13, 2017 at 3:42 AM, zhichang.yuan
> <yuanzhichang@hisilicon.com> wrote:
>> This patchset supports the IPMI-bt device attached to the Low-Pin-Count
>> interface implemented on Hisilicon Hip06/Hip07 SoC.
>> -----------
>> | LPC host|
>> | |
>> -----------
>> |
>> _____________V_______________LPC
>> | |
>> V V
>> ------------
>> | BT(ipmi)|
>> ------------
>>
>> When master accesses those peripherals beneath the Hip06/Hip07 LPC, a specific
>> LPC driver is needed to make LPC host generate the standard LPC I/O cycles with
>> the target peripherals'I/O port addresses. But on curent arm64 world, there is
>> no real I/O accesses. All the I/O operations through in/out pair are based on
>> MMIO which is not satisfied the I/O mechanism on Hip06/Hip07 LPC.
>> To solve this issue and keep the relevant existing peripherals' driver
>> untouched, this patchset implements:
>> - introduces a generic I/O space management framwork, LIBIO, to support I/O
>> operations of both MMIO buses and the host controllers which access their
>> peripherals with host local I/O addresses;
>> - redefines the in/out accessors to provide unified interfaces for MMIO and
>> legacy I/O. Based on the LIBIO, the calling of in/out() from upper-layer
>> drivers, such as ipmi-si, will be redirected to the corresponding
>> device-specific I/O hooks to perfrom the I/O accesses.
>> Based on this patch-set, all the I/O accesses to Hip06/Hip07 LPC peripherals
>> can be supported without any changes on the existing ipmi-si driver.
>
> Thanks for reposting this. I have a few high-level comments first, based on
> the walk through the code I did with Gabriele and John last week:
>
> - I think the libio framework is more generic than it needs to be, but as
> Alex really liked it this way and it was done like this based on his earlier
> comments, I think that's ok.
>
> - after we went back and forth on the ACPI implementation, we concluded
> that it is correct to do the same as on DT and completely abstract the
> number space for I/O ports. No code should rely on a Linux port number
> to have any particular relation to the physical address or the the address
> on a PCI or LPC bus.
Thanks again for your helps in Linaro Connect!
I think we are heading for this direction, is it?
>
> - The name "libio" still needs to be changed, this is way too generic, as
> "I/O" can refer to many things in the kernel, and almost none of them
> are related to x86 programmed I/O ports in any way. My suggestion
> would be "generic_ioport", or possibly "libioport", "libpio" or "pci_io". Any
> of them would work for me, or someone else could come up with a better
> name that describes what it is.
Ok. We will make a better name:)
>
> - I'm pretty sure the current implementation is broken for the ioport_map
> function that tries to turn an IORESOURCE_IO number into a pointer.
> Forcing CONFIG_GENERIC_IOMAP on would solve this, but also
> make all MMIO operations slower, which we probably don't want.
> It's probably enough to add a check in ioport_map() to see if the range
> is mapped into a virtual address or not.
Yes, I think our LIBIO will break the ioport_map() at this moment.
I try to solve this issue. Could you help to check the following ideas?
I am not deeper understanding the whole I/O framework, the following maybe not correct:(
ioport_map seems architecture-dependent. For our LIBIO, we don't want to replace the existing I/O
frameworks which support MMIO at this moment. Can we add these two revise to solve this issue?
1) Make LIBIO only target for non GENERIC_IOMAP platforms
config LIBIO
bool "Generic logical IO management"
depends on !GENERIC_IOMAP
def_bool y if PCI && (ARC || MN10300 || UNICORE32 || SPARC || MICROBLAZE || S390 || AVR32 || CRIS || BLACKFIN || XTENSA || ARM64)
2) Modify the ioport_map() defined in asm-generic/io.h
Add the checks to identify the input 'port' is MMIO, otherwise, return NULL;
Then is it enough to avoid the negative effect on the existing I/O framework?
>
> - We could simplify the lookup a bit by using the trick from arch/ia64
> of using an array instead of linked list for walking the port numbers.
> There, the upper bits of the port number refer to an address space
> number while the lower bits refer to the bus address within that
> address space. This should work just as well as the current
> implementation but would be a little easier to understand. Maybe
> Bjorn can comment on this too, as I think he was involved with the
> ia64 implementation.
>
Yes, It will be more efficient.
But the issue remained here is still how to coexist with the existing I/O frameworks.
I will continue to look into.
Thanks,
Zhichang
> Arnd
>
> .
>
[toc] | [prev] | [next] | [standalone]
| From | Arnd Bergmann <arnd@arndb.de> |
|---|---|
| Date | 2017-03-15 14:30 +0100 |
| Message-ID | <tlha1-8dq-3@gated-at.bofh.it> |
| In reply to | #1601029 |
On Wed, Mar 15, 2017 at 5:05 AM, zhichang.yuan
<yuanzhichang@hisilicon.com> wrote:
>> - I think the libio framework is more generic than it needs to be, but as
>> Alex really liked it this way and it was done like this based on his earlier
>> comments, I think that's ok.
>>
>> - after we went back and forth on the ACPI implementation, we concluded
>> that it is correct to do the same as on DT and completely abstract the
>> number space for I/O ports. No code should rely on a Linux port number
>> to have any particular relation to the physical address or the the address
>> on a PCI or LPC bus.
> Thanks again for your helps in Linaro Connect!
> I think we are heading for this direction, is it?
Yes, I think so.
>> - I'm pretty sure the current implementation is broken for the ioport_map
>> function that tries to turn an IORESOURCE_IO number into a pointer.
>> Forcing CONFIG_GENERIC_IOMAP on would solve this, but also
>> make all MMIO operations slower, which we probably don't want.
>> It's probably enough to add a check in ioport_map() to see if the range
>> is mapped into a virtual address or not.
>
>
> Yes, I think our LIBIO will break the ioport_map() at this moment.
> I try to solve this issue. Could you help to check the following ideas?
> I am not deeper understanding the whole I/O framework, the following maybe not correct:(
>
> ioport_map seems architecture-dependent. For our LIBIO, we don't want to replace the existing I/O
> frameworks which support MMIO at this moment. Can we add these two revise to solve this issue?
> 1) Make LIBIO only target for non GENERIC_IOMAP platforms
>
> config LIBIO
> bool "Generic logical IO management"
> depends on !GENERIC_IOMAP
I don't think there is even a problem with GENERIC_IOMAP: If both are
set, passing a low number as a pointer will turn an ioread32() into an
inl(), which is implemented by libio.
> def_bool y if PCI && (ARC || MN10300 || UNICORE32 || SPARC || MICROBLAZE || S390 || AVR32 || CRIS || BLACKFIN || XTENSA || ARM64)
I think most of these architectures just use their own inb/outb functions,
and should not use libio at all.
It's also possible that they use an older way of mapping I/O ports by calling
ioremap() on the physical address and treating the pointer as a 32-bit
I/O port number (relying on the PCI_IOBASE=0 default). Architectures doing
that might have other issues with libio, and I wouldn't try converting those.
> 2) Modify the ioport_map() defined in asm-generic/io.h
> Add the checks to identify the input 'port' is MMIO, otherwise, return NULL;
This seems fine.
>> - We could simplify the lookup a bit by using the trick from arch/ia64
>> of using an array instead of linked list for walking the port numbers.
>> There, the upper bits of the port number refer to an address space
>> number while the lower bits refer to the bus address within that
>> address space. This should work just as well as the current
>> implementation but would be a little easier to understand. Maybe
>> Bjorn can comment on this too, as I think he was involved with the
>> ia64 implementation.
>>
> Yes, It will be more efficient.
>
> But the issue remained here is still how to coexist with the existing I/O frameworks.
> I will continue to look into.
Ok. Let's wait for Bjorn to reply on this idea before you spend too much time
on this though.
Arnd
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web