Discussion:
[PATCH v4 0/8] asm-generic/io.h overhaul
Thierry Reding
2014-08-13 10:28:50 UTC
Permalink
From: Thierry Reding <***@nvidia.com>

Hi,

Here is the fourth version of a series that started out as an attempt to
provide string versions of the read*() and write*() accessors to more
architectures so that drivers can use them portably. The series has
since evolved into a more general cleanup of asm-generic/io.h and the
functions defined therein.

Patch 1 is trivial and removes a redundant redefinition of PCI_IOBASE
from the asm/io.h header on ARC. Patches 2 and 3 remove unnecessary
volatile keywoards from some functions, which is a prerequisite to clean
up some of the functions in subsequent patches.

The xlate_dev_{kmem,mem}_ptr() functions are used to map memory when the
/dev/mem device is accessed. Patches 4 and 5 use more consistent data
types for these functions, which will get a "standard" prototype in the
asm-generic/io.h header in a subsequent patch.

Patch 6 is the bulk of this series. It implements the string variants of
the read*() and write*() accessors and cleans up various other parts of
the asm-generic/io.h header file. Macros are converted to static inline
functions for better type checking. Overriding generic implementations
in architectures is handled more consistently.

Patches 7 and 8, finally, make use of the asm-generic/io.h header on the
32-bit and 64-bit ARM architectures.

This is compile- and runtime-tested on 32-bit and 64-bit ARM and compile
tested on IA64, Microblaze, s390, SPARC, x86 and Xtensa. For ARC,
Blackfin, Metag, OpenRISC, Score and Unicore32 which also use
asm-generic/io.h I couldn't find or build a cross-compiler that would
run on my system. But by code inspection they shouldn't break with this
patch.

To ensure bisectability I built multi_v7_defconfig on 32-bit ARM and the
defconfig for 64-bit ARM, IA64, Microblaze, s390, SPARC, x86 and Xtensa
after each commit and verified that the series does not introduce any
build errors or warnings.

Provided there are no objections to the patches there's still the matter
of how to merge them. Patch 6 depends on patches 1-5 to avoid warnings
and/or errors during the build. Patches 7 and 8 depend on patch 6. In my
opinion it doesn't make much sense to split them up, so I guess we'll
need a volunteer to take them all into one tree. Ideally that tree would
feed into linux-next so that we can get as much build and test-coverage
as possible during the 3.17 release cycle so that these patches can go
into 3.18.

Arnd, I'm opportunistically sending this To: you in the hopes that you
can take it into your asm-generic tree which seems like the best fit for
this.

Thierry

Thierry Reding (8):
ARC: Remove redundant PCI_IOBASE declaration
serial: sunzilog: Remove unnecessary volatile keyword
sparc: Remove unnecessary volatile usage
[IA64] Change xlate_dev_{kmem,mem}_ptr() prototypes
/dev/mem: Use more consistent data types
asm-generic/io.h: Implement generic {read,write}s*()
ARM: Use include/asm-generic/io.h
arm64: Use include/asm-generic/io.h

arch/arc/include/asm/io.h | 2 -
arch/arm/include/asm/io.h | 75 ++---
arch/arm/include/asm/memory.h | 2 +
arch/arm64/Kconfig | 1 -
arch/arm64/include/asm/io.h | 122 ++-----
arch/arm64/include/asm/memory.h | 2 +
arch/ia64/include/asm/uaccess.h | 16 +-
arch/s390/include/asm/io.h | 5 +-
arch/s390/mm/maccess.c | 4 +-
arch/sparc/include/asm/io_32.h | 18 +-
arch/x86/include/asm/io.h | 4 +-
arch/x86/mm/ioremap.c | 4 +-
drivers/char/mem.c | 13 +-
drivers/tty/serial/sunzilog.h | 8 +-
include/asm-generic/io.h | 683 ++++++++++++++++++++++++++++++++--------
15 files changed, 647 insertions(+), 312 deletions(-)
--
2.0.4
Thierry Reding
2014-08-13 10:28:52 UTC
Permalink
From: Thierry Reding <***@nvidia.com>

The field annotated with volatile are all accessed through I/O accessors
so they don't need to be explicitly marked. The accessors will take care
of it.

Signed-off-by: Thierry Reding <***@nvidia.com>
---
Changes in v4:
- new patch

drivers/tty/serial/sunzilog.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/tty/serial/sunzilog.h b/drivers/tty/serial/sunzilog.h
index 5dec7b47cc38..de2850c1ab57 100644
--- a/drivers/tty/serial/sunzilog.h
+++ b/drivers/tty/serial/sunzilog.h
@@ -2,10 +2,10 @@
#define _SUNZILOG_H

struct zilog_channel {
- volatile unsigned char control;
- volatile unsigned char __pad1;
- volatile unsigned char data;
- volatile unsigned char __pad2;
+ unsigned char control;
+ unsigned char __pad1;
+ unsigned char data;
+ unsigned char __pad2;
};

struct zilog_layout {
--
2.0.4
Thierry Reding
2014-08-13 10:28:54 UTC
Permalink
From: Thierry Reding <***@nvidia.com>

xlate_dev_mem_ptr() is used to convert a physical address to an uncached
kernel virtual address mapping, so make it use phys_addr_t as type for
the physical address and return void * for the kernel virtual address.

xlate_dev_kmem_ptr() converts a cached kernel virtual address mapping to
an uncached kernel virtual address mapping, so make it use void * for
both the input parameter and return value.

Signed-off-by: Thierry Reding <***@nvidia.com>
---
Changes in v4:
- new patch

arch/ia64/include/asm/uaccess.h | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/ia64/include/asm/uaccess.h b/arch/ia64/include/asm/uaccess.h
index 449c8c0fa2bd..103bedc59644 100644
--- a/arch/ia64/include/asm/uaccess.h
+++ b/arch/ia64/include/asm/uaccess.h
@@ -365,15 +365,15 @@ ia64_done_with_exception (struct pt_regs *regs)
}

