Re: [dpdk-dev] [PATCH v11 2/2] bus/pci: support MMIO in PCI ioport accessors
From: Wang, Haiyue <hidden>
Date: 2021-03-11 06:43:34
Hi Huawei,
-----Original Message----- From: dev <redacted> On Behalf Of ???(????) Sent: Thursday, March 11, 2021 01:37 To: david.marchand@redhat.com; maxime.coquelin@redhat.com; Yigit, Ferruh <redacted> Cc: dev@dpdk.org; Burakov, Anatoly <redacted>; xuemingl@nvidia.com; grive@u256.net; 谢华伟(此时此刻) [off-list ref] Subject: [dpdk-dev] [PATCH v11 2/2] bus/pci: support MMIO in PCI ioport accessors With I/O BAR, we get PIO(port-mapped I/O) address. With MMIO(memory-mapped I/O) BAR, we get mapped virtual address. We distinguish PIO and MMIO by their address range like how kernel does, i.e, address below 64K is PIO. ioread/write8/16/32 is provided to access PIO/MMIO. By the way, for virtio on arch other than x86, BAR flag indicates PIO but is mapped. Signed-off-by: huawei xie <redacted> Reviewed-by: Maxime Coquelin <redacted> --- drivers/bus/pci/linux/pci.c | 4 -- drivers/bus/pci/linux/pci_uio.c | 156 +++++++++++++++++++++++++++++----------- 2 files changed, 113 insertions(+), 47 deletions(-)
+#if defined(RTE_ARCH_X86)
+static inline uint8_t ioread8(void *addr)
+{
+ uint8_t val;
+
+ val = (uint64_t)(uintptr_t)addr >= PIO_MAX ?
+ *(volatile uint8_t *)addr :
+ inb_p((unsigned long)addr);
+
+ return val;
+}
+
+static inline uint16_t ioread16(void *addr)
+{
+ uint16_t val;
+
+ val = (uint64_t)(uintptr_t)addr >= PIO_MAX ?
+ *(volatile uint16_t *)addr :
+ inw_p((unsigned long)addr);
+
+ return val;
+}
+
+static inline uint32_t ioread32(void *addr)
+{
+ uint32_t val;
+
+ val = (uint64_t)(uintptr_t)addr >= PIO_MAX ?
+ *(volatile uint32_t *)addr :
+ inl_p((unsigned long)addr);
+
+ return val;
+}
+
+static inline void iowrite8(uint8_t val, void *addr)
+{
+ (uint64_t)(uintptr_t)addr >= PIO_MAX ?
+ *(volatile uint8_t *)addr = val :
+ outb_p(val, (unsigned long)addr);
+}
+
+static inline void iowrite16(uint16_t val, void *addr)
+{
+ (uint64_t)(uintptr_t)addr >= PIO_MAX ?
+ *(volatile uint16_t *)addr = val :
+ outw_p(val, (unsigned long)addr);
+}
+
+static inline void iowrite32(uint32_t val, void *addr)
+{
+ (uint64_t)(uintptr_t)addr >= PIO_MAX ?
+ *(volatile uint32_t *)addr = val :
+ outl_p(val, (unsigned long)addr);
+}
+#else
+static inline uint8_t ioread8(void *addr)
+{
+ return *(volatile uint8_t *)addr;
+}
+
+static inline uint16_t ioread16(void *addr)
+{
+ return *(volatile uint16_t *)addr;
+}
+
+static inline uint32_t ioread32(void *addr)
+{
+ return *(volatile uint32_t *)addr;
+}
+
+static inline void iowrite8(uint8_t val, void *addr)
+{
+ *(volatile uint8_t *)addr = val;
+}
+
+static inline void iowrite16(uint16_t val, void *addr)
+{
+ *(volatile uint16_t *)addr = val;
+}
+
+static inline void iowrite32(uint32_t val, void *addr)
+{
+ *(volatile uint32_t *)addr = val;
+}
+#endif
+Like kernel use macro to do pio and mmio, maybe we can also to do so for making code clean: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/iomap.c #define IO_COND(addr, is_pio, is_mmio) do { \ unsigned long port = (unsigned long __force)addr; \ if (port >= PIO_RESERVED) { \ is_mmio; \ } else if (port > PIO_OFFSET) { \ port &= PIO_MASK; \ is_pio; \ } else \ bad_io_access(port, #is_pio ); \ } while (0) Like: #if defined(RTE_ARCH_X86) #define IO_COND(addr, is_pio, is_mmio) do { \ if ((uint64_t)(uintptr_t)addr >= PIO_MAX) { \ is_mmio; \ } else { \ is_pio; \ } \ } while (0) #else #define IO_COND(addr, is_pio, is_mmio) do { \ is_mmio; \ } while (0) #endif static inline uint8_t ioread8(void *addr) { uint8_t val; IO_COND(addr, val = inb_p((unsigned long)addr), val = *(volatile uint8_t *)addr); return val; } static inline uint16_t ioread16(void *addr) { uint16_t val; IO_COND(addr, val = inw_p((unsigned long)addr), val = *(volatile uint16_t *)addr); return val; } static inline uint32_t ioread32(void *addr) { uint32_t val; IO_COND(addr, val = inl_p((unsigned long)addr), val = *(volatile uint32_t *)addr); return val; } static inline void iowrite8(uint8_t val, void *addr) { IO_COND(addr, outb_p(val, (unsigned long)addr), *(volatile uint8_t *)addr = val); } static inline void iowrite16(uint16_t val, void *addr) { IO_COND(addr, outw_p(val, (unsigned long)addr), *(volatile uint16_t *)addr = val); } static inline void iowrite32(uint32_t val, void *addr) { IO_COND(addr, outl_p(val, (unsigned long)addr), *(volatile uint32_t *)addr = val); }
quoted hunk ↗ jump to hunk
void pci_uio_ioport_read(struct rte_pci_ioport *p, void *data, size_t len, off_t offset)@@ -528,25 +622,13 @@ for (d = data; len > 0; d += size, reg += size, len -= size) { if (len >= 4) { size = 4; -#if defined(RTE_ARCH_X86) - *(uint32_t *)d = inl(reg); -#else - *(uint32_t *)d = *(volatile uint32_t *)reg; -#endif + *(uint32_t *)d = ioread32((void *)reg); } else if (len >= 2) { size = 2; -#if defined(RTE_ARCH_X86) - *(uint16_t *)d = inw(reg); -#else - *(uint16_t *)d = *(volatile uint16_t *)reg; -#endif + *(uint16_t *)d = ioread16((void *)reg); } else { size = 1; -#if defined(RTE_ARCH_X86) - *d = inb(reg); -#else - *d = *(volatile uint8_t *)reg; -#endif + *d = ioread8((void *)reg); } } }@@ -562,25 +644,13 @@ for (s = data; len > 0; s += size, reg += size, len -= size) { if (len >= 4) { size = 4; -#if defined(RTE_ARCH_X86) - outl_p(*(const uint32_t *)s, reg); -#else - *(volatile uint32_t *)reg = *(const uint32_t *)s; -#endif + iowrite32(*(const uint32_t *)s, (void *)reg); } else if (len >= 2) { size = 2; -#if defined(RTE_ARCH_X86) - outw_p(*(const uint16_t *)s, reg); -#else - *(volatile uint16_t *)reg = *(const uint16_t *)s; -#endif + iowrite16(*(const uint16_t *)s, (void *)reg); } else { size = 1; -#if defined(RTE_ARCH_X86) - outb_p(*s, reg); -#else - *(volatile uint8_t *)reg = *s; -#endif + iowrite8(*s, (void *)reg); } } } --1.8.3.1