summaryrefslogtreecommitdiff
path: root/arch/parisc/lib
diff options
context:
space:
mode:
Diffstat (limited to 'arch/parisc/lib')
-rw-r--r--arch/parisc/lib/Makefile1
-rw-r--r--arch/parisc/lib/bitops.c44
-rw-r--r--arch/parisc/lib/checksum.c56
-rw-r--r--arch/parisc/lib/io.c166
-rw-r--r--arch/parisc/lib/iomap.c148
-rw-r--r--arch/parisc/lib/lusercopy.S68
-rw-r--r--arch/parisc/lib/memcpy.c71
-rw-r--r--arch/parisc/lib/memset.c21
-rw-r--r--arch/parisc/lib/ucmpdi2.c3
9 files changed, 204 insertions, 374 deletions
diff --git a/arch/parisc/lib/Makefile b/arch/parisc/lib/Makefile
index f2dac4d73b1b..7b197667faf6 100644
--- a/arch/parisc/lib/Makefile
+++ b/arch/parisc/lib/Makefile
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
#
# Makefile for parisc-specific library files
#
diff --git a/arch/parisc/lib/bitops.c b/arch/parisc/lib/bitops.c
index 70ffbcf889b8..9df810050642 100644
--- a/arch/parisc/lib/bitops.c
+++ b/arch/parisc/lib/bitops.c
@@ -18,7 +18,7 @@ arch_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = {
#endif
#ifdef CONFIG_64BIT
-unsigned long __xchg64(unsigned long x, unsigned long *ptr)
+unsigned long notrace __xchg64(unsigned long x, volatile unsigned long *ptr)
{
unsigned long temp, flags;
@@ -30,7 +30,7 @@ unsigned long __xchg64(unsigned long x, unsigned long *ptr)
}
#endif
-unsigned long __xchg32(int x, int *ptr)
+unsigned long notrace __xchg32(int x, volatile int *ptr)
{
unsigned long flags;
long temp;
@@ -43,7 +43,7 @@ unsigned long __xchg32(int x, int *ptr)
}
-unsigned long __xchg8(char x, char *ptr)
+unsigned long notrace __xchg8(char x, volatile char *ptr)
{
unsigned long flags;
long temp;
@@ -56,26 +56,20 @@ unsigned long __xchg8(char x, char *ptr)
}
-u64 __cmpxchg_u64(volatile u64 *ptr, u64 old, u64 new)
-{
- unsigned long flags;
- u64 prev;
-
- _atomic_spin_lock_irqsave(ptr, flags);
- if ((prev = *ptr) == old)
- *ptr = new;
- _atomic_spin_unlock_irqrestore(ptr, flags);
- return prev;
-}
+#define CMPXCHG(T) \
+ T notrace __cmpxchg_##T(volatile T *ptr, T old, T new) \
+ { \
+ unsigned long flags; \
+ T prev; \
+ \
+ _atomic_spin_lock_irqsave(ptr, flags); \
+ if ((prev = *ptr) == old) \
+ *ptr = new; \
+ _atomic_spin_unlock_irqrestore(ptr, flags); \
+ return prev; \
+ }
-unsigned long __cmpxchg_u32(volatile unsigned int *ptr, unsigned int old, unsigned int new)
-{
- unsigned long flags;
- unsigned int prev;
-
- _atomic_spin_lock_irqsave(ptr, flags);
- if ((prev = *ptr) == old)
- *ptr = new;
- _atomic_spin_unlock_irqrestore(ptr, flags);
- return (unsigned long)prev;
-}
+CMPXCHG(u64)
+CMPXCHG(u32)
+CMPXCHG(u16)
+CMPXCHG(u8)
diff --git a/arch/parisc/lib/checksum.c b/arch/parisc/lib/checksum.c
index ba6384da6ade..59d8c15d81bd 100644
--- a/arch/parisc/lib/checksum.c
+++ b/arch/parisc/lib/checksum.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
@@ -8,11 +9,6 @@
* Authors: Ralf Baechle, <ralf@waldorf-gmbh.de>
* Lots of code moved from tcp.c and ip.c; see those files
* for more names.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
*/
#include <linux/module.h>
#include <linux/types.h>
@@ -29,15 +25,6 @@
: "=r"(_t) \
: "r"(_r), "0"(_t));
-static inline unsigned short from32to16(unsigned int x)
-{
- /* 32 bits --> 16 bits + carry */
- x = (x & 0xffff) + (x >> 16);
- /* 16 bits + carry --> 16 bits including carry */
- x = (x & 0xffff) + (x >> 16);
- return (unsigned short)x;
-}
-
static inline unsigned int do_csum(const unsigned char * buff, int len)
{
int odd, count;
@@ -89,7 +76,7 @@ static inline unsigned int do_csum(const unsigned char * buff, int len)
}
if (len & 1)
result += le16_to_cpu(*buff);
- result = from32to16(result);
+ result = csum_from32to16(result);
if (odd)
result = swab16(result);
out:
@@ -106,44 +93,7 @@ __wsum csum_partial(const void *buff, int len, __wsum sum)
{
unsigned int result = do_csum(buff, len);
addc(result, sum);
- return (__force __wsum)from32to16(result);
+ return (__force __wsum)csum_from32to16(result);
}
EXPORT_SYMBOL(csum_partial);
-
-/*
- * copy while checksumming, otherwise like csum_partial
- */
-__wsum csum_partial_copy_nocheck(const void *src, void *dst,
- int len, __wsum sum)
-{
- /*
- * It's 2:30 am and I don't feel like doing it real ...
- * This is lots slower than the real thing (tm)
- */
- sum = csum_partial(src, len, sum);
- memcpy(dst, src, len);
-
- return sum;
-}
-EXPORT_SYMBOL(csum_partial_copy_nocheck);
-
-/*
- * Copy from userspace and compute checksum. If we catch an exception
- * then zero the rest of the buffer.
- */
-__wsum csum_partial_copy_from_user(const void __user *src,
- void *dst, int len,
- __wsum sum, int *err_ptr)
-{
- int missing;
-
- missing = copy_from_user(dst, src, len);
- if (missing) {
- memset(dst + len - missing, 0, missing);
- *err_ptr = -EFAULT;
- }
-
- return csum_partial(dst, len, sum);
-}
-EXPORT_SYMBOL(csum_partial_copy_from_user);
diff --git a/arch/parisc/lib/io.c b/arch/parisc/lib/io.c
index 7c00496b47d4..3c7e617f5a93 100644
--- a/arch/parisc/lib/io.c
+++ b/arch/parisc/lib/io.c
@@ -12,114 +12,6 @@
#include <linux/module.h>
#include <asm/io.h>
-/* Copies a block of memory to a device in an efficient manner.
- * Assumes the device can cope with 32-bit transfers. If it can't,
- * don't use this function.
- */
-void memcpy_toio(volatile void __iomem *dst, const void *src, int count)
-{
- if (((unsigned long)dst & 3) != ((unsigned long)src & 3))
- goto bytecopy;
- while ((unsigned long)dst & 3) {
- writeb(*(char *)src, dst++);
- src++;
- count--;
- }
- while (count > 3) {
- __raw_writel(*(u32 *)src, dst);
- src += 4;
- dst += 4;
- count -= 4;
- }
- bytecopy:
- while (count--) {
- writeb(*(char *)src, dst++);
- src++;
- }
-}
-
-/*
-** Copies a block of memory from a device in an efficient manner.
-** Assumes the device can cope with 32-bit transfers. If it can't,
-** don't use this function.
-**
-** CR16 counts on C3000 reading 256 bytes from Symbios 896 RAM:
-** 27341/64 = 427 cyc per int
-** 61311/128 = 478 cyc per short
-** 122637/256 = 479 cyc per byte
-** Ergo bus latencies dominant (not transfer size).
-** Minimize total number of transfers at cost of CPU cycles.
-** TODO: only look at src alignment and adjust the stores to dest.
-*/
-void memcpy_fromio(void *dst, const volatile void __iomem *src, int count)
-{
- /* first compare alignment of src/dst */
- if ( (((unsigned long)dst ^ (unsigned long)src) & 1) || (count < 2) )
- goto bytecopy;
-
- if ( (((unsigned long)dst ^ (unsigned long)src) & 2) || (count < 4) )
- goto shortcopy;
-
- /* Then check for misaligned start address */
- if ((unsigned long)src & 1) {
- *(u8 *)dst = readb(src);
- src++;
- dst++;
- count--;
- if (count < 2) goto bytecopy;
- }
-
- if ((unsigned long)src & 2) {
- *(u16 *)dst = __raw_readw(src);
- src += 2;
- dst += 2;
- count -= 2;
- }
-
- while (count > 3) {
- *(u32 *)dst = __raw_readl(src);
- dst += 4;
- src += 4;
- count -= 4;
- }
-
- shortcopy:
- while (count > 1) {
- *(u16 *)dst = __raw_readw(src);
- src += 2;
- dst += 2;
- count -= 2;
- }
-
- bytecopy:
- while (count--) {
- *(char *)dst = readb(src);
- src++;
- dst++;
- }
-}
-
-/* Sets a block of memory on a device to a given value.
- * Assumes the device can cope with 32-bit transfers. If it can't,
- * don't use this function.
- */
-void memset_io(volatile void __iomem *addr, unsigned char val, int count)
-{
- u32 val32 = (val << 24) | (val << 16) | (val << 8) | val;
- while ((unsigned long)addr & 3) {
- writeb(val, addr++);
- count--;
- }
- while (count > 3) {
- __raw_writel(val32, addr);
- addr += 4;
- count -= 4;
- }
- while (count--) {
- writeb(val, addr++);
- }
-}
-
/*
* Read COUNT 8-bit bytes from port PORT into memory starting at
* SRC.
@@ -170,15 +62,15 @@ void insw (unsigned long port, void *dst, unsigned long count)
unsigned char *p;
p = (unsigned char *)dst;
-
+
if (!count)
return;
-
+
switch (((unsigned long)p) & 0x3)
{
case 0x00: /* Buffer 32-bit aligned */
while (count>=2) {
-
+
count -= 2;
l = cpu_to_le16(inw(port)) << 16;
l |= cpu_to_le16(inw(port));
@@ -189,13 +81,13 @@ void insw (unsigned long port, void *dst, unsigned long count)
*(unsigned short *)p = cpu_to_le16(inw(port));
}
break;
-
+
case 0x02: /* Buffer 16-bit aligned */
*(unsigned short *)p = cpu_to_le16(inw(port));
p += 2;
count--;
while (count>=2) {
-
+
count -= 2;
l = cpu_to_le16(inw(port)) << 16;
l |= cpu_to_le16(inw(port));
@@ -206,13 +98,13 @@ void insw (unsigned long port, void *dst, unsigned long count)
*(unsigned short *)p = cpu_to_le16(inw(port));
}
break;
-
+
case 0x01: /* Buffer 8-bit aligned */
case 0x03:
/* I don't bother with 32bit transfers
* in this case, 16bit will have to do -- DE */
--count;
-
+
l = cpu_to_le16(inw(port));
*p = l >> 8;
p++;
@@ -242,10 +134,10 @@ void insl (unsigned long port, void *dst, unsigned long count)
unsigned char *p;
p = (unsigned char *)dst;
-
+
if (!count)
return;
-
+
switch (((unsigned long) dst) & 0x3)
{
case 0x00: /* Buffer 32-bit aligned */
@@ -255,14 +147,14 @@ void insl (unsigned long port, void *dst, unsigned long count)
p += 4;
}
break;
-
+
case 0x02: /* Buffer 16-bit aligned */
--count;
-
+
l = cpu_to_le32(inl(port));
*(unsigned short *)p = l >> 16;
p += 2;
-
+
while (count--)
{
l2 = cpu_to_le32(inl(port));
@@ -274,7 +166,7 @@ void insl (unsigned long port, void *dst, unsigned long count)
break;
case 0x01: /* Buffer 8-bit aligned */
--count;
-
+
l = cpu_to_le32(inl(port));
*(unsigned char *)p = l >> 24;
p++;
@@ -291,7 +183,7 @@ void insl (unsigned long port, void *dst, unsigned long count)
break;
case 0x03: /* Buffer 8-bit aligned */
--count;
-
+
l = cpu_to_le32(inl(port));
*p = l >> 24;
p++;
@@ -340,10 +232,10 @@ void outsw (unsigned long port, const void *src, unsigned long count)
const unsigned char *p;
p = (const unsigned char *)src;
-
+
if (!count)
return;
-
+
switch (((unsigned long)p) & 0x3)
{
case 0x00: /* Buffer 32-bit aligned */
@@ -358,13 +250,13 @@ void outsw (unsigned long port, const void *src, unsigned long count)
outw(le16_to_cpu(*(unsigned short*)p), port);
}
break;
-
+
case 0x02: /* Buffer 16-bit aligned */
-
+
outw(le16_to_cpu(*(unsigned short*)p), port);
p += 2;
count--;
-
+
while (count>=2) {
count -= 2;
l = *(unsigned int *)p;
@@ -376,11 +268,11 @@ void outsw (unsigned long port, const void *src, unsigned long count)
outw(le16_to_cpu(*(unsigned short *)p), port);
}
break;
-
- case 0x01: /* Buffer 8-bit aligned */
+
+ case 0x01: /* Buffer 8-bit aligned */
/* I don't bother with 32bit transfers
* in this case, 16bit will have to do -- DE */
-
+
l = *p << 8;
p++;
count--;
@@ -395,7 +287,7 @@ void outsw (unsigned long port, const void *src, unsigned long count)
l2 = *(unsigned char *)p;
outw (le16_to_cpu(l | l2>>8), port);
break;
-
+
}
}
@@ -412,10 +304,10 @@ void outsl (unsigned long port, const void *src, unsigned long count)
const unsigned char *p;
p = (const unsigned char *)src;
-
+
if (!count)
return;
-
+
switch (((unsigned long)p) & 0x3)
{
case 0x00: /* Buffer 32-bit aligned */
@@ -425,13 +317,13 @@ void outsl (unsigned long port, const void *src, unsigned long count)
p += 4;
}
break;
-
+
case 0x02: /* Buffer 16-bit aligned */
--count;
-
+
l = *(unsigned short *)p;
p += 2;
-
+
while (count--)
{
l2 = *(unsigned int *)p;
@@ -462,7 +354,7 @@ void outsl (unsigned long port, const void *src, unsigned long count)
break;
case 0x03: /* Buffer 8-bit aligned */
--count;
-
+
l = *p << 24;
p++;
diff --git a/arch/parisc/lib/iomap.c b/arch/parisc/lib/iomap.c
index 4b19e6e64fb7..915c0c4da663 100644
--- a/arch/parisc/lib/iomap.c
+++ b/arch/parisc/lib/iomap.c
@@ -43,19 +43,27 @@
#endif
struct iomap_ops {
- unsigned int (*read8)(void __iomem *);
- unsigned int (*read16)(void __iomem *);
- unsigned int (*read16be)(void __iomem *);
- unsigned int (*read32)(void __iomem *);
- unsigned int (*read32be)(void __iomem *);
+ unsigned int (*read8)(const void __iomem *);
+ unsigned int (*read16)(const void __iomem *);
+ unsigned int (*read16be)(const void __iomem *);
+ unsigned int (*read32)(const void __iomem *);
+ unsigned int (*read32be)(const void __iomem *);
+#ifdef CONFIG_64BIT
+ u64 (*read64)(const void __iomem *);
+ u64 (*read64be)(const void __iomem *);
+#endif
void (*write8)(u8, void __iomem *);
void (*write16)(u16, void __iomem *);
void (*write16be)(u16, void __iomem *);
void (*write32)(u32, void __iomem *);
void (*write32be)(u32, void __iomem *);
- void (*read8r)(void __iomem *, void *, unsigned long);
- void (*read16r)(void __iomem *, void *, unsigned long);
- void (*read32r)(void __iomem *, void *, unsigned long);
+#ifdef CONFIG_64BIT
+ void (*write64)(u64, void __iomem *);
+ void (*write64be)(u64, void __iomem *);
+#endif
+ void (*read8r)(const void __iomem *, void *, unsigned long);
+ void (*read16r)(const void __iomem *, void *, unsigned long);
+ void (*read32r)(const void __iomem *, void *, unsigned long);
void (*write8r)(void __iomem *, const void *, unsigned long);
void (*write16r)(void __iomem *, const void *, unsigned long);
void (*write32r)(void __iomem *, const void *, unsigned long);
@@ -65,17 +73,17 @@ struct iomap_ops {
#define ADDR2PORT(addr) ((unsigned long __force)(addr) & 0xffffff)
-static unsigned int ioport_read8(void __iomem *addr)
+static unsigned int ioport_read8(const void __iomem *addr)
{
return inb(ADDR2PORT(addr));
}
-static unsigned int ioport_read16(void __iomem *addr)
+static unsigned int ioport_read16(const void __iomem *addr)
{
return inw(ADDR2PORT(addr));
}
-static unsigned int ioport_read32(void __iomem *addr)
+static unsigned int ioport_read32(const void __iomem *addr)
{
return inl(ADDR2PORT(addr));
}
@@ -95,17 +103,17 @@ static void ioport_write32(u32 datum, void __iomem *addr)
outl(datum, ADDR2PORT(addr));
}
-static void ioport_read8r(void __iomem *addr, void *dst, unsigned long count)
+static void ioport_read8r(const void __iomem *addr, void *dst, unsigned long count)
{
insb(ADDR2PORT(addr), dst, count);
}
-static void ioport_read16r(void __iomem *addr, void *dst, unsigned long count)
+static void ioport_read16r(const void __iomem *addr, void *dst, unsigned long count)
{
insw(ADDR2PORT(addr), dst, count);
}
-static void ioport_read32r(void __iomem *addr, void *dst, unsigned long count)
+static void ioport_read32r(const void __iomem *addr, void *dst, unsigned long count)
{
insl(ADDR2PORT(addr), dst, count);
}
@@ -146,31 +154,43 @@ static const struct iomap_ops ioport_ops = {
/* Legacy I/O memory ops */
-static unsigned int iomem_read8(void __iomem *addr)
+static unsigned int iomem_read8(const void __iomem *addr)
{
return readb(addr);
}
-static unsigned int iomem_read16(void __iomem *addr)
+static unsigned int iomem_read16(const void __iomem *addr)
{
return readw(addr);
}
-static unsigned int iomem_read16be(void __iomem *addr)
+static unsigned int iomem_read16be(const void __iomem *addr)
{
return __raw_readw(addr);
}
-static unsigned int iomem_read32(void __iomem *addr)
+static unsigned int iomem_read32(const void __iomem *addr)
{
return readl(addr);
}
-static unsigned int iomem_read32be(void __iomem *addr)
+static unsigned int iomem_read32be(const void __iomem *addr)
{
return __raw_readl(addr);
}
+#ifdef CONFIG_64BIT
+static u64 iomem_read64(const void __iomem *addr)
+{
+ return readq(addr);
+}
+
+static u64 iomem_read64be(const void __iomem *addr)
+{
+ return __raw_readq(addr);
+}
+#endif
+
static void iomem_write8(u8 datum, void __iomem *addr)
{
writeb(datum, addr);
@@ -196,7 +216,19 @@ static void iomem_write32be(u32 datum, void __iomem *addr)
__raw_writel(datum, addr);
}
-static void iomem_read8r(void __iomem *addr, void *dst, unsigned long count)
+#ifdef CONFIG_64BIT
+static void iomem_write64(u64 datum, void __iomem *addr)
+{
+ writeq(datum, addr);
+}
+
+static void iomem_write64be(u64 datum, void __iomem *addr)
+{
+ __raw_writeq(datum, addr);
+}
+#endif
+
+static void iomem_read8r(const void __iomem *addr, void *dst, unsigned long count)
{
while (count--) {
*(u8 *)dst = __raw_readb(addr);
@@ -204,7 +236,7 @@ static void iomem_read8r(void __iomem *addr, void *dst, unsigned long count)
}
}
-static void iomem_read16r(void __iomem *addr, void *dst, unsigned long count)
+static void iomem_read16r(const void __iomem *addr, void *dst, unsigned long count)
{
while (count--) {
*(u16 *)dst = __raw_readw(addr);
@@ -212,7 +244,7 @@ static void iomem_read16r(void __iomem *addr, void *dst, unsigned long count)
}
}
-static void iomem_read32r(void __iomem *addr, void *dst, unsigned long count)
+static void iomem_read32r(const void __iomem *addr, void *dst, unsigned long count)
{
while (count--) {
*(u32 *)dst = __raw_readl(addr);
@@ -250,11 +282,19 @@ static const struct iomap_ops iomem_ops = {
.read16be = iomem_read16be,
.read32 = iomem_read32,
.read32be = iomem_read32be,
+#ifdef CONFIG_64BIT
+ .read64 = iomem_read64,
+ .read64be = iomem_read64be,
+#endif
.write8 = iomem_write8,
.write16 = iomem_write16,
.write16be = iomem_write16be,
.write32 = iomem_write32,
.write32be = iomem_write32be,
+#ifdef CONFIG_64BIT
+ .write64 = iomem_write64,
+ .write64be = iomem_write64be,
+#endif
.read8r = iomem_read8r,
.read16r = iomem_read16r,
.read32r = iomem_read32r,
@@ -269,41 +309,57 @@ static const struct iomap_ops *iomap_ops[8] = {
};
-unsigned int ioread8(void __iomem *addr)
+unsigned int ioread8(const void __iomem *addr)
{
if (unlikely(INDIRECT_ADDR(addr)))
return iomap_ops[ADDR_TO_REGION(addr)]->read8(addr);
return *((u8 *)addr);
}
-unsigned int ioread16(void __iomem *addr)
+unsigned int ioread16(const void __iomem *addr)
{
if (unlikely(INDIRECT_ADDR(addr)))
return iomap_ops[ADDR_TO_REGION(addr)]->read16(addr);
return le16_to_cpup((u16 *)addr);
}
-unsigned int ioread16be(void __iomem *addr)
+unsigned int ioread16be(const void __iomem *addr)
{
if (unlikely(INDIRECT_ADDR(addr)))
return iomap_ops[ADDR_TO_REGION(addr)]->read16be(addr);
return *((u16 *)addr);
}
-unsigned int ioread32(void __iomem *addr)
+unsigned int ioread32(const void __iomem *addr)
{
if (unlikely(INDIRECT_ADDR(addr)))
return iomap_ops[ADDR_TO_REGION(addr)]->read32(addr);
return le32_to_cpup((u32 *)addr);
}
-unsigned int ioread32be(void __iomem *addr)
+unsigned int ioread32be(const void __iomem *addr)
{
if (unlikely(INDIRECT_ADDR(addr)))
return iomap_ops[ADDR_TO_REGION(addr)]->read32be(addr);
return *((u32 *)addr);
}
+#ifdef CONFIG_64BIT
+u64 ioread64(const void __iomem *addr)
+{
+ if (unlikely(INDIRECT_ADDR(addr)))
+ return iomap_ops[ADDR_TO_REGION(addr)]->read64(addr);
+ return le64_to_cpup((u64 *)addr);
+}
+
+u64 ioread64be(const void __iomem *addr)
+{
+ if (unlikely(INDIRECT_ADDR(addr)))
+ return iomap_ops[ADDR_TO_REGION(addr)]->read64be(addr);
+ return *((u64 *)addr);
+}
+#endif
+
void iowrite8(u8 datum, void __iomem *addr)
{
if (unlikely(INDIRECT_ADDR(addr))) {
@@ -349,9 +405,29 @@ void iowrite32be(u32 datum, void __iomem *addr)
}
}
+#ifdef CONFIG_64BIT
+void iowrite64(u64 datum, void __iomem *addr)
+{
+ if (unlikely(INDIRECT_ADDR(addr))) {
+ iomap_ops[ADDR_TO_REGION(addr)]->write64(datum, addr);
+ } else {
+ *((u64 *)addr) = cpu_to_le64(datum);
+ }
+}
+
+void iowrite64be(u64 datum, void __iomem *addr)
+{
+ if (unlikely(INDIRECT_ADDR(addr))) {
+ iomap_ops[ADDR_TO_REGION(addr)]->write64be(datum, addr);
+ } else {
+ *((u64 *)addr) = datum;
+ }
+}
+#endif
+
/* Repeating interfaces */
-void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
+void ioread8_rep(const void __iomem *addr, void *dst, unsigned long count)
{
if (unlikely(INDIRECT_ADDR(addr))) {
iomap_ops[ADDR_TO_REGION(addr)]->read8r(addr, dst, count);
@@ -363,7 +439,7 @@ void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
}
}
-void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
+void ioread16_rep(const void __iomem *addr, void *dst, unsigned long count)
{
if (unlikely(INDIRECT_ADDR(addr))) {
iomap_ops[ADDR_TO_REGION(addr)]->read16r(addr, dst, count);
@@ -375,7 +451,7 @@ void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
}
}
-void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
+void ioread32_rep(const void __iomem *addr, void *dst, unsigned long count)
{
if (unlikely(INDIRECT_ADDR(addr))) {
iomap_ops[ADDR_TO_REGION(addr)]->read32r(addr, dst, count);
@@ -437,23 +513,34 @@ void ioport_unmap(void __iomem *addr)
}
}
+#ifdef CONFIG_PCI
void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
{
if (!INDIRECT_ADDR(addr)) {
iounmap(addr);
}
}
+EXPORT_SYMBOL(pci_iounmap);
+#endif
EXPORT_SYMBOL(ioread8);
EXPORT_SYMBOL(ioread16);
EXPORT_SYMBOL(ioread16be);
EXPORT_SYMBOL(ioread32);
EXPORT_SYMBOL(ioread32be);
+#ifdef CONFIG_64BIT
+EXPORT_SYMBOL(ioread64);
+EXPORT_SYMBOL(ioread64be);
+#endif
EXPORT_SYMBOL(iowrite8);
EXPORT_SYMBOL(iowrite16);
EXPORT_SYMBOL(iowrite16be);
EXPORT_SYMBOL(iowrite32);
EXPORT_SYMBOL(iowrite32be);
+#ifdef CONFIG_64BIT
+EXPORT_SYMBOL(iowrite64);
+EXPORT_SYMBOL(iowrite64be);
+#endif
EXPORT_SYMBOL(ioread8_rep);
EXPORT_SYMBOL(ioread16_rep);
EXPORT_SYMBOL(ioread32_rep);
@@ -462,4 +549,3 @@ EXPORT_SYMBOL(iowrite16_rep);
EXPORT_SYMBOL(iowrite32_rep);
EXPORT_SYMBOL(ioport_map);
EXPORT_SYMBOL(ioport_unmap);
-EXPORT_SYMBOL(pci_iounmap);
diff --git a/arch/parisc/lib/lusercopy.S b/arch/parisc/lib/lusercopy.S
index b53fb6fedf06..b428d29e45fb 100644
--- a/arch/parisc/lib/lusercopy.S
+++ b/arch/parisc/lib/lusercopy.S
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* User Space Access Routines
*
@@ -7,21 +8,6 @@
* Copyright (C) 2003 Randolph Chung <tausq with parisc-linux.org>
* Copyright (C) 2017 Helge Deller <deller@gmx.de>
* Copyright (C) 2017 John David Anglin <dave.anglin@bell.net>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
@@ -42,21 +28,6 @@
#include <linux/linkage.h>
/*
- * get_sr gets the appropriate space value into
- * sr1 for kernel/user space access, depending
- * on the flag stored in the task structure.
- */
-
- .macro get_sr
- mfctl %cr30,%r1
- ldw TI_SEGMENT(%r1),%r22
- mfsp %sr3,%r1
- or,<> %r22,%r0,%r0
- copy %r0,%r1
- mtsp %r1,%sr1
- .endm
-
- /*
* unsigned long lclear_user(void *to, unsigned long n)
*
* Returns 0 for success.
@@ -65,10 +36,9 @@
ENTRY_CFI(lclear_user)
comib,=,n 0,%r25,$lclu_done
- get_sr
$lclu_loop:
addib,<> -1,%r25,$lclu_loop
-1: stbs,ma %r0,1(%sr1,%r26)
+1: stbs,ma %r0,1(%sr3,%r26)
$lclu_done:
bv %r0(%r2)
@@ -81,40 +51,6 @@ $lclu_done:
ENDPROC_CFI(lclear_user)
- /*
- * long lstrnlen_user(char *s, long n)
- *
- * Returns 0 if exception before zero byte or reaching N,
- * N+1 if N would be exceeded,
- * else strlen + 1 (i.e. includes zero byte).
- */
-
-ENTRY_CFI(lstrnlen_user)
- comib,= 0,%r25,$lslen_nzero
- copy %r26,%r24
- get_sr
-1: ldbs,ma 1(%sr1,%r26),%r1
-$lslen_loop:
- comib,=,n 0,%r1,$lslen_done
- addib,<> -1,%r25,$lslen_loop
-2: ldbs,ma 1(%sr1,%r26),%r1
-$lslen_done:
- bv %r0(%r2)
- sub %r26,%r24,%r28
-
-$lslen_nzero:
- b $lslen_done
- ldo 1(%r26),%r26 /* special case for N == 0 */
-
-3: b $lslen_done
- copy %r24,%r26 /* reset r26 so 0 is returned on fault */
-
- ASM_EXCEPTIONTABLE_ENTRY(1b,3b)
- ASM_EXCEPTIONTABLE_ENTRY(2b,3b)
-
-ENDPROC_CFI(lstrnlen_user)
-
-
/*
* unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len)
*
diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c
index 865a7f796c7f..03165c82dfdb 100644
--- a/arch/parisc/lib/memcpy.c
+++ b/arch/parisc/lib/memcpy.c
@@ -1,34 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Optimized memory copy routines.
*
* Copyright (C) 2004 Randolph Chung <tausq@debian.org>
* Copyright (C) 2013-2017 Helge Deller <deller@gmx.de>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
* Portions derived from the GNU C Library
* Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc.
- *
*/
#include <linux/module.h>
#include <linux/compiler.h>
#include <linux/uaccess.h>
+#include <linux/mm.h>
-#define get_user_space() (uaccess_kernel() ? 0 : mfsp(3))
-#define get_kernel_space() (0)
+#define get_user_space() mfsp(SR_USER)
+#define get_kernel_space() SR_KERNEL
/* Returns 0 for success, otherwise, returns number of bytes not transferred. */
extern unsigned long pa_memcpy(void *dst, const void *src,
@@ -37,8 +24,8 @@ extern unsigned long pa_memcpy(void *dst, const void *src,
unsigned long raw_copy_to_user(void __user *dst, const void *src,
unsigned long len)
{
- mtsp(get_kernel_space(), 1);
- mtsp(get_user_space(), 2);
+ mtsp(get_kernel_space(), SR_TEMP1);
+ mtsp(get_user_space(), SR_TEMP2);
return pa_memcpy((void __force *)dst, src, len);
}
EXPORT_SYMBOL(raw_copy_to_user);
@@ -46,39 +33,41 @@ EXPORT_SYMBOL(raw_copy_to_user);
unsigned long raw_copy_from_user(void *dst, const void __user *src,
unsigned long len)
{
- mtsp(get_user_space(), 1);
- mtsp(get_kernel_space(), 2);
- return pa_memcpy(dst, (void __force *)src, len);
-}
-EXPORT_SYMBOL(raw_copy_from_user);
+ unsigned long start = (unsigned long) src;
+ unsigned long end = start + len;
+ unsigned long newlen = len;
-unsigned long raw_copy_in_user(void __user *dst, const void __user *src, unsigned long len)
-{
- mtsp(get_user_space(), 1);
- mtsp(get_user_space(), 2);
- return pa_memcpy((void __force *)dst, (void __force *)src, len);
-}
+ mtsp(get_user_space(), SR_TEMP1);
+ mtsp(get_kernel_space(), SR_TEMP2);
+ /* Check region is user accessible */
+ while (start < end) {
+ if (!prober_user(SR_TEMP1, start)) {
+ newlen = (start - (unsigned long) src);
+ break;
+ }
+ start += PAGE_SIZE;
+ /* align to page boundry which may have different permission */
+ start = PAGE_ALIGN_DOWN(start);
+ }
+ return len - newlen + pa_memcpy(dst, (void __force *)src, newlen);
+}
+EXPORT_SYMBOL(raw_copy_from_user);
void * memcpy(void * dst,const void *src, size_t count)
{
- mtsp(get_kernel_space(), 1);
- mtsp(get_kernel_space(), 2);
+ mtsp(get_kernel_space(), SR_TEMP1);
+ mtsp(get_kernel_space(), SR_TEMP2);
pa_memcpy(dst, src, count);
return dst;
}
-EXPORT_SYMBOL(raw_copy_in_user);
EXPORT_SYMBOL(memcpy);
-long probe_kernel_read(void *dst, const void *src, size_t size)
+bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
{
- unsigned long addr = (unsigned long)src;
-
- if (addr < PAGE_SIZE)
- return -EFAULT;
-
+ if ((unsigned long)unsafe_src < PAGE_SIZE)
+ return false;
/* check for I/O space F_EXTEND(0xfff00000) access as well? */
-
- return __probe_kernel_read(dst, src, size);
+ return true;
}
diff --git a/arch/parisc/lib/memset.c b/arch/parisc/lib/memset.c
index 1d7929bd7642..133e4809859a 100644
--- a/arch/parisc/lib/memset.c
+++ b/arch/parisc/lib/memset.c
@@ -1,23 +1,4 @@
-/* Copyright (C) 1991, 1997 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-/* Slight modifications for pa-risc linux - Paul Bame <bame@debian.org> */
-
+/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <linux/types.h>
#include <asm/string.h>
diff --git a/arch/parisc/lib/ucmpdi2.c b/arch/parisc/lib/ucmpdi2.c
index 8e6014a142ef..9d8b4dbae273 100644
--- a/arch/parisc/lib/ucmpdi2.c
+++ b/arch/parisc/lib/ucmpdi2.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/module.h>
+#include <linux/libgcc.h>
union ull_union {
unsigned long long ull;
@@ -9,7 +10,7 @@ union ull_union {
} ui;
};
-int __ucmpdi2(unsigned long long a, unsigned long long b)
+word_type __ucmpdi2(unsigned long long a, unsigned long long b)
{
union ull_union au = {.ull = a};
union ull_union bu = {.ull = b};