root/arch/mips/include/asm/octeon/cvmx-spinlock.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. cvmx_spinlock_init
  2. cvmx_spinlock_locked
  3. cvmx_spinlock_unlock
  4. cvmx_spinlock_trylock
  5. cvmx_spinlock_lock
  6. cvmx_spinlock_bit_lock
  7. cvmx_spinlock_bit_trylock
  8. cvmx_spinlock_bit_unlock

   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 <asm/octeon/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__ */

/* [<][>][^][v][top][bottom][index][help] */