#define ARCH_HAS_TRANSLATE_MEM_PTR 1
-static __inline__ char *
-xlate_dev_mem_ptr (unsigned long p)
+static __inline__ void *
+xlate_dev_mem_ptr(phys_addr_t p)
{
struct page *page;
- char * ptr;
+ void *ptr;

page = pfn_to_page(p >> PAGE_SHIFT);
if (PageUncached(page))
- ptr = (char *)p + __IA64_UNCACHED_OFFSET;
+ ptr = (void *)p + __IA64_UNCACHED_OFFSET;
else
ptr = __va(p);

@@ -383,15 +383,15 @@ xlate_dev_mem_ptr (unsigned long p)
/*
* Convert a virtual cached kernel memory pointer to an uncached pointer
*/
-static __inline__ char *
-xlate_dev_kmem_ptr (char * p)
+static __inline__ void *
+xlate_dev_kmem_ptr(void *p)
{
struct page *page;
- char * ptr;
+ void *ptr;

page = virt_to_page((unsigned long)p);
if (PageUncached(page))
- ptr = (char *)__pa(p) + __IA64_UNCACHED_OFFSET;
+ ptr = (void *)__pa(p) + __IA64_UNCACHED_OFFSET;
else
ptr = p;
--
2.0.4
Thierry Reding
2014-08-13 10:28:58 UTC
Permalink
From: Thierry Reding <***@nvidia.com>

Include the generic I/O header file so that duplicate implementations
can be removed. This will also help to establish consistency across more
architectures regarding which accessors they support.

Acked-by: Catalin Marinas <***@arm.com>
Signed-off-by: Thierry Reding <***@nvidia.com>
---
Changes in v4:
- define xlate_dev_{kmem,mem}_ptr() before asm-generic/io.h include

Changes in v3:
- add io{read,write}{16,32}be() to match what 32-bit ARM does

arch/arm64/Kconfig | 1 -
arch/arm64/include/asm/io.h | 122 ++++++++--------------------------------
arch/arm64/include/asm/memory.h | 2 +
3 files changed, 27 insertions(+), 98 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 62b4ae1c5bbf..c06bd0b67865 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -23,7 +23,6 @@ config ARM64
select GENERIC_CLOCKEVENTS_BROADCAST if SMP
select GENERIC_CPU_AUTOPROBE
select GENERIC_EARLY_IOREMAP
- select GENERIC_IOMAP
select GENERIC_IRQ_PROBE
select GENERIC_IRQ_SHOW
select GENERIC_SCHED_CLOCK
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index e0ecdcf6632d..a8e7a717c360 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -34,26 +34,31 @@
/*
* Generic IO read/write. These perform native-endian accesses.
*/
+#define __raw_writeb __raw_writeb
static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
{
asm volatile("strb %w0, [%1]" : : "r" (val), "r" (addr));
}

+#define __raw_writew __raw_writew
static inline void __raw_writew(u16 val, volatile void __iomem *addr)
{
asm volatile("strh %w0, [%1]" : : "r" (val), "r" (addr));
}

+#define __raw_writel __raw_writel
static inline void __raw_writel(u32 val, volatile void __iomem *addr)
{
asm volatile("str %w0, [%1]" : : "r" (val), "r" (addr));
}

+#define __raw_writeq __raw_writeq
static inline void __raw_writeq(u64 val, volatile void __iomem *addr)
{
asm volatile("str %0, [%1]" : : "r" (val), "r" (addr));
}

+#define __raw_readb __raw_readb
static inline u8 __raw_readb(const volatile void __iomem *addr)
{
u8 val;
@@ -61,6 +66,7 @@ static inline u8 __raw_readb(const volatile void __iomem *addr)
return val;
}

+#define __raw_readw __raw_readw
static inline u16 __raw_readw(const volatile void __iomem *addr)
{
u16 val;
@@ -68,6 +74,7 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)
return val;
}

+#define __raw_readl __raw_readl
static inline u32 __raw_readl(const volatile void __iomem *addr)
{
u32 val;
@@ -75,6 +82,7 @@ static inline u32 __raw_readl(const volatile void __iomem *addr)
return val;
}

+#define __raw_readq __raw_readq
static inline u64 __raw_readq(const volatile void __iomem *addr)
{
u64 val;
@@ -124,94 +132,6 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
#define IO_SPACE_LIMIT 0xffff
#define PCI_IOBASE ((void __iomem *)(MODULES_VADDR - SZ_32M))

-static inline u8 inb(unsigned long addr)
-{
- return readb(addr + PCI_IOBASE);
-}
-
-static inline u16 inw(unsigned long addr)
-{
- return readw(addr + PCI_IOBASE);
-}
-
-static inline u32 inl(unsigned long addr)
-{
- return readl(addr + PCI_IOBASE);
-}
-
-static inline void outb(u8 b, unsigned long addr)
-{
- writeb(b, addr + PCI_IOBASE);
-}
-
-static inline void outw(u16 b, unsigned long addr)
-{
- writew(b, addr + PCI_IOBASE);
-}
-
-static inline void outl(u32 b, unsigned long addr)
-{
- writel(b, addr + PCI_IOBASE);
-}
-
-#define inb_p(addr) inb(addr)
-#define inw_p(addr) inw(addr)
-#define inl_p(addr) inl(addr)
-
-#define outb_p(x, addr) outb((x), (addr))
-#define outw_p(x, addr) outw((x), (addr))
-#define outl_p(x, addr) outl((x), (addr))
-
-static inline void insb(unsigned long addr, void *buffer, int count)
-{
- u8 *buf = buffer;
- while (count--)
- *buf++ = __raw_readb(addr + PCI_IOBASE);
-}
-
-static inline void insw(unsigned long addr, void *buffer, int count)
-{
- u16 *buf = buffer;
- while (count--)
- *buf++ = __raw_readw(addr + PCI_IOBASE);
-}
-
-static inline void insl(unsigned long addr, void *buffer, int count)
-{
- u32 *buf = buffer;
- while (count--)
- *buf++ = __raw_readl(addr + PCI_IOBASE);
-}
-
-static inline void outsb(unsigned long addr, const void *buffer, int count)
-{
- const u8 *buf = buffer;
- while (count--)
- __raw_writeb(*buf++, addr + PCI_IOBASE);
-}
-
-static inline void outsw(unsigned long addr, const void *buffer, int count)
-{
- const u16 *buf = buffer;
- while (count--)
- __raw_writew(*buf++, addr + PCI_IOBASE);
-}
-
-static inline void outsl(unsigned long addr, const void *buffer, int count)
-{
- const u32 *buf = buffer;
- while (count--)
- __raw_writel(*buf++, addr + PCI_IOBASE);
-}
-
-#define insb_p(port,to,len) insb(port,to,len)
-#define insw_p(port,to,len) insw(port,to,len)
-#define insl_p(port,to,len) insl(port,to,len)
-
-#define outsb_p(port,from,len) outsb(port,from,len)
-#define outsw_p(port,from,len) outsw(port,from,len)
-#define outsl_p(port,from,len) outsl(port,from,len)
-
/*
* String version of I/O memory access operations.
*/
@@ -235,18 +155,14 @@ extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size);
#define ioremap_wc(addr, size) __ioremap((addr), (size), __pgprot(PROT_NORMAL_NC))
#define iounmap __iounmap

-#define ARCH_HAS_IOREMAP_WC
-#include <asm-generic/iomap.h>
-
/*
- * More restrictive address range checking than the default implementation
- * (PHYS_OFFSET and PHYS_MASK taken into account).
+ * io{read,write}{16,32}be() macros
*/
-#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
-extern int valid_phys_addr_range(unsigned long addr, size_t size);
-extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
+#define ioread16be(p) ({ __u16 __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; })
+#define ioread32be(p) ({ __u32 __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; })

-extern int devmem_is_allowed(unsigned long pfn);
+#define iowrite16be(v,p) ({ __iowmb(); __raw_writew((__force __u16)cpu_to_be16(v), p); })
+#define iowrite32be(v,p) ({ __iowmb(); __raw_writew((__force __u32)cpu_to_be32(v), p); })

/*
* Convert a physical pointer to a virtual kernel pointer for /dev/mem
@@ -259,6 +175,18 @@ extern int devmem_is_allowed(unsigned long pfn);
*/
#define xlate_dev_kmem_ptr(p) p

+#include <asm-generic/io.h>
+
+/*
+ * More restrictive address range checking than the default implementation
+ * (PHYS_OFFSET and PHYS_MASK taken into account).
+ */
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+extern int valid_phys_addr_range(unsigned long addr, size_t size);
+extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
+
+extern int devmem_is_allowed(unsigned long pfn);
+
struct bio_vec;
extern bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
const struct bio_vec *vec2);
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index ccc7087d3c4e..a40a4d7e830f 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -120,11 +120,13 @@ extern phys_addr_t memstart_addr;
* translation for translating DMA addresses. Use the driver
* DMA support - see dma-mapping.h.
*/
+#define virt_to_phys virt_to_phys
static inline phys_addr_t virt_to_phys(const volatile void *x)
{
return __virt_to_phys((unsigned long)(x));
}

+#define phys_to_virt phys_to_virt
static inline void *phys_to_virt(phys_addr_t x)
{
return (void *)(__phys_to_virt(x));
--
2.0.4
Thierry Reding
2014-08-13 10:28:51 UTC
Permalink
From: Thierry Reding <***@nvidia.com>

ARC's asm/io.h includes the asm-generic/io.h which already defines the
PCI_IOBASE variable in exactly the same way, so it can be dropped from
the architecture specific header.

Signed-off-by: Thierry Reding <***@nvidia.com>
---
Changes in v4:
- new patch

arch/arc/include/asm/io.h | 2 --
1 file changed, 2 deletions(-)

diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h
index 334ce7017a18..cabd518cb253 100644
--- a/arch/arc/include/asm/io.h
+++ b/arch/arc/include/asm/io.h
@@ -13,8 +13,6 @@
#include <asm/byteorder.h>
#include <asm/page.h>

-#define PCI_IOBASE ((void __iomem *)0)
-
extern void __iomem *ioremap(unsigned long physaddr, unsigned long size);
extern void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
unsigned long flags);
--
2.0.4
Thierry Reding
2014-08-13 10:28:53 UTC
Permalink
From: Thierry Reding <***@nvidia.com>

The volatile keyword is only necessary in accessors that immediately
perform memory accesses. Wrappers around such accessors, such as the
_memset_io() and _memcpy_{to,from}io() functions don't need them.

Signed-off-by: Thierry Reding <***@nvidia.com>
---
Changes in v4:
- new patch

arch/sparc/include/asm/io_32.h | 18 +++++++-----------
1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/arch/sparc/include/asm/io_32.h b/arch/sparc/include/asm/io_32.h
index 9f532902627c..49267f2575d7 100644
--- a/arch/sparc/include/asm/io_32.h
+++ b/arch/sparc/include/asm/io_32.h
@@ -16,18 +16,15 @@

#include <asm-generic/io.h>

-static inline void _memset_io(volatile void __iomem *dst,
- int c, __kernel_size_t n)
+static inline void _memset_io(void __iomem *dst, int c, __kernel_size_t n)
{
- volatile void __iomem *d = dst;
-
while (n--) {
- writeb(c, d);
- d++;
+ writeb(c, dst);
+ dst++;
}
}

-static inline void _memcpy_fromio(void *dst, const volatile void __iomem *src,
+static inline void _memcpy_fromio(void *dst, const void __iomem *src,
__kernel_size_t n)
{
char *d = dst;
@@ -39,16 +36,15 @@ static inline void _memcpy_fromio(void *dst, const volatile void __iomem *src,
}
}

-static inline void _memcpy_toio(volatile void __iomem *dst, const void *src,
+static inline void _memcpy_toio(void __iomem *dst, const void *src,
__kernel_size_t n)
{
const char *s = src;
- volatile void __iomem *d = dst;

while (n--) {
char tmp = *s++;
- writeb(tmp, d);
- d++;
+ writeb(tmp, dst);
+ dst++;
}
}
--
2.0.4
Thierry Reding
2014-08-13 10:28:57 UTC
Permalink
From: Thierry Reding <***@nvidia.com>

Include the generic I/O header file so that duplicate implementations
can be removed. This will also help to establish consistency across more
architectures regarding which accessors they support.

Signed-off-by: Thierry Reding <***@nvidia.com>
---
Changes in v4:
- define xlate_dev_{kmem,mem}_ptr() before asm-generic/io.h include

Changes in v3:
- override io{read,write}{16,32}be() since the generic ones don't have
the required memory barriers

arch/arm/include/asm/io.h | 75 ++++++++++++++++---------------------------
arch/arm/include/asm/memory.h | 2 ++
2 files changed, 29 insertions(+), 48 deletions(-)

diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 3d23418cbddd..d45cb6b9459a 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -69,6 +69,7 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
* writeback addressing modes as these incur a significant performance
* overhead (the address generation must be emulated in software).
*/
+#define __raw_writew __raw_writew
static inline void __raw_writew(u16 val, volatile void __iomem *addr)
{
asm volatile("strh %1, %0"
@@ -76,6 +77,7 @@ static inline void __raw_writew(u16 val, volatile void __iomem *addr)
: "r" (val));
}

+#define __raw_readw __raw_readw
static inline u16 __raw_readw(const volatile void __iomem *addr)
{
u16 val;
@@ -86,6 +88,7 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)
}
#endif

+#define __raw_writeb __raw_writeb
static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
{
asm volatile("strb %1, %0"
@@ -93,6 +96,7 @@ static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
: "r" (val));
}

+#define __raw_writel __raw_writel
static inline void __raw_writel(u32 val, volatile void __iomem *addr)
{
asm volatile("str %1, %0"
@@ -100,6 +104,7 @@ static inline void __raw_writel(u32 val, volatile void __iomem *addr)
: "r" (val));
}

+#define __raw_readb __raw_readb
static inline u8 __raw_readb(const volatile void __iomem *addr)
{
u8 val;
@@ -109,6 +114,7 @@ static inline u8 __raw_readb(const volatile void __iomem *addr)
return val;
}

+#define __raw_readl __raw_readl
static inline u32 __raw_readl(const volatile void __iomem *addr)
{
u32 val;
@@ -266,20 +272,6 @@ extern int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr);
#define insl(p,d,l) __raw_readsl(__io(p),d,l)
#endif

-#define outb_p(val,port) outb((val),(port))
-#define outw_p(val,port) outw((val),(port))
-#define outl_p(val,port) outl((val),(port))
-#define inb_p(port) inb((port))
-#define inw_p(port) inw((port))
-#define inl_p(port) inl((port))
-
-#define outsb_p(port,from,len) outsb(port,from,len)
-#define outsw_p(port,from,len) outsw(port,from,len)
-#define outsl_p(port,from,len) outsl(port,from,len)
-#define insb_p(port,to,len) insb(port,to,len)
-#define insw_p(port,to,len) insw(port,to,len)
-#define insl_p(port,to,len) insl(port,to,len)
-
/*
* String version of IO memory access ops:
*/
@@ -346,40 +338,38 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
#define iounmap __arm_iounmap

/*
- * io{read,write}{8,16,32} macros
+ * io{read,write}{16,32}be() macros
*/
-#ifndef ioread8
-#define ioread8(p) ({ unsigned int __v = __raw_readb(p); __iormb(); __v; })
-#define ioread16(p) ({ unsigned int __v = le16_to_cpu((__force __le16)__raw_readw(p)); __iormb(); __v; })
-#define ioread32(p) ({ unsigned int __v = le32_to_cpu((__force __le32)__raw_readl(p)); __iormb(); __v; })
-
-#define ioread16be(p) ({ unsigned int __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; })
-#define ioread32be(p) ({ unsigned int __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; })
-
-#define iowrite8(v,p) ({ __iowmb(); __raw_writeb(v, p); })
-#define iowrite16(v,p) ({ __iowmb(); __raw_writew((__force __u16)cpu_to_le16(v), p); })
-#define iowrite32(v,p) ({ __iowmb(); __raw_writel((__force __u32)cpu_to_le32(v), p); })
+#define ioread16be(p) ({ __u16 __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; })
+#define ioread32be(p) ({ __u32 __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; })

-#define iowrite16be(v,p) ({ __iowmb(); __raw_writew((__force __u16)cpu_to_be16(v), p); })
-#define iowrite32be(v,p) ({ __iowmb(); __raw_writel((__force __u32)cpu_to_be32(v), p); })
-
-#define ioread8_rep(p,d,c) __raw_readsb(p,d,c)
-#define ioread16_rep(p,d,c) __raw_readsw(p,d,c)
-#define ioread32_rep(p,d,c) __raw_readsl(p,d,c)
-
-#define iowrite8_rep(p,s,c) __raw_writesb(p,s,c)
-#define iowrite16_rep(p,s,c) __raw_writesw(p,s,c)
-#define iowrite32_rep(p,s,c) __raw_writesl(p,s,c)
+#define iowrite16be(v,p) ({ __iowmb(); __raw_writew((__force __u16)cpu_to_be16(v), p); })
+#define iowrite32be(v,p) ({ __iowmb(); __raw_writew((__force __u32)cpu_to_be32(v), p); })

+#define ioport_map ioport_map
extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
+#define ioport_unmap ioport_unmap
extern void ioport_unmap(void __iomem *addr);
-#endif

struct pci_dev;

+#define pci_iounmap pci_iounmap
extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);

