diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-08-04 12:36:20 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-08-04 12:36:20 -0400 |
commit | 455ce9d8410d381f56a1676449a723ca1985b369 (patch) | |
tree | 05ab694a3529958cf917214cfa3dd47b09dc1a2b /arch/parisc/include | |
parent | 447e1363bc2cc80fa9205a51a4f86d83c35b54a4 (diff) | |
parent | 205e9a2106b934ea39049bab28f0896c17a2cb30 (diff) |
Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/parisc-2.6
* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/parisc-2.6:
[PARISC] wire up sendmmsg syscall
[PARISC] fix return type of __atomic64_add_return
[PARISC] Fix futex support
Diffstat (limited to 'arch/parisc/include')
-rw-r--r-- | arch/parisc/include/asm/atomic.h | 4 | ||||
-rw-r--r-- | arch/parisc/include/asm/futex.h | 66 | ||||
-rw-r--r-- | arch/parisc/include/asm/unistd.h | 3 |
3 files changed, 64 insertions, 9 deletions
diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h index b1dc71f5534e..4054b31e0fa9 100644 --- a/arch/parisc/include/asm/atomic.h +++ b/arch/parisc/include/asm/atomic.h | |||
@@ -258,10 +258,10 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) | |||
258 | 258 | ||
259 | #define ATOMIC64_INIT(i) ((atomic64_t) { (i) }) | 259 | #define ATOMIC64_INIT(i) ((atomic64_t) { (i) }) |
260 | 260 | ||
261 | static __inline__ int | 261 | static __inline__ s64 |
262 | __atomic64_add_return(s64 i, atomic64_t *v) | 262 | __atomic64_add_return(s64 i, atomic64_t *v) |
263 | { | 263 | { |
264 | int ret; | 264 | s64 ret; |
265 | unsigned long flags; | 265 | unsigned long flags; |
266 | _atomic_spin_lock_irqsave(v, flags); | 266 | _atomic_spin_lock_irqsave(v, flags); |
267 | 267 | ||
diff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h index 67a33cc27ef2..2388bdb32832 100644 --- a/arch/parisc/include/asm/futex.h +++ b/arch/parisc/include/asm/futex.h | |||
@@ -5,11 +5,14 @@ | |||
5 | 5 | ||
6 | #include <linux/futex.h> | 6 | #include <linux/futex.h> |
7 | #include <linux/uaccess.h> | 7 | #include <linux/uaccess.h> |
8 | #include <asm/atomic.h> | ||
8 | #include <asm/errno.h> | 9 | #include <asm/errno.h> |
9 | 10 | ||
10 | static inline int | 11 | static inline int |
11 | futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) | 12 | futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) |
12 | { | 13 | { |
14 | unsigned long int flags; | ||
15 | u32 val; | ||
13 | int op = (encoded_op >> 28) & 7; | 16 | int op = (encoded_op >> 28) & 7; |
14 | int cmp = (encoded_op >> 24) & 15; | 17 | int cmp = (encoded_op >> 24) & 15; |
15 | int oparg = (encoded_op << 8) >> 20; | 18 | int oparg = (encoded_op << 8) >> 20; |
@@ -18,21 +21,58 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) | |||
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 21 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 22 | oparg = 1 << oparg; |
20 | 23 | ||
21 | if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) | 24 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr))) |
22 | return -EFAULT; | 25 | return -EFAULT; |
23 | 26 | ||
24 | pagefault_disable(); | 27 | pagefault_disable(); |
25 | 28 | ||
29 | _atomic_spin_lock_irqsave(uaddr, flags); | ||
30 | |||
26 | switch (op) { | 31 | switch (op) { |
27 | case FUTEX_OP_SET: | 32 | case FUTEX_OP_SET: |
33 | /* *(int *)UADDR2 = OPARG; */ | ||
34 | ret = get_user(oldval, uaddr); | ||
35 | if (!ret) | ||
36 | ret = put_user(oparg, uaddr); | ||
37 | break; | ||
28 | case FUTEX_OP_ADD: | 38 | case FUTEX_OP_ADD: |
39 | /* *(int *)UADDR2 += OPARG; */ | ||
40 | ret = get_user(oldval, uaddr); | ||
41 | if (!ret) { | ||
42 | val = oldval + oparg; | ||
43 | ret = put_user(val, uaddr); | ||
44 | } | ||
45 | break; | ||
29 | case FUTEX_OP_OR: | 46 | case FUTEX_OP_OR: |
47 | /* *(int *)UADDR2 |= OPARG; */ | ||
48 | ret = get_user(oldval, uaddr); | ||
49 | if (!ret) { | ||
50 | val = oldval | oparg; | ||
51 | ret = put_user(val, uaddr); | ||
52 | } | ||
53 | break; | ||
30 | case FUTEX_OP_ANDN: | 54 | case FUTEX_OP_ANDN: |
55 | /* *(int *)UADDR2 &= ~OPARG; */ | ||
56 | ret = get_user(oldval, uaddr); | ||
57 | if (!ret) { | ||
58 | val = oldval & ~oparg; | ||
59 | ret = put_user(val, uaddr); | ||
60 | } | ||
61 | break; | ||
31 | case FUTEX_OP_XOR: | 62 | case FUTEX_OP_XOR: |
63 | /* *(int *)UADDR2 ^= OPARG; */ | ||
64 | ret = get_user(oldval, uaddr); | ||
65 | if (!ret) { | ||
66 | val = oldval ^ oparg; | ||
67 | ret = put_user(val, uaddr); | ||
68 | } | ||
69 | break; | ||
32 | default: | 70 | default: |
33 | ret = -ENOSYS; | 71 | ret = -ENOSYS; |
34 | } | 72 | } |
35 | 73 | ||
74 | _atomic_spin_unlock_irqrestore(uaddr, flags); | ||
75 | |||
36 | pagefault_enable(); | 76 | pagefault_enable(); |
37 | 77 | ||
38 | if (!ret) { | 78 | if (!ret) { |
@@ -54,7 +94,9 @@ static inline int | |||
54 | futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, | 94 | futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, |
55 | u32 oldval, u32 newval) | 95 | u32 oldval, u32 newval) |
56 | { | 96 | { |
97 | int ret; | ||
57 | u32 val; | 98 | u32 val; |
99 | unsigned long flags; | ||
58 | 100 | ||
59 | /* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is | 101 | /* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is |
60 | * our gateway page, and causes no end of trouble... | 102 | * our gateway page, and causes no end of trouble... |
@@ -65,12 +107,24 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, | |||
65 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) | 107 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) |
66 | return -EFAULT; | 108 | return -EFAULT; |
67 | 109 | ||
68 | if (get_user(val, uaddr)) | 110 | /* HPPA has no cmpxchg in hardware and therefore the |
69 | return -EFAULT; | 111 | * best we can do here is use an array of locks. The |
70 | if (val == oldval && put_user(newval, uaddr)) | 112 | * lock selected is based on a hash of the userspace |
71 | return -EFAULT; | 113 | * address. This should scale to a couple of CPUs. |
114 | */ | ||
115 | |||
116 | _atomic_spin_lock_irqsave(uaddr, flags); | ||
117 | |||
118 | ret = get_user(val, uaddr); | ||
119 | |||
120 | if (!ret && val == oldval) | ||
121 | ret = put_user(newval, uaddr); | ||
122 | |||
72 | *uval = val; | 123 | *uval = val; |
73 | return 0; | 124 | |
125 | _atomic_spin_unlock_irqrestore(uaddr, flags); | ||
126 | |||
127 | return ret; | ||
74 | } | 128 | } |
75 | 129 | ||
76 | #endif /*__KERNEL__*/ | 130 | #endif /*__KERNEL__*/ |
diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h index 3392de3e7be0..d61de64f990a 100644 --- a/arch/parisc/include/asm/unistd.h +++ b/arch/parisc/include/asm/unistd.h | |||
@@ -821,8 +821,9 @@ | |||
821 | #define __NR_open_by_handle_at (__NR_Linux + 326) | 821 | #define __NR_open_by_handle_at (__NR_Linux + 326) |
822 | #define __NR_syncfs (__NR_Linux + 327) | 822 | #define __NR_syncfs (__NR_Linux + 327) |
823 | #define __NR_setns (__NR_Linux + 328) | 823 | #define __NR_setns (__NR_Linux + 328) |
824 | #define __NR_sendmmsg (__NR_Linux + 329) | ||
824 | 825 | ||
825 | #define __NR_Linux_syscalls (__NR_setns + 1) | 826 | #define __NR_Linux_syscalls (__NR_sendmmsg + 1) |
826 | 827 | ||
827 | 828 | ||
828 | #define __IGNORE_select /* newselect */ | 829 | #define __IGNORE_select /* newselect */ |