]> git.karo-electronics.de Git - mv-sheeva.git/blob - include/asm-generic/cmpxchg-local.h
Merge tag 'md-3.4-fixes' of git://neil.brown.name/md
[mv-sheeva.git] / include / asm-generic / cmpxchg-local.h
1 #ifndef __ASM_GENERIC_CMPXCHG_LOCAL_H
2 #define __ASM_GENERIC_CMPXCHG_LOCAL_H
3
4 #include <linux/types.h>
5 #include <linux/irqflags.h>
6
7 extern unsigned long wrong_size_cmpxchg(volatile void *ptr);
8
9 /*
10  * Generic version of __cmpxchg_local (disables interrupts). Takes an unsigned
11  * long parameter, supporting various types of architectures.
12  */
13 static inline unsigned long __cmpxchg_local_generic(volatile void *ptr,
14                 unsigned long old, unsigned long new, int size)
15 {
16         unsigned long flags, prev;
17
18         /*
19          * Sanity checking, compile-time.
20          */
21         if (size == 8 && sizeof(unsigned long) != 8)
22                 wrong_size_cmpxchg(ptr);
23
24         local_irq_save(flags);
25         switch (size) {
26         case 1: prev = *(u8 *)ptr;
27                 if (prev == old)
28                         *(u8 *)ptr = (u8)new;
29                 break;
30         case 2: prev = *(u16 *)ptr;
31                 if (prev == old)
32                         *(u16 *)ptr = (u16)new;
33                 break;
34         case 4: prev = *(u32 *)ptr;
35                 if (prev == old)
36                         *(u32 *)ptr = (u32)new;
37                 break;
38         case 8: prev = *(u64 *)ptr;
39                 if (prev == old)
40                         *(u64 *)ptr = (u64)new;
41                 break;
42         default:
43                 wrong_size_cmpxchg(ptr);
44         }
45         local_irq_restore(flags);
46         return prev;
47 }
48
49 /*
50  * Generic version of __cmpxchg64_local. Takes an u64 parameter.
51  */
52 static inline u64 __cmpxchg64_local_generic(volatile void *ptr,
53                 u64 old, u64 new)
54 {
55         u64 prev;
56         unsigned long flags;
57
58         local_irq_save(flags);
59         prev = *(u64 *)ptr;
60         if (prev == old)
61                 *(u64 *)ptr = new;
62         local_irq_restore(flags);
63         return prev;
64 }
65
66 #endif