/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
+#include <asm-generic/io.h>
+
+/*
* can the hardware map this into one segment or not, given no other
* constraints.
*/
@@ -401,17 +391,6 @@ extern int devmem_is_allowed(unsigned long pfn);
#endif

/*
- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- * access
- */
-#define xlate_dev_mem_ptr(p) __va(p)
-
-/*
- * Convert a virtual cached pointer to an uncached pointer
- */
-#define xlate_dev_kmem_ptr(p) p
-
-/*
* Register ISA memory and port locations for glibc iopl/inb/outb
* emulation.
*/
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index e731018869a7..1c187611d3c7 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -274,11 +274,13 @@ static inline unsigned long __phys_to_virt(phys_addr_t x)
* translation for translating DMA addresses. Use the driver
* DMA support - see dma-mapping.h.
*/
+#define virt_to_phys virt_to_phys
static inline phys_addr_t virt_to_phys(const volatile void *x)
{
return __virt_to_phys((unsigned long)(x));
}

+#define phys_to_virt phys_to_virt
static inline void *phys_to_virt(phys_addr_t x)
{
return (void *)__phys_to_virt(x);
--
2.0.4
Thierry Reding
2014-08-13 10:28:56 UTC
Permalink
From: Thierry Reding <***@nvidia.com>

Currently driver writers need to use io{read,write}{8,16,32}_rep() when
accessing FIFO registers portably. This is bad for two reasons: it is
inconsistent with how other registers are accessed using the standard
{read,write}{b,w,l}() functions, which can lead to confusion. On some
architectures the io{read,write}*() functions also need to perform some
extra checks to determine whether an address is memory-mapped or refers
to I/O space. Drivers which can be expected to never use I/O can safely
use the {read,write}s{b,w,l,q}(), just like they use their non-string
variants and there's no need for these extra checks.

This patch implements generic versions of readsb(), readsw(), readsl(),
readsq(), writesb(), writesw(), writesl() and writesq(). Variants of
these string functions for I/O accesses (ins*() and outs*() as well as
ioread*_rep() and iowrite*_rep()) are now implemented in terms of the
new functions.

Going forward, {read,write}{,s}{b,w,l,q}() should be used consistently
by drivers for devices that will only ever be memory-mapped and hence
don't need to access I/O space, whereas io{read,write}{8,16,32}_rep()
should be used by drivers for devices that can be either memory-mapped
or I/O-mapped.

While at it, also make sure that any of the functions provided as
fallback for architectures that don't override them can't be overridden
subsequently. At the same time, replace all macros by static inline
functions for better type checking and reorder functions by logical
groups.

Signed-off-by: Thierry Reding <***@nvidia.com>
---
Changes in v4:
- reorder functions to form logical groups (Sam Ravnborg)
- convert functions to static inlines for type checking
- provide {,un}xlate_dev{kmem,mem}_ptr()

Changes in v3:
- allow architectures to override io{read,write}{16,32}be()
- explain the reasons for this change in the commit message

Changes in v2:
- respect IO_SPACE_LIMIT in ioport_map()

include/asm-generic/io.h | 683 ++++++++++++++++++++++++++++++++++++++---------
1 file changed, 555 insertions(+), 128 deletions(-)

diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index 975e1cc75edb..508a57257de5 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -24,250 +24,622 @@
#define mmiowb() do {} while (0)
#endif

-/*****************************************************************************/
/*
- * readX/writeX() are used to access memory mapped devices. On some
- * architectures the memory mapped IO stuff needs to be accessed
- * differently. On the simple architectures, we just read/write the
- * memory location directly.
+ * __raw_{read,write}{b,w,l,q}() access memory in native endianness.
+ *
+ * On some architectures memory mapped IO needs to be accessed differently.
+ * On the simple architectures, we just read/write the memory location
+ * directly.
*/
+
#ifndef __raw_readb
+#define __raw_readb __raw_readb
static inline u8 __raw_readb(const volatile void __iomem *addr)
{
- return *(const volatile u8 __force *) addr;
+ return *(const volatile u8 __force *)addr;
}
#endif

#ifndef __raw_readw
+#define __raw_readw __raw_readw
static inline u16 __raw_readw(const volatile void __iomem *addr)
{
- return *(const volatile u16 __force *) addr;
+ return *(const volatile u16 __force *)addr;
}
#endif

#ifndef __raw_readl
+#define __raw_readl __raw_readl
static inline u32 __raw_readl(const volatile void __iomem *addr)
{
- return *(const volatile u32 __force *) addr;
+ return *(const volatile u32 __force *)addr;
}
#endif

-#define readb __raw_readb
-
-#define readw readw
-static inline u16 readw(const volatile void __iomem *addr)
-{
- return __le16_to_cpu(__raw_readw(addr));
-}
-
-#define readl readl
-static inline u32 readl(const volatile void __iomem *addr)
+#ifdef CONFIG_64BIT
+#ifndef __raw_readq
+#define __raw_readq __raw_readq
+static inline u64 __raw_readq(const volatile void __iomem *addr)
{
- return __le32_to_cpu(__raw_readl(addr));
+ return *(const volatile u64 __force *)addr;
}
+#endif
+#endif /* CONFIG_64BIT */

#ifndef __raw_writeb
-static inline void __raw_writeb(u8 b, volatile void __iomem *addr)
+#define __raw_writeb __raw_writeb
+static inline void __raw_writeb(u8 value, volatile void __iomem *addr)
{
- *(volatile u8 __force *) addr = b;
+ *(volatile u8 __force *)addr = value;
}
#endif

#ifndef __raw_writew
-static inline void __raw_writew(u16 b, volatile void __iomem *addr)
+#define __raw_writew __raw_writew
+static inline void __raw_writew(u16 value, volatile void __iomem *addr)
{
- *(volatile u16 __force *) addr = b;
+ *(volatile u16 __force *)addr = value;
}
#endif

#ifndef __raw_writel
-static inline void __raw_writel(u32 b, volatile void __iomem *addr)
+#define __raw_writel __raw_writel
+static inline void __raw_writel(u32 value, volatile void __iomem *addr)
{
- *(volatile u32 __force *) addr = b;
+ *(volatile u32 __force *)addr = value;
}
#endif

-#define writeb __raw_writeb
-#define writew(b,addr) __raw_writew(__cpu_to_le16(b),addr)
-#define writel(b,addr) __raw_writel(__cpu_to_le32(b),addr)
-
#ifdef CONFIG_64BIT
-#ifndef __raw_readq
-static inline u64 __raw_readq(const volatile void __iomem *addr)
+#ifndef __raw_writeq
+#define __raw_writeq __raw_writeq
+static inline void __raw_writeq(u64 value, volatile void __iomem *addr)
{
- return *(const volatile u64 __force *) addr;
+ *(volatile u64 __force *)addr = value;
}
#endif
+#endif /* CONFIG_64BIT */

-#define readq readq
-static inline u64 readq(const volatile void __iomem *addr)
-{
- return __le64_to_cpu(__raw_readq(addr));
-}
+/*
+ * {read,write}{b,w,l,q}() access little endian memory and return result in
+ * native endianness.
+ */

-#ifndef __raw_writeq
-static inline void __raw_writeq(u64 b, volatile void __iomem *addr)
+#ifndef readb
+#define readb readb
+static inline u8 readb(const void __iomem *addr)
{
- *(volatile u64 __force *) addr = b;
+ return __raw_readb(addr);
}
#endif

-#define writeq(b, addr) __raw_writeq(__cpu_to_le64(b), addr)
-#endif /* CONFIG_64BIT */
-
-#ifndef PCI_IOBASE
-#define PCI_IOBASE ((void __iomem *) 0)
+#ifndef readw
+#define readw readw
+static inline u16 readw(const void __iomem *addr)
+{
+ return __le16_to_cpu(__raw_readw(addr));
+}
#endif

-/*****************************************************************************/
-/*
- * traditional input/output functions
- */
-
-static inline u8 inb(unsigned long addr)
+#ifndef readl
+#define readl readl
+static inline u32 readl(const void __iomem *addr)
{
- return readb(addr + PCI_IOBASE);
+ return __le32_to_cpu(__raw_readl(addr));
}
+#endif

-static inline u16 inw(unsigned long addr)
+#ifdef CONFIG_64BIT
+#ifndef readq
+#define readq readq
+static inline u64 readq(const void __iomem *addr)
{
- return readw(addr + PCI_IOBASE);
+ return __le64_to_cpu(__raw_readq(addr));
}
+#endif
+#endif /* CONFIG_64BIT */

-static inline u32 inl(unsigned long addr)
+#ifndef writeb
+#define writeb writeb
+static inline void writeb(u8 value, void __iomem *addr)
{
- return readl(addr + PCI_IOBASE);
+ __raw_writeb(value, addr);
}
+#endif

-static inline void outb(u8 b, unsigned long addr)
+#ifndef writew
+#define writew writew
+static inline void writew(u16 value, void __iomem *addr)
{
- writeb(b, addr + PCI_IOBASE);
+ __raw_writew(cpu_to_le16(value), addr);
}
+#endif

-static inline void outw(u16 b, unsigned long addr)
+#ifndef writel
+#define writel writel
+static inline void writel(u32 value, void __iomem *addr)
{
- writew(b, addr + PCI_IOBASE);
+ __raw_writel(__cpu_to_le32(value), addr);
}
+#endif

-static inline void outl(u32 b, unsigned long addr)
+#ifdef CONFIG_64BIT
+#ifndef writeq
+#define writeq writeq
+static inline void writeq(u64 value, void __iomem *addr)
{
- writel(b, addr + PCI_IOBASE);
+ __raw_writeq(__cpu_to_le64(value), addr);
}
+#endif
+#endif /* CONFIG_64BIT */

-#define inb_p(addr) inb(addr)
-#define inw_p(addr) inw(addr)
-#define inl_p(addr) inl(addr)
-#define outb_p(x, addr) outb((x), (addr))
-#define outw_p(x, addr) outw((x), (addr))
-#define outl_p(x, addr) outl((x), (addr))
-
-#ifndef insb
-static inline void insb(unsigned long addr, void *buffer, int count)
+/*
+ * {read,write}s{b,w,l,q}() repeatedly access the same memory address in
+ * native endianness in 8-, 16-, 32- or 64-bit chunks (@count times).
+ */
+#ifndef readsb
+#define readsb readsb
+static inline void readsb(const void __iomem *addr, void *buffer,
+ unsigned int count)
{
if (count) {
u8 *buf = buffer;
+
do {
- u8 x = __raw_readb(addr + PCI_IOBASE);
+ u8 x = __raw_readb(addr);
*buf++ = x;
} while (--count);
}
}
#endif

-#ifndef insw
-static inline void insw(unsigned long addr, void *buffer, int count)
+#ifndef readsw
+#define readsw readsw
+static inline void readsw(const void __iomem *addr, void *buffer,
+ unsigned int count)
{
if (count) {
u16 *buf = buffer;
+
do {
- u16 x = __raw_readw(addr + PCI_IOBASE);
+ u16 x = __raw_readw(addr);
*buf++ = x;
} while (--count);
}
}
#endif

-#ifndef insl
-static inline void insl(unsigned long addr, void *buffer, int count)
+#ifndef readsl
+#define readsl readsl
+static inline void readsl(const void __iomem *addr, void *buffer,
+ unsigned int count)
{
if (count) {
u32 *buf = buffer;
+
do {
- u32 x = __raw_readl(addr + PCI_IOBASE);
+ u32 x = __raw_readl(addr);
*buf++ = x;
} while (--count);
}
}
#endif

-#ifndef outsb
-static inline void outsb(unsigned long addr, const void *buffer, int count)
+#ifdef CONFIG_64BIT
+#ifndef readsq
+#define readsq readsq
+static inline void readsq(const void __iomem *addr, void *buffer,
+ unsigned int count)
+{
+ if (count) {
+ u64 *buf = buffer;
+
+ do {
+ u64 x = __raw_readq(addr);
+ *buf++ = x;
+ } while (--count);
+ }
+}
+#endif
+#endif /* CONFIG_64BIT */
+
+#ifndef writesb
+#define writesb writesb
+static inline void writesb(void __iomem *addr, const void *buffer,
+ unsigned int count)
{
if (count) {
const u8 *buf = buffer;
+
do {
- __raw_writeb(*buf++, addr + PCI_IOBASE);
+ __raw_writeb(*buf++, addr);
} while (--count);
}
}
#endif

-#ifndef outsw
-static inline void outsw(unsigned long addr, const void *buffer, int count)
+#ifndef writesw
+#define writesw writesw
+static inline void writesw(void __iomem *addr, const void *buffer,
+ unsigned int count)
{
if (count) {
const u16 *buf = buffer;
+
do {
- __raw_writew(*buf++, addr + PCI_IOBASE);
+ __raw_writew(*buf++, addr);
} while (--count);
}
}
#endif

-#ifndef outsl
-static inline void outsl(unsigned long addr, const void *buffer, int count)
+#ifndef writesl
+#define writesl writesl
+static inline void writesl(void __iomem *addr, const void *buffer,
+ unsigned int count)
{
if (count) {
const u32 *buf = buffer;
+
do {
- __raw_writel(*buf++, addr + PCI_IOBASE);
+ __raw_writel(*buf++, addr);
} while (--count);
}
}
#endif

-#ifndef CONFIG_GENERIC_IOMAP
-#define ioread8(addr) readb(addr)
-#define ioread16(addr) readw(addr)
-#define ioread16be(addr) __be16_to_cpu(__raw_readw(addr))
-#define ioread32(addr) readl(addr)
-#define ioread32be(addr) __be32_to_cpu(__raw_readl(addr))
-
-#define iowrite8(v, addr) writeb((v), (addr))
-#define iowrite16(v, addr) writew((v), (addr))
-#define iowrite16be(v, addr) __raw_writew(__cpu_to_be16(v), addr)
-#define iowrite32(v, addr) writel((v), (addr))
-#define iowrite32be(v, addr) __raw_writel(__cpu_to_be32(v), addr)
-
-#define ioread8_rep(p, dst, count) \
- insb((unsigned long) (p), (dst), (count))
-#define ioread16_rep(p, dst, count) \
- insw((unsigned long) (p), (dst), (count))
-#define ioread32_rep(p, dst, count) \
- insl((unsigned long) (p), (dst), (count))
-
-#define iowrite8_rep(p, src, count) \
- outsb((unsigned long) (p), (src), (count))
-#define iowrite16_rep(p, src, count) \
- outsw((unsigned long) (p), (src), (count))
-#define iowrite32_rep(p, src, count) \
- outsl((unsigned long) (p), (src), (count))
-#endif /* CONFIG_GENERIC_IOMAP */
+#ifdef CONFIG_64BIT
+#ifndef writesq
+#define writesq writesq
+static inline void writesq(void __iomem *addr, const void *buffer,
+ unsigned int count)
+{
+ if (count) {
+ const u64 *buf = buffer;
+
+ do {
+ __raw_writeq(*buf++, addr);
+ } while (--count);
+ }
+}
+#endif
+#endif /* CONFIG_64BIT */
+
+#ifndef PCI_IOBASE
+#define PCI_IOBASE ((void __iomem *)0)
+#endif

#ifndef IO_SPACE_LIMIT
#define IO_SPACE_LIMIT 0xffff
#endif

+/*
+ * {in,out}{b,w,l}() access little endian I/O. {in,out}{b,w,l}_p() can be
+ * implemented on hardware that needs an additional delay for I/O accesses to
+ * take effect.
+ */
+
+#ifndef inb
+#define inb inb
+static inline u8 inb(unsigned long addr)
+{
+ return readb(PCI_IOBASE + addr);
+}
+#endif
+
+#ifndef inw
+#define inw inw
+static inline u16 inw(unsigned long addr)
+{
+ return readw(PCI_IOBASE + addr);
+}
+#endif
+
+#ifndef inl
+#define inl inl
+static inline u32 inl(unsigned long addr)
+{
+ return readl(PCI_IOBASE + addr);
+}
+#endif
+
+#ifndef outb
+#define outb outb
+static inline void outb(u8 value, unsigned long addr)
+{
+ writeb(value, PCI_IOBASE + addr);
+}
+#endif
+
+#ifndef outw
+#define outw outw
+static inline void outw(u16 value, unsigned long addr)
+{
+ writew(value, PCI_IOBASE + addr);
+}
+#endif
+
+#ifndef outl
+#define outl outl
+static inline void outl(u32 value, unsigned long addr)
+{
+ writel(value, PCI_IOBASE + addr);
+}
+#endif
+
+#ifndef inb_p
+#define inb_p inb_p
+static inline u8 inb_p(unsigned long addr)
+{
+ return inb(addr);
+}
+#endif
+
+#ifndef inw_p
+#define inw_p inw_p
+static inline u16 inw_p(unsigned long addr)
+{
+ return inw(addr);
+}
+#endif
+
+#ifndef inl_p
+#define inl_p inl_p
+static inline u32 inl_p(unsigned long addr)
+{
+ return inl(addr);
+}
+#endif
+
+#ifndef outb_p
+#define outb_p outb_p
+static inline void outb_p(u8 value, unsigned long addr)
+{
+ outb(value, addr);
+}
+#endif
+
+#ifndef outw_p
+#define outw_p outw_p
+static inline void outw_p(u16 value, unsigned long addr)
+{
+ outw(value, addr);
+}
+#endif
+
+#ifndef outl_p
+#define outl_p outl_p
+static inline void outl_p(u32 value, unsigned long addr)
+{
+ outl(value, addr);
+}
+#endif
+
+/*
+ * {in,out}s{b,w,l}{,_p}() are variants of the above that repeatedly access a
+ * single I/O port multiple times.
+ */
+
+#ifndef insb
+#define insb insb
+static inline void insb(unsigned long addr, void *buffer, unsigned int count)
+{
+ readsb(PCI_IOBASE + addr, buffer, count);
+}
+#endif
+
+#ifndef insw
+#define insw insw
+static inline void insw(unsigned long addr, void *buffer, unsigned int count)
+{
+ readsw(PCI_IOBASE + addr, buffer, count);
+}
+#endif
+
+#ifndef insl
+#define insl insl
+static inline void insl(unsigned long addr, void *buffer, unsigned int count)
+{
+ readsl(PCI_IOBASE + addr, buffer, count);
+}
+#endif
+
+#ifndef outsb
+#define outsb outsb
+static inline void outsb(unsigned long addr, const void *buffer,
+ unsigned int count)
+{
+ writesb(PCI_IOBASE + addr, buffer, count);
+}
+#endif
+
+#ifndef outsw
+#define outsw outsw
+static inline void outsw(unsigned long addr, const void *buffer,
+ unsigned int count)
+{
+ writesw(PCI_IOBASE + addr, buffer, count);
+}
+#endif
+
+#ifndef outsl
+#define outsl outsl
+static inline void outsl(unsigned long addr, const void *buffer,
+ unsigned int count)
+{
+ writesl(PCI_IOBASE + addr, buffer, count);
+}
+#endif
+
+#ifndef insb_p
+#define insb_p insb_p
+static inline void insb_p(unsigned long addr, void *buffer, unsigned int count)
+{
+ insb(addr, buffer, count);
+}
+#endif
+
+#ifndef insw_p
+#define insw_p insw_p
+static inline void insw_p(unsigned long addr, void *buffer, unsigned int count)
+{
+ insw(addr, buffer, count);
+}
+#endif
+
+#ifndef insl_p
+#define insl_p insl_p
+static inline void insl_p(unsigned long addr, void *buffer, unsigned int count)
+{
+ insl(addr, buffer, count);
+}
+#endif
+
+#ifndef outsb_p
+#define outsb_p outsb_p
+static inline void outsb_p(unsigned long addr, const void *buffer,
+ unsigned int count)
+{
+ outsb(addr, buffer, count);
+}
+#endif
+
+#ifndef outsw_p
+#define outsw_p outsw_p
+static inline void outsw_p(unsigned long addr, const void *buffer,
+ unsigned int count)
+{
+ outsw(addr, buffer, count);
+}
+#endif
+
+#ifndef outsl_p
+#define outsl_p outsl_p
+static inline void outsl_p(unsigned long addr, const void *buffer,
+ unsigned int count)
+{
+ outsl(addr, buffer, count);
+}
+#endif
+
+#ifndef CONFIG_GENERIC_IOMAP
+static inline u8 ioread8(const void __iomem *addr)
+{
+ return readb(addr);
+}
+
+static inline u16 ioread16(const void __iomem *addr)
+{
+ return readw(addr);
+}
+
+static inline u32 ioread32(const void __iomem *addr)
+{
+ return readl(addr);
+}
+
+static inline void iowrite8(u8 value, void __iomem *addr)
+{
+ writeb(value, addr);
+}
+
+static inline void iowrite16(u16 value, void __iomem *addr)
+{
+ writew(value, addr);
+}
+
+static inline void iowrite32(u32 value, void __iomem *addr)
+{
+ writel(value, addr);
+}
+
+#ifndef ioread16be
+#define ioread16be ioread16be
+static inline u16 ioread16be(const void __iomem *addr)
+{
+ return __be16_to_cpu(__raw_readw(addr));
+}
+#endif
+
+#ifndef ioread32be
+#define ioread32be ioread32be
+static inline u32 ioread32be(const void __iomem *addr)
+{
+ return __be32_to_cpu(__raw_readl(addr));
+}
+#endif
+
+#ifndef iowrite16be
+#define iowrite16be iowrite16be
+static inline void iowrite16be(u16 value, void __iomem *addr)
+{
+ __raw_writew(__cpu_to_be16(value), addr);
+}
+#endif
+
+#ifndef iowrite32be
+#define iowrite32be iowrite32be
+static inline void iowrite32be(u32 value, void __iomem *addr)
+{
+ __raw_writel(__cpu_to_be32(value), addr);
+}
+#endif
+
+#ifndef ioread8_rep
+#define ioread8_rep ioread8_rep
+static inline void ioread8_rep(const void __iomem *addr, void *buffer,
+ unsigned int count)
+{
+ readsb(addr, buffer, count);
+}
+#endif
+
+#ifndef ioread16_rep
+#define ioread16_rep ioread16_rep
+static inline void ioread16_rep(const void __iomem *addr, void *buffer,
+ unsigned int count)
+{
+ readsw(addr, buffer, count);
+}
+#endif
+
+#ifndef ioread32_rep
+#define ioread32_rep ioread32_rep
+static inline void ioread32_rep(const void __iomem *addr, void *buffer,
+ unsigned int count)
+{
+ readsl(addr, buffer, count);
+}
+#endif
+
+#ifndef iowrite8_rep
+#define iowrite8_rep iowrite8_rep
+static inline void iowrite8_rep(void __iomem *addr, const void *buffer,
+ unsigned int count)
+{
+ writesb(addr, buffer, count);
+}
+#endif
+
+#ifndef iowrite16_rep
+#define iowrite16_rep iowrite16_rep
+static inline void iowrite16_rep(void __iomem *addr, const void *buffer,
+ unsigned int count)
+{
+ writesw(addr, buffer, count);
+}
+#endif
+
+#ifndef iowrite32_rep
+#define iowrite32_rep iowrite32_rep
+static inline void iowrite32_rep(void __iomem *addr, const void *buffer,
+ unsigned int count)
+{
+ writesl(addr, buffer, count);
+}
+#endif
+#endif /* CONFIG_GENERIC_IOMAP */
+
#ifdef __KERNEL__

#include <linux/vmalloc.h>
@@ -278,6 +650,7 @@ struct pci_dev;
extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);

