~ubuntu-branches/ubuntu/saucy/linux-n900/saucy

« back to all changes in this revision

Viewing changes to arch/mips/include/asm/octeon/cvmx-spinlock.h

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Poirier
  • Date: 2011-02-18 09:43:31 UTC
  • Revision ID: james.westby@ubuntu.com-20110218094331-eyubsja4f9k0yhmq
Tags: 2.6.35-1.1
Initial release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***********************license start***************
 
2
 * Author: Cavium Networks
 
3
 *
 
4
 * Contact: support@caviumnetworks.com
 
5
 * This file is part of the OCTEON SDK
 
6
 *
 
7
 * Copyright (c) 2003-2008 Cavium Networks
 
8
 *
 
9
 * This file is free software; you can redistribute it and/or modify
 
10
 * it under the terms of the GNU General Public License, Version 2, as
 
11
 * published by the Free Software Foundation.
 
12
 *
 
13
 * This file is distributed in the hope that it will be useful, but
 
14
 * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
 
15
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
 
16
 * NONINFRINGEMENT.  See the GNU General Public License for more
 
17
 * details.
 
18
 *
 
19
 * You should have received a copy of the GNU General Public License
 
20
 * along with this file; if not, write to the Free Software
 
21
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 
22
 * or visit http://www.gnu.org/licenses/.
 
23
 *
 
24
 * This file may also be available under a different license from Cavium.
 
25
 * Contact Cavium Networks for more information
 
26
 ***********************license end**************************************/
 
27
 
 
28
/**
 
29
 * Implementation of spinlocks for Octeon CVMX.  Although similar in
 
30
 * function to Linux kernel spinlocks, they are not compatible.
 
31
 * Octeon CVMX spinlocks are only used to synchronize with the boot
 
32
 * monitor and other non-Linux programs running in the system.
 
33
 */
 
34
 
 
35
#ifndef __CVMX_SPINLOCK_H__
 
36
#define __CVMX_SPINLOCK_H__
 
37
 
 
38
#include "cvmx-asm.h"
 
39
 
 
40
/* Spinlocks for Octeon */
 
41
 
 
42
/* define these to enable recursive spinlock debugging */
 
43
/*#define CVMX_SPINLOCK_DEBUG */
 
44
 
 
45
/**
 
46
 * Spinlocks for Octeon CVMX
 
47
 */
 
48
typedef struct {
 
49
        volatile uint32_t value;
 
50
} cvmx_spinlock_t;
 
51
 
 
52
/* note - macros not expanded in inline ASM, so values hardcoded */
 
53
#define  CVMX_SPINLOCK_UNLOCKED_VAL  0
 
54
#define  CVMX_SPINLOCK_LOCKED_VAL    1
 
55
 
 
56
#define CVMX_SPINLOCK_UNLOCKED_INITIALIZER  {CVMX_SPINLOCK_UNLOCKED_VAL}
 
57
 
 
58
/**
 
59
 * Initialize a spinlock
 
60
 *
 
61
 * @lock:   Lock to initialize
 
62
 */
 
63
static inline void cvmx_spinlock_init(cvmx_spinlock_t *lock)
 
64
{
 
65
        lock->value = CVMX_SPINLOCK_UNLOCKED_VAL;
 
66
}
 
67
 
 
68
/**
 
69
 * Return non-zero if the spinlock is currently locked
 
70
 *
 
71
 * @lock:   Lock to check
 
72
 * Returns Non-zero if locked
 
73
 */
 
74
static inline int cvmx_spinlock_locked(cvmx_spinlock_t *lock)
 
75
{
 
76
        return lock->value != CVMX_SPINLOCK_UNLOCKED_VAL;
 
77
}
 
78
 
 
79
/**
 
80
 * Releases lock
 
81
 *
 
82
 * @lock:   pointer to lock structure
 
83
 */
 
84
static inline void cvmx_spinlock_unlock(cvmx_spinlock_t *lock)
 
85
{
 
86
        CVMX_SYNCWS;
 
87
        lock->value = 0;
 
88
        CVMX_SYNCWS;
 
89
}
 
90
 
 
91
/**
 
92
 * Attempts to take the lock, but does not spin if lock is not available.
 
93
 * May take some time to acquire the lock even if it is available
 
94
 * due to the ll/sc not succeeding.
 
95
 *
 
96
 * @lock:   pointer to lock structure
 
97
 *
 
98
 * Returns 0: lock successfully taken
 
99
 *         1: lock not taken, held by someone else
 
100
 * These return values match the Linux semantics.
 
101
 */
 
102
 
 
103
static inline unsigned int cvmx_spinlock_trylock(cvmx_spinlock_t *lock)
 
104
{
 
105
        unsigned int tmp;
 
106
 
 
107
        __asm__ __volatile__(".set noreorder         \n"
 
108
                             "1: ll   %[tmp], %[val] \n"
 
109
                        /* if lock held, fail immediately */
 
110
                             "   bnez %[tmp], 2f     \n"
 
111
                             "   li   %[tmp], 1      \n"
 
112
                             "   sc   %[tmp], %[val] \n"
 
113
                             "   beqz %[tmp], 1b     \n"
 
114
                             "   li   %[tmp], 0      \n"
 
115
                             "2:                     \n"
 
116
                             ".set reorder           \n" :
 
117
                        [val] "+m"(lock->value), [tmp] "=&r"(tmp)
 
118
                             : : "memory");
 
119
 
 
120
        return tmp != 0;                /* normalize to 0 or 1 */
 
121
}
 
