Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / mn10300 / include / asm / cmpxchg.h
1 /* MN10300 Atomic xchg/cmpxchg operations
2  *
3  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public Licence
8  * as published by the Free Software Foundation; either version
9  * 2 of the Licence, or (at your option) any later version.
10  */
11 #ifndef _ASM_CMPXCHG_H
12 #define _ASM_CMPXCHG_H
13
14 #include <asm/irqflags.h>
15
16 #ifdef CONFIG_SMP
17 #ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
18 static inline
19 unsigned long __xchg(volatile unsigned long *m, unsigned long val)
20 {
21         unsigned long status;
22         unsigned long oldval;
23
24         asm volatile(
25                 "1:     mov     %4,(_AAR,%3)    \n"
26                 "       mov     (_ADR,%3),%1    \n"
27                 "       mov     %5,(_ADR,%3)    \n"
28                 "       mov     (_ADR,%3),%0    \n"     /* flush */
29                 "       mov     (_ASR,%3),%0    \n"
30                 "       or      %0,%0           \n"
31                 "       bne     1b              \n"
32                 : "=&r"(status), "=&r"(oldval), "=m"(*m)
33                 : "a"(ATOMIC_OPS_BASE_ADDR), "r"(m), "r"(val)
34                 : "memory", "cc");
35
36         return oldval;
37 }
38
39 static inline unsigned long __cmpxchg(volatile unsigned long *m,
40                                       unsigned long old, unsigned long new)
41 {
42         unsigned long status;
43         unsigned long oldval;
44
45         asm volatile(
46                 "1:     mov     %4,(_AAR,%3)    \n"
47                 "       mov     (_ADR,%3),%1    \n"
48                 "       cmp     %5,%1           \n"
49                 "       bne     2f              \n"
50                 "       mov     %6,(_ADR,%3)    \n"
51                 "2:     mov     (_ADR,%3),%0    \n"     /* flush */
52                 "       mov     (_ASR,%3),%0    \n"
53                 "       or      %0,%0           \n"
54                 "       bne     1b              \n"
55                 : "=&r"(status), "=&r"(oldval), "=m"(*m)
56                 : "a"(ATOMIC_OPS_BASE_ADDR), "r"(m),
57                   "r"(old), "r"(new)
58                 : "memory", "cc");
59
60         return oldval;
61 }
62 #else  /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
63 #error "No SMP atomic operation support!"
64 #endif /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
65
66 #else  /* CONFIG_SMP */
67
68 /*
69  * Emulate xchg for non-SMP MN10300
70  */
71 struct __xchg_dummy { unsigned long a[100]; };
72 #define __xg(x) ((struct __xchg_dummy *)(x))
73
74 static inline
75 unsigned long __xchg(volatile unsigned long *m, unsigned long val)
76 {
77         unsigned long oldval;
78         unsigned long flags;
79
80         flags = arch_local_cli_save();
81         oldval = *m;
82         *m = val;
83         arch_local_irq_restore(flags);
84         return oldval;
85 }
86
87 /*
88  * Emulate cmpxchg for non-SMP MN10300
89  */
90 static inline unsigned long __cmpxchg(volatile unsigned long *m,
91                                       unsigned long old, unsigned long new)
92 {
93         unsigned long oldval;
94         unsigned long flags;
95
96         flags = arch_local_cli_save();
97         oldval = *m;
98         if (oldval == old)
99                 *m = new;
100         arch_local_irq_restore(flags);
101         return oldval;
102 }
103
104 #endif /* CONFIG_SMP */
105
106 #define xchg(ptr, v)                                            \
107         ((__typeof__(*(ptr))) __xchg((unsigned long *)(ptr),    \
108                                      (unsigned long)(v)))
109
110 #define cmpxchg(ptr, o, n)                                      \
111         ((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
112                                         (unsigned long)(o),     \
113                                         (unsigned long)(n)))
114
115 #endif /* _ASM_CMPXCHG_H */