#ifndef pci_iounmap
+#define pci_iounmap pci_iounmap
static inline void pci_iounmap(struct pci_dev *dev, void __iomem *p)
{
}
@@ -289,11 +662,15 @@ static inline void pci_iounmap(struct pci_dev *dev, void __iomem *p)
* These are pretty trivial
*/
#ifndef virt_to_phys
+#define virt_to_phys virt_to_phys
static inline unsigned long virt_to_phys(volatile void *address)
{
return __pa((unsigned long)address);
}
+#endif

+#ifndef phys_to_virt
+#define phys_to_virt phys_to_virt
static inline void *phys_to_virt(unsigned long address)
{
return __va(address);
@@ -306,20 +683,33 @@ static inline void *phys_to_virt(unsigned long address)
* This implementation is for the no-MMU case only... if you have an MMU
* you'll need to provide your own definitions.
*/
+
#ifndef CONFIG_MMU
-static inline void __iomem *ioremap(phys_addr_t offset, unsigned long size)
+static inline void __iomem *ioremap(phys_addr_t offset, size_t size)
{
- return (void __iomem*) (unsigned long)offset;
+ return (void __iomem *)(unsigned long)offset;
}

-#define __ioremap(offset, size, flags) ioremap(offset, size)
+static inline void __iomem *__ioremap(phys_addr_t offset, size_t size,
+ unsigned long flags)
+{
+ return ioremap(offset, size);
+}

#ifndef ioremap_nocache
-#define ioremap_nocache ioremap
+#define ioremap_nocache ioremap_nocache
+static inline void __iomem *ioremap_nocache(phys_addr_t offset, size_t size)
+{
+ return ioremap(offset, size);
+}
#endif

#ifndef ioremap_wc
-#define ioremap_wc ioremap_nocache
+#define ioremap_wc ioremap_wc
+static inline void __iomem *ioremap_wc(phys_addr_t offset, size_t size)
+{
+ return ioremap_nocache(offset, size);
+}
#endif

static inline void iounmap(void __iomem *addr)
@@ -329,14 +719,20 @@ static inline void iounmap(void __iomem *addr)

#ifdef CONFIG_HAS_IOPORT_MAP
#ifndef CONFIG_GENERIC_IOMAP
+#ifndef ioport_map
+#define ioport_map ioport_map
static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
{
- return (void __iomem *) port;
+ return PCI_IOBASE + (port & IO_SPACE_LIMIT);
}
+#endif

+#ifndef ioport_unmap
+#define ioport_unmap ioport_unmap
static inline void ioport_unmap(void __iomem *p)
{
}
+#endif
#else /* CONFIG_GENERIC_IOMAP */
extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
extern void ioport_unmap(void __iomem *p);
@@ -344,35 +740,66 @@ extern void ioport_unmap(void __iomem *p);
#endif /* CONFIG_HAS_IOPORT_MAP */

#ifndef xlate_dev_kmem_ptr
-#define xlate_dev_kmem_ptr(p) p
+#define xlate_dev_kmem_ptr xlate_dev_kmem_ptr
+static inline void *xlate_dev_kmem_ptr(void *addr)
+{
+ return addr;
+}
#endif
+
#ifndef xlate_dev_mem_ptr
-#define xlate_dev_mem_ptr(p) __va(p)
+#define xlate_dev_mem_ptr xlate_dev_mem_ptr
+static inline void *xlate_dev_mem_ptr(phys_addr_t addr)
+{
+ return __va(addr);
+}
+#endif
+
+#ifndef unxlate_dev_mem_ptr
+#define unxlate_dev_mem_ptr unxlate_dev_mem_ptr
+static inline void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
+{
+}
#endif

#ifdef CONFIG_VIRT_TO_BUS
#ifndef virt_to_bus
-static inline unsigned long virt_to_bus(volatile void *address)
+static inline unsigned long virt_to_bus(void *address)
{
- return ((unsigned long) address);
+ return (unsigned long)address;
}

static inline void *bus_to_virt(unsigned long address)
{
- return (void *) address;
+ return (void *)address;
}
#endif
#endif

#ifndef memset_io
-#define memset_io(a, b, c) memset(__io_virt(a), (b), (c))
+#define memset_io memset_io
+static inline void memset_io(void __iomem *addr, int value, size_t size)
+{
+ memset(__io_virt(addr), value, size);
+}
#endif

#ifndef memcpy_fromio
-#define memcpy_fromio(a, b, c) memcpy((a), __io_virt(b), (c))
+#define memcpy_fromio memcpy_fromio
+static inline void memcpy_fromio(void *buffer, const void __iomem *addr,
+ size_t size)
+{
+ memcpy(buffer, __io_virt(addr), size);
+}
#endif
+
#ifndef memcpy_toio
-#define memcpy_toio(a, b, c) memcpy(__io_virt(a), (b), (c))
+#define memcpy_toio memcpy_toio
+static inline void memcpy_toio(void __iomem *addr, const void *buffer,
+ size_t size)
+{
+ memcpy(__io_virt(addr), buffer, size);
+}
#endif

#endif /* __KERNEL__ */
--
2.0.4
Geert Uytterhoeven
2014-09-29 08:54:34 UTC
Permalink
On Wed, Aug 13, 2014 at 12:28 PM, Thierry Reding
Post by Thierry Reding
#ifndef memset_io
-#define memset_io(a, b, c) memset(__io_virt(a), (b), (c))
+#define memset_io memset_io
+static inline void memset_io(void __iomem *addr, int value, size_t size)
+{
+ memset(__io_virt(addr), value, size);
+}
#endif
xtensa/allmodconfig:

include/asm-generic/io.h:820:2: error: implicit declaration of
function 'memset' [-Werror=implicit-function-declaration]
include/asm-generic/io.h:829:2: error: implicit declaration of
function 'memcpy' [-Werror=implicit-function-declaration]
arch/xtensa/include/asm/string.h:110:14: error: conflicting types for 'memset'
arch/xtensa/include/asm/string.h:113:14: error: conflicting types for 'memcpy'

http://kisskb.ellerman.id.au/kisskb/buildresult/12028900/

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ***@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
--
To unsubscribe from this list: send the line "unsubscribe sparclinux" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Thierry Reding
2014-09-29 08:59:09 UTC
Permalink
Post by Richard Weinberger
On Wed, Aug 13, 2014 at 12:28 PM, Thierry Reding
Post by Thierry Reding
#ifndef memset_io
-#define memset_io(a, b, c) memset(__io_virt(a), (b), (c))
+#define memset_io memset_io
+static inline void memset_io(void __iomem *addr, int value, size_t size)
+{
+ memset(__io_virt(addr), value, size);
+}
#endif
include/asm-generic/io.h:820:2: error: implicit declaration of
function 'memset' [-Werror=implicit-function-declaration]
include/asm-generic/io.h:829:2: error: implicit declaration of
function 'memcpy' [-Werror=implicit-function-declaration]
arch/xtensa/include/asm/string.h:110:14: error: conflicting types for 'memset'
arch/xtensa/include/asm/string.h:113:14: error: conflicting types for 'memcpy'
http://kisskb.ellerman.id.au/kisskb/buildresult/12028900/
I think this can be fixed by including linux/string.h for memset() and
memcpy() in include/asm-generic/io.h.

Thanks,
Thierry
Max Filippov
2014-09-30 10:22:18 UTC
Permalink
Hi Thierry,

On Mon, Sep 29, 2014 at 12:59 PM, Thierry Reding
Post by Thierry Reding
Post by Richard Weinberger
On Wed, Aug 13, 2014 at 12:28 PM, Thierry Reding
Post by Thierry Reding
#ifndef memset_io
-#define memset_io(a, b, c) memset(__io_virt(a), (b), (c))
+#define memset_io memset_io
+static inline void memset_io(void __iomem *addr, int value, size_t size)
+{
+ memset(__io_virt(addr), value, size);
+}
#endif
include/asm-generic/io.h:820:2: error: implicit declaration of
function 'memset' [-Werror=implicit-function-declaration]
include/asm-generic/io.h:829:2: error: implicit declaration of
function 'memcpy' [-Werror=implicit-function-declaration]
arch/xtensa/include/asm/string.h:110:14: error: conflicting types for 'memset'
arch/xtensa/include/asm/string.h:113:14: error: conflicting types for 'memcpy'
http://kisskb.ellerman.id.au/kisskb/buildresult/12028900/
I think this can be fixed by including linux/string.h for memset() and
memcpy() in include/asm-generic/io.h.
Will you send that fix or do I need to do it?
--
Thanks.
-- Max
--
To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Max Filippov
2014-09-30 10:26:20 UTC
Permalink
Post by Max Filippov
Hi Thierry,
Post by Thierry Reding
I think this can be fixed by including linux/string.h for memset() and
memcpy() in include/asm-generic/io.h.
Will you send that fix or do I need to do it?
Never mind, found that it's fixed in today's next.
--
Thanks.
-- Max
Arnd Bergmann
2014-09-30 10:39:37 UTC
Permalink
Post by Max Filippov
Post by Max Filippov
Hi Thierry,
Post by Thierry Reding
I think this can be fixed by including linux/string.h for memset() and
memcpy() in include/asm-generic/io.h.
Will you send that fix or do I need to do it?
Never mind, found that it's fixed in today's next.
Actually I just backed out the original patches, the problem is still
there in my tree.

Arnd
Thierry Reding
2014-09-30 10:51:19 UTC
Permalink
Post by Arnd Bergmann
Post by Max Filippov
Post by Max Filippov
Hi Thierry,
Post by Thierry Reding
I think this can be fixed by including linux/string.h for memset() and
memcpy() in include/asm-generic/io.h.
Will you send that fix or do I need to do it?
Never mind, found that it's fixed in today's next.
Actually I just backed out the original patches, the problem is still
there in my tree.
I'll integrate the fix for this in my series, so this should be gone
with v5.

Thierry

Thierry Reding
2014-08-13 10:28:55 UTC
Permalink
From: Thierry Reding <***@nvidia.com>

The xlate_dev_{kmem,mem}_ptr() functions take either a physical address
or a kernel virtual address, so data types should be phys_addr_t and
void *. They both return a kernel virtual address which is only ever
used in calls to copy_{from,to}_user(), so make variables that store it
void * rather than char * for consistency.

Also only define a weak unxlate_dev_mem_ptr() function if architectures
haven't overridden them in the asm/io.h header file.

Signed-off-by: Thierry Reding <***@nvidia.com>
---
Changes in v4:
- new patch

arch/s390/include/asm/io.h | 5 +++--
arch/s390/mm/maccess.c | 4 ++--
arch/x86/include/asm/io.h | 4 ++--
arch/x86/mm/ioremap.c | 4 ++--
drivers/char/mem.c | 13 ++++++++-----
5 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/arch/s390/include/asm/io.h b/arch/s390/include/asm/io.h
index cd6b9ee7b69c..d22c2eeae78f 100644
--- a/arch/s390/include/asm/io.h
+++ b/arch/s390/include/asm/io.h
@@ -13,9 +13,10 @@
#include <asm/page.h>
#include <asm/pci_io.h>

-void *xlate_dev_mem_ptr(unsigned long phys);
#define xlate_dev_mem_ptr xlate_dev_mem_ptr
-void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
+void *xlate_dev_mem_ptr(phys_addr_t phys);
+#define unxlate_dev_mem_ptr unxlate_dev_mem_ptr
+void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr);