122
 
 
123
/**
 
124
 * Gets lock, spins until lock is taken
 
125
 *
 
126
 * @lock:   pointer to lock structure
 
127
 */
 
128
static inline void cvmx_spinlock_lock(cvmx_spinlock_t *lock)
 
129
{
 
130
        unsigned int tmp;
 
131
 
 
132
        __asm__ __volatile__(".set noreorder         \n"
 
133
                             "1: ll   %[tmp], %[val]  \n"
 
134
                             "   bnez %[tmp], 1b     \n"
 
135
                             "   li   %[tmp], 1      \n"
 
136
                             "   sc   %[tmp], %[val] \n"
 
137
                             "   beqz %[tmp], 1b     \n"
 
138
                             "   nop                \n"
 
139
                             ".set reorder           \n" :
 
140
                        [val] "+m"(lock->value), [tmp] "=&r"(tmp)
 
141
                        : : "memory");
 
142
 
 
143
}
 
144
 
 
145
/** ********************************************************************
 
146
 * Bit spinlocks
 
147
 * These spinlocks use a single bit (bit 31) of a 32 bit word for locking.
 
148
 * The rest of the bits in the word are left undisturbed.  This enables more
 
149
 * compact data structures as only 1 bit is consumed for the lock.
 
150
 *
 
151
 */
 
152
 
 
153
/**
 
154
 * Gets lock, spins until lock is taken
 
155
 * Preserves the low 31 bits of the 32 bit
 
156
 * word used for the lock.
 
157
 *
 
158
 *
 
159
 * @word:  word to lock bit 31 of
 
160
 */
 
161
static inline void cvmx_spinlock_bit_lock(uint32_t *word)
 
162
{
 
163
        unsigned int tmp;
 
164
        unsigned int sav;
 
165
 
 
166
        __asm__ __volatile__(".set noreorder         \n"
 
167
                             ".set noat              \n"
 
168
                             "1: ll    %[tmp], %[val]  \n"
 
169
                             "   bbit1 %[tmp], 31, 1b    \n"
 
170
                             "   li    $at, 1      \n"
 
171
                             "   ins   %[tmp], $at, 31, 1  \n"
 
172
                             "   sc    %[tmp], %[val] \n"
 
173
                             "   beqz  %[tmp], 1b     \n"
 
174
                             "   nop                \n"
 
175
                             ".set at              \n"
 
176
                             ".set reorder           \n" :
 
177
                        [val] "+m"(*word), [tmp] "=&r"(tmp), [sav] "=&r"(sav)
 
178
                             : : "memory");
 
179
 
 
180
}
 
181
 
 
182
/**
 
183
 * Attempts to get lock, returns immediately with success/failure
 
184
 * Preserves the low 31 bits of the 32 bit
 
185
 * word used for the lock.
 
186
 *
 
187
 *
 
188
 * @word:  word to lock bit 31 of
 
189
 * Returns 0: lock successfully taken
 
190
 *         1: lock not taken, held by someone else
 
191
 * These return values match the Linux semantics.
 
192
 */
 
193
static inline unsigned int cvmx_spinlock_bit_trylock(uint32_t *word)
 
194
{
 
195
        unsigned int tmp;
 
196
 
 
197
        __asm__ __volatile__(".set noreorder\n\t"
 
198
                             ".set noat\n"
 
199
                             "1: ll    %[tmp], %[val] \n"
 
200
                        /* if lock held, fail immediately */
 
201
                             "   bbit1 %[tmp], 31, 2f     \n"
 
202
                             "   li    $at, 1      \n"
 
203
                             "   ins   %[tmp], $at, 31, 1  \n"
 
204
                             "   sc    %[tmp], %[val] \n"
 
205
                             "   beqz  %[tmp], 1b     \n"
 
206
                             "   li    %[tmp], 0      \n"
 
207
                             "2:                     \n"
 
208
                             ".set at              \n"
 
209
                             ".set reorder           \n" :
 
210
                        [val] "+m"(*word), [tmp] "=&r"(tmp)
 
211
                        : : "memory");
 
212
 
 
213
        return tmp != 0;                /* normalize to 0 or 1 */
 
214
}
 
215
 
 
216
/**
 
217
 * Releases bit lock
 
218
 *
 
219
 * Unconditionally clears bit 31 of the lock word.  Note that this is
 
220
 * done non-atomically, as this implementation assumes that the rest
 
221
 * of the bits in the word are protected by the lock.
 
222
 *
 
223
 * @word:  word to unlock bit 31 in
 
224
 */
 
225
static inline void cvmx_spinlock_bit_unlock(uint32_t *word)
 
226
{
 
227
        CVMX_SYNCWS;
 
228
        *word &= ~(1UL << 31);
 
229
        CVMX_SYNCWS;
 
230
}
 
231
 
 
232
#endif /* __CVMX_SPINLOCK_H__ */