Hi Huawei, > -----Original Message----- > From: dev <dev-boun...@dpdk.org> On Behalf Of ???(????) > Sent: Thursday, March 11, 2021 01:37 > To: david.march...@redhat.com; maxime.coque...@redhat.com; Yigit, Ferruh > <ferruh.yi...@intel.com> > Cc: dev@dpdk.org; Burakov, Anatoly <anatoly.bura...@intel.com>; > xuemi...@nvidia.com; gr...@u256.net; > 谢华伟(此时此刻) <huawei....@alibaba-inc.com> > 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 <huawei....@alibaba-inc.com> > Reviewed-by: Maxime Coquelin <maxime.coque...@redhat.com> > --- > 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); } > 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