/*
* Convert a virtual cached pointer to an uncached pointer
diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c
index 2a2e35416d2f..2eb34bdfc613 100644
--- a/arch/s390/mm/maccess.c
+++ b/arch/s390/mm/maccess.c
@@ -176,7 +176,7 @@ static int is_swapped(unsigned long addr)
* For swapped prefix pages a new buffer is returned that contains a copy of
* the absolute memory. The buffer size is maximum one page large.
*/
-void *xlate_dev_mem_ptr(unsigned long addr)
+void *xlate_dev_mem_ptr(phys_addr_t addr)
{
void *bounce = (void *) addr;
unsigned long size;
@@ -197,7 +197,7 @@ void *xlate_dev_mem_ptr(unsigned long addr)
/*
* Free converted buffer for /dev/mem access (if necessary)
*/
-void unxlate_dev_mem_ptr(unsigned long addr, void *buf)
+void unxlate_dev_mem_ptr(phys_addr_t addr, void *buf)
{
if ((void *) addr != buf)
free_page((unsigned long) buf);
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index b8237d8a1e0c..ae2b593e7c6e 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -310,8 +310,8 @@ BUILDIO(b, b, char)
BUILDIO(w, w, short)
BUILDIO(l, , int)

-extern void *xlate_dev_mem_ptr(unsigned long phys);
-extern void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
+extern void *xlate_dev_mem_ptr(phys_addr_t phys);
+extern void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr);

extern int ioremap_change_attr(unsigned long vaddr, unsigned long size,
unsigned long prot_val);
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index baff1da354e0..6d9cc45123e5 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -315,7 +315,7 @@ EXPORT_SYMBOL(iounmap);
* Convert a physical pointer to a virtual kernel pointer for /dev/mem
* access
*/
-void *xlate_dev_mem_ptr(unsigned long phys)
+void *xlate_dev_mem_ptr(phys_addr_t phys)
{
void *addr;
unsigned long start = phys & PAGE_MASK;
@@ -331,7 +331,7 @@ void *xlate_dev_mem_ptr(unsigned long phys)
return addr;
}

-void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
+void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
{
if (page_is_ram(phys >> PAGE_SHIFT))
return;
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 917403fe10da..a304e8a6ebf2 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -84,9 +84,12 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size)
}
#endif

-void __weak unxlate_dev_mem_ptr(unsigned long phys, void *addr)
+#ifndef unxlate_dev_mem_ptr
+#define unxlate_dev_mem_ptr unxlate_dev_mem_ptr
+void __weak unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
{
}
+#endif

/*
* This funcion reads the *physical* memory. The f_pos points directly to the
@@ -97,7 +100,7 @@ static ssize_t read_mem(struct file *file, char __user *buf,
{
phys_addr_t p = *ppos;
ssize_t read, sz;
- char *ptr;
+ void *ptr;

if (p != *ppos)
return 0;
@@ -400,7 +403,7 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
* uncached, then it must also be accessed uncached
* by the kernel or data corruption may occur
*/
- kbuf = xlate_dev_kmem_ptr((char *)p);
+ kbuf = xlate_dev_kmem_ptr((void *)p);

if (copy_to_user(buf, kbuf, sz))
return -EFAULT;
@@ -461,7 +464,7 @@ static ssize_t do_write_kmem(unsigned long p, const char __user *buf,
#endif

while (count > 0) {
- char *ptr;
+ void *ptr;

sz = size_inside_page(p, count);

@@ -470,7 +473,7 @@ static ssize_t do_write_kmem(unsigned long p, const char __user *buf,
* it must also be accessed uncached by the kernel or data
* corruption may occur.
*/
- ptr = xlate_dev_kmem_ptr((char *)p);
+ ptr = xlate_dev_kmem_ptr((void *)p);

copied = copy_from_user(ptr, buf, sz);
if (copied) {
--
2.0.4
Thierry Reding
2014-08-25 11:26:33 UTC
Permalink
Post by Thierry Reding
Hi,
Here is the fourth version of a series that started out as an attempt to
provide string versions of the read*() and write*() accessors to more
architectures so that drivers can use them portably. The series has
since evolved into a more general cleanup of asm-generic/io.h and the
functions defined therein.
Patch 1 is trivial and removes a redundant redefinition of PCI_IOBASE
from the asm/io.h header on ARC. Patches 2 and 3 remove unnecessary
volatile keywoards from some functions, which is a prerequisite to clean
up some of the functions in subsequent patches.
The xlate_dev_{kmem,mem}_ptr() functions are used to map memory when the
/dev/mem device is accessed. Patches 4 and 5 use more consistent data
types for these functions, which will get a "standard" prototype in the
asm-generic/io.h header in a subsequent patch.
Patch 6 is the bulk of this series. It implements the string variants of
the read*() and write*() accessors and cleans up various other parts of
the asm-generic/io.h header file. Macros are converted to static inline
functions for better type checking. Overriding generic implementations
in architectures is handled more consistently.
Patches 7 and 8, finally, make use of the asm-generic/io.h header on the
32-bit and 64-bit ARM architectures.
This is compile- and runtime-tested on 32-bit and 64-bit ARM and compile
tested on IA64, Microblaze, s390, SPARC, x86 and Xtensa. For ARC,
Blackfin, Metag, OpenRISC, Score and Unicore32 which also use
asm-generic/io.h I couldn't find or build a cross-compiler that would
run on my system. But by code inspection they shouldn't break with this
patch.
To ensure bisectability I built multi_v7_defconfig on 32-bit ARM and the
defconfig for 64-bit ARM, IA64, Microblaze, s390, SPARC, x86 and Xtensa
after each commit and verified that the series does not introduce any
build errors or warnings.
Provided there are no objections to the patches there's still the matter
of how to merge them. Patch 6 depends on patches 1-5 to avoid warnings
and/or errors during the build. Patches 7 and 8 depend on patch 6. In my
opinion it doesn't make much sense to split them up, so I guess we'll
need a volunteer to take them all into one tree. Ideally that tree would
feed into linux-next so that we can get as much build and test-coverage
as possible during the 3.17 release cycle so that these patches can go
into 3.18.
Arnd, I'm opportunistically sending this To: you in the hopes that you
can take it into your asm-generic tree which seems like the best fit for
this.
Thierry
ARC: Remove redundant PCI_IOBASE declaration
serial: sunzilog: Remove unnecessary volatile keyword
sparc: Remove unnecessary volatile usage
[IA64] Change xlate_dev_{kmem,mem}_ptr() prototypes
/dev/mem: Use more consistent data types
asm-generic/io.h: Implement generic {read,write}s*()
ARM: Use include/asm-generic/io.h
arm64: Use include/asm-generic/io.h
arch/arc/include/asm/io.h | 2 -
arch/arm/include/asm/io.h | 75 ++---
arch/arm/include/asm/memory.h | 2 +
arch/arm64/Kconfig | 1 -
arch/arm64/include/asm/io.h | 122 ++-----
arch/arm64/include/asm/memory.h | 2 +
arch/ia64/include/asm/uaccess.h | 16 +-
arch/s390/include/asm/io.h | 5 +-
arch/s390/mm/maccess.c | 4 +-
arch/sparc/include/asm/io_32.h | 18 +-
arch/x86/include/asm/io.h | 4 +-
arch/x86/mm/ioremap.c | 4 +-
drivers/char/mem.c | 13 +-
drivers/tty/serial/sunzilog.h | 8 +-
include/asm-generic/io.h | 683 ++++++++++++++++++++++++++++++++--------
15 files changed, 647 insertions(+), 312 deletions(-)
Arnd, do you think this looks good to take for test-driving in
linux-next?

Thierry
Thierry Reding
2014-09-24 06:04:21 UTC
Permalink
Post by Thierry Reding
Post by Thierry Reding
Hi,
Here is the fourth version of a series that started out as an attempt to
provide string versions of the read*() and write*() accessors to more
architectures so that drivers can use them portably. The series has
since evolved into a more general cleanup of asm-generic/io.h and the
functions defined therein.
Patch 1 is trivial and removes a redundant redefinition of PCI_IOBASE
from the asm/io.h header on ARC. Patches 2 and 3 remove unnecessary
volatile keywoards from some functions, which is a prerequisite to clean
up some of the functions in subsequent patches.
The xlate_dev_{kmem,mem}_ptr() functions are used to map memory when the
/dev/mem device is accessed. Patches 4 and 5 use more consistent data
types for these functions, which will get a "standard" prototype in the
asm-generic/io.h header in a subsequent patch.
Patch 6 is the bulk of this series. It implements the string variants of
the read*() and write*() accessors and cleans up various other parts of
the asm-generic/io.h header file. Macros are converted to static inline
functions for better type checking. Overriding generic implementations
in architectures is handled more consistently.
Patches 7 and 8, finally, make use of the asm-generic/io.h header on the
32-bit and 64-bit ARM architectures.
This is compile- and runtime-tested on 32-bit and 64-bit ARM and compile
tested on IA64, Microblaze, s390, SPARC, x86 and Xtensa. For ARC,
Blackfin, Metag, OpenRISC, Score and Unicore32 which also use
asm-generic/io.h I couldn't find or build a cross-compiler that would
run on my system. But by code inspection they shouldn't break with this
patch.
To ensure bisectability I built multi_v7_defconfig on 32-bit ARM and the
defconfig for 64-bit ARM, IA64, Microblaze, s390, SPARC, x86 and Xtensa
after each commit and verified that the series does not introduce any
build errors or warnings.
Provided there are no objections to the patches there's still the matter
of how to merge them. Patch 6 depends on patches 1-5 to avoid warnings
and/or errors during the build. Patches 7 and 8 depend on patch 6. In my
opinion it doesn't make much sense to split them up, so I guess we'll
need a volunteer to take them all into one tree. Ideally that tree would
feed into linux-next so that we can get as much build and test-coverage
as possible during the 3.17 release cycle so that these patches can go
into 3.18.
Arnd, I'm opportunistically sending this To: you in the hopes that you
can take it into your asm-generic tree which seems like the best fit for
this.
Thierry
ARC: Remove redundant PCI_IOBASE declaration
serial: sunzilog: Remove unnecessary volatile keyword
sparc: Remove unnecessary volatile usage
[IA64] Change xlate_dev_{kmem,mem}_ptr() prototypes
/dev/mem: Use more consistent data types
asm-generic/io.h: Implement generic {read,write}s*()
ARM: Use include/asm-generic/io.h
arm64: Use include/asm-generic/io.h
arch/arc/include/asm/io.h | 2 -
arch/arm/include/asm/io.h | 75 ++---
arch/arm/include/asm/memory.h | 2 +
arch/arm64/Kconfig | 1 -
arch/arm64/include/asm/io.h | 122 ++-----
arch/arm64/include/asm/memory.h | 2 +
arch/ia64/include/asm/uaccess.h | 16 +-
arch/s390/include/asm/io.h | 5 +-
arch/s390/mm/maccess.c | 4 +-
arch/sparc/include/asm/io_32.h | 18 +-
arch/x86/include/asm/io.h | 4 +-
arch/x86/mm/ioremap.c | 4 +-
drivers/char/mem.c | 13 +-
drivers/tty/serial/sunzilog.h | 8 +-
include/asm-generic/io.h | 683 ++++++++++++++++++++++++++++++++--------
15 files changed, 647 insertions(+), 312 deletions(-)
Arnd, do you think this looks good to take for test-driving in
linux-next?
Ping?

Thierry
Arnd Bergmann
2014-09-25 14:56:53 UTC
Permalink
Post by Thierry Reding
Arnd, do you think this looks good to take for test-driving in
linux-next?
Ping?
I've put it all into the asm-generic tree, and Will's patches on top.
Unless I get complaints, I plan to submit them all for 3.18.

Arnd
Richard Weinberger
2014-08-25 11:53:30 UTC
Permalink
On Wed, Aug 13, 2014 at 12:28 PM, Thierry Reding
Post by Thierry Reding
Hi,
Here is the fourth version of a series that started out as an attempt to
provide string versions of the read*() and write*() accessors to more
architectures so that drivers can use them portably. The series has
since evolved into a more general cleanup of asm-generic/io.h and the
functions defined therein.
Patch 1 is trivial and removes a redundant redefinition of PCI_IOBASE
from the asm/io.h header on ARC. Patches 2 and 3 remove unnecessary
volatile keywoards from some functions, which is a prerequisite to clean
up some of the functions in subsequent patches.
The xlate_dev_{kmem,mem}_ptr() functions are used to map memory when the
/dev/mem device is accessed. Patches 4 and 5 use more consistent data
types for these functions, which will get a "standard" prototype in the
asm-generic/io.h header in a subsequent patch.
Patch 6 is the bulk of this series. It implements the string variants of
the read*() and write*() accessors and cleans up various other parts of
the asm-generic/io.h header file. Macros are converted to static inline
functions for better type checking. Overriding generic implementations
in architectures is handled more consistently.
Patches 7 and 8, finally, make use of the asm-generic/io.h header on the
32-bit and 64-bit ARM architectures.
This is compile- and runtime-tested on 32-bit and 64-bit ARM and compile
tested on IA64, Microblaze, s390, SPARC, x86 and Xtensa. For ARC,
Blackfin, Metag, OpenRISC, Score and Unicore32 which also use
asm-generic/io.h I couldn't find or build a cross-compiler that would
run on my system. But by code inspection they shouldn't break with this
patch.
To ensure bisectability I built multi_v7_defconfig on 32-bit ARM and the
defconfig for 64-bit ARM, IA64, Microblaze, s390, SPARC, x86 and Xtensa
after each commit and verified that the series does not introduce any
build errors or warnings.
Provided there are no objections to the patches there's still the matter
of how to merge them. Patch 6 depends on patches 1-5 to avoid warnings
and/or errors during the build. Patches 7 and 8 depend on patch 6. In my
opinion it doesn't make much sense to split them up, so I guess we'll
need a volunteer to take them all into one tree. Ideally that tree would
feed into linux-next so that we can get as much build and test-coverage
as possible during the 3.17 release cycle so that these patches can go
into 3.18.
Arnd, I'm opportunistically sending this To: you in the hopes that you
can take it into your asm-generic tree which seems like the best fit for
this.
Do you have a git tree for that?
Would be nice for testing UML, it depends also on generic io.
--
Thanks,
//richard
Thierry Reding
2014-08-25 12:27:35 UTC
Permalink
Post by Richard Weinberger
On Wed, Aug 13, 2014 at 12:28 PM, Thierry Reding
Post by Thierry Reding
Hi,
Here is the fourth version of a series that started out as an attempt to
provide string versions of the read*() and write*() accessors to more
architectures so that drivers can use them portably. The series has
since evolved into a more general cleanup of asm-generic/io.h and the
functions defined therein.
Patch 1 is trivial and removes a redundant redefinition of PCI_IOBASE
from the asm/io.h header on ARC. Patches 2 and 3 remove unnecessary
volatile keywoards from some functions, which is a prerequisite to clean
up some of the functions in subsequent patches.
The xlate_dev_{kmem,mem}_ptr() functions are used to map memory when the
/dev/mem device is accessed. Patches 4 and 5 use more consistent data
types for these functions, which will get a "standard" prototype in the
asm-generic/io.h header in a subsequent patch.
Patch 6 is the bulk of this series. It implements the string variants of
the read*() and write*() accessors and cleans up various other parts of
the asm-generic/io.h header file. Macros are converted to static inline
functions for better type checking. Overriding generic implementations
in architectures is handled more consistently.
Patches 7 and 8, finally, make use of the asm-generic/io.h header on the
32-bit and 64-bit ARM architectures.
This is compile- and runtime-tested on 32-bit and 64-bit ARM and compile
tested on IA64, Microblaze, s390, SPARC, x86 and Xtensa. For ARC,
Blackfin, Metag, OpenRISC, Score and Unicore32 which also use
asm-generic/io.h I couldn't find or build a cross-compiler that would
run on my system. But by code inspection they shouldn't break with this
patch.
To ensure bisectability I built multi_v7_defconfig on 32-bit ARM and the
defconfig for 64-bit ARM, IA64, Microblaze, s390, SPARC, x86 and Xtensa
after each commit and verified that the series does not introduce any
build errors or warnings.
Provided there are no objections to the patches there's still the matter
of how to merge them. Patch 6 depends on patches 1-5 to avoid warnings
and/or errors during the build. Patches 7 and 8 depend on patch 6. In my
opinion it doesn't make much sense to split them up, so I guess we'll
need a volunteer to take them all into one tree. Ideally that tree would
feed into linux-next so that we can get as much build and test-coverage
as possible during the 3.17 release cycle so that these patches can go
into 3.18.
Arnd, I'm opportunistically sending this To: you in the hopes that you
can take it into your asm-generic tree which seems like the best fit for
this.
Do you have a git tree for that?
Would be nice for testing UML, it depends also on generic io.
Yes, it's all here:

https://github.com/thierryreding/linux.git staging/asm-generic-io

That branch is based on today's linux-next (next-20140825).

Thierry
Richard Weinberger
2014-08-25 12:52:25 UTC
Permalink
Post by Thierry Reding
Post by Richard Weinberger
On Wed, Aug 13, 2014 at 12:28 PM, Thierry Reding
Post by Thierry Reding
Hi,
Here is the fourth version of a series that started out as an attempt to
provide string versions of the read*() and write*() accessors to more
architectures so that drivers can use them portably. The series has
since evolved into a more general cleanup of asm-generic/io.h and the
functions defined therein.
Patch 1 is trivial and removes a redundant redefinition of PCI_IOBASE
from the asm/io.h header on ARC. Patches 2 and 3 remove unnecessary
volatile keywoards from some functions, which is a prerequisite to clean
up some of the functions in subsequent patches.
The xlate_dev_{kmem,mem}_ptr() functions are used to map memory when the
/dev/mem device is accessed. Patches 4 and 5 use more consistent data
types for these functions, which will get a "standard" prototype in the
asm-generic/io.h header in a subsequent patch.
Patch 6 is the bulk of this series. It implements the string variants of
the read*() and write*() accessors and cleans up various other parts of
the asm-generic/io.h header file. Macros are converted to static inline
functions for better type checking. Overriding generic implementations
in architectures is handled more consistently.
Patches 7 and 8, finally, make use of the asm-generic/io.h header on the
32-bit and 64-bit ARM architectures.
This is compile- and runtime-tested on 32-bit and 64-bit ARM and compile
tested on IA64, Microblaze, s390, SPARC, x86 and Xtensa. For ARC,
Blackfin, Metag, OpenRISC, Score and Unicore32 which also use
asm-generic/io.h I couldn't find or build a cross-compiler that would
run on my system. But by code inspection they shouldn't break with this
patch.
To ensure bisectability I built multi_v7_defconfig on 32-bit ARM and the
defconfig for 64-bit ARM, IA64, Microblaze, s390, SPARC, x86 and Xtensa
after each commit and verified that the series does not introduce any
build errors or warnings.
Provided there are no objections to the patches there's still the matter
of how to merge them. Patch 6 depends on patches 1-5 to avoid warnings
and/or errors during the build. Patches 7 and 8 depend on patch 6. In my
opinion it doesn't make much sense to split them up, so I guess we'll
need a volunteer to take them all into one tree. Ideally that tree would
feed into linux-next so that we can get as much build and test-coverage
as possible during the 3.17 release cycle so that these patches can go
into 3.18.
Arnd, I'm opportunistically sending this To: you in the hopes that you
can take it into your asm-generic tree which seems like the best fit for
this.
Do you have a git tree for that?
Would be nice for testing UML, it depends also on generic io.
https://github.com/thierryreding/linux.git staging/asm-generic-io
That branch is based on today's linux-next (next-20140825).
Looks good, UML builds and boots fine here.

Thanks,
//richard
--
To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Thierry Reding
2014-08-25 13:37:53 UTC
Permalink
Post by Richard Weinberger
Post by Thierry Reding
Post by Richard Weinberger
On Wed, Aug 13, 2014 at 12:28 PM, Thierry Reding
Post by Thierry Reding
Hi,
Here is the fourth version of a series that started out as an attempt to
provide string versions of the read*() and write*() accessors to more
architectures so that drivers can use them portably. The series has
since evolved into a more general cleanup of asm-generic/io.h and the
functions defined therein.
Patch 1 is trivial and removes a redundant redefinition of PCI_IOBASE
from the asm/io.h header on ARC. Patches 2 and 3 remove unnecessary
volatile keywoards from some functions, which is a prerequisite to clean
up some of the functions in subsequent patches.
The xlate_dev_{kmem,mem}_ptr() functions are used to map memory when the
/dev/mem device is accessed. Patches 4 and 5 use more consistent data
types for these functions, which will get a "standard" prototype in the
asm-generic/io.h header in a subsequent patch.
Patch 6 is the bulk of this series. It implements the string variants of
the read*() and write*() accessors and cleans up various other parts of
the asm-generic/io.h header file. Macros are converted to static inline
functions for better type checking. Overriding generic implementations
in architectures is handled more consistently.
Patches 7 and 8, finally, make use of the asm-generic/io.h header on the
32-bit and 64-bit ARM architectures.
This is compile- and runtime-tested on 32-bit and 64-bit ARM and compile
tested on IA64, Microblaze, s390, SPARC, x86 and Xtensa. For ARC,
Blackfin, Metag, OpenRISC, Score and Unicore32 which also use
asm-generic/io.h I couldn't find or build a cross-compiler that would
run on my system. But by code inspection they shouldn't break with this
patch.
To ensure bisectability I built multi_v7_defconfig on 32-bit ARM and the
defconfig for 64-bit ARM, IA64, Microblaze, s390, SPARC, x86 and Xtensa
after each commit and verified that the series does not introduce any
build errors or warnings.
Provided there are no objections to the patches there's still the matter
of how to merge them. Patch 6 depends on patches 1-5 to avoid warnings
and/or errors during the build. Patches 7 and 8 depend on patch 6. In my
opinion it doesn't make much sense to split them up, so I guess we'll
need a volunteer to take them all into one tree. Ideally that tree would
feed into linux-next so that we can get as much build and test-coverage
as possible during the 3.17 release cycle so that these patches can go
into 3.18.
Arnd, I'm opportunistically sending this To: you in the hopes that you
can take it into your asm-generic tree which seems like the best fit for
this.
Do you have a git tree for that?
Would be nice for testing UML, it depends also on generic io.
https://github.com/thierryreding/linux.git staging/asm-generic-io
That branch is based on today's linux-next (next-20140825).
Looks good, UML builds and boots fine here.
Excellent, thanks for testing.

Thierry
Loading...