![]() |
|
|||
0001 /***********************license start*************** 0002 * Author: Cavium Networks 0003 * 0004 * Contact: support@caviumnetworks.com 0005 * This file is part of the OCTEON SDK 0006 * 0007 * Copyright (c) 2003-2008 Cavium Networks 0008 * 0009 * This file is free software; you can redistribute it and/or modify 0010 * it under the terms of the GNU General Public License, Version 2, as 0011 * published by the Free Software Foundation. 0012 * 0013 * This file is distributed in the hope that it will be useful, but 0014 * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 0015 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 0016 * NONINFRINGEMENT. See the GNU General Public License for more 0017 * details. 0018 * 0019 * You should have received a copy of the GNU General Public License 0020 * along with this file; if not, write to the Free Software 0021 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 0022 * or visit http://www.gnu.org/licenses/. 0023 * 0024 * This file may also be available under a different license from Cavium. 0025 * Contact Cavium Networks for more information 0026 ***********************license end**************************************/ 0027 0028 /** 0029 * Implementation of spinlocks for Octeon CVMX. Although similar in 0030 * function to Linux kernel spinlocks, they are not compatible. 0031 * Octeon CVMX spinlocks are only used to synchronize with the boot 0032 * monitor and other non-Linux programs running in the system. 0033 */ 0034 0035 #ifndef __CVMX_SPINLOCK_H__ 0036 #define __CVMX_SPINLOCK_H__ 0037 0038 #include <asm/octeon/cvmx-asm.h> 0039 0040 /* Spinlocks for Octeon */ 0041 0042 /* define these to enable recursive spinlock debugging */ 0043 /*#define CVMX_SPINLOCK_DEBUG */ 0044 0045 /** 0046 * Spinlocks for Octeon CVMX 0047 */ 0048 typedef struct { 0049 volatile uint32_t value; 0050 } cvmx_spinlock_t; 0051 0052 /* note - macros not expanded in inline ASM, so values hardcoded */ 0053 #define CVMX_SPINLOCK_UNLOCKED_VAL 0 0054 #define CVMX_SPINLOCK_LOCKED_VAL 1 0055 0056 #define CVMX_SPINLOCK_UNLOCKED_INITIALIZER {CVMX_SPINLOCK_UNLOCKED_VAL} 0057 0058 /** 0059 * Initialize a spinlock 0060 * 0061 * @lock: Lock to initialize 0062 */ 0063 static inline void cvmx_spinlock_init(cvmx_spinlock_t *lock) 0064 { 0065 lock->value = CVMX_SPINLOCK_UNLOCKED_VAL; 0066 } 0067 0068 /** 0069 * Return non-zero if the spinlock is currently locked 0070 * 0071 * @lock: Lock to check 0072 * Returns Non-zero if locked 0073 */ 0074 static inline int cvmx_spinlock_locked(cvmx_spinlock_t *lock) 0075 { 0076 return lock->value != CVMX_SPINLOCK_UNLOCKED_VAL; 0077 } 0078 0079 /** 0080 * Releases lock 0081 * 0082 * @lock: pointer to lock structure 0083 */ 0084 static inline void cvmx_spinlock_unlock(cvmx_spinlock_t *lock) 0085 { 0086 CVMX_SYNCWS; 0087 lock->value = 0; 0088 CVMX_SYNCWS; 0089 } 0090 0091 /** 0092 * Attempts to take the lock, but does not spin if lock is not available. 0093 * May take some time to acquire the lock even if it is available 0094 * due to the ll/sc not succeeding. 0095 * 0096 * @lock: pointer to lock structure 0097 * 0098 * Returns 0: lock successfully taken 0099 * 1: lock not taken, held by someone else 0100 * These return values match the Linux semantics. 0101 */ 0102 0103 static inline unsigned int cvmx_spinlock_trylock(cvmx_spinlock_t *lock) 0104 { 0105 unsigned int tmp; 0106 0107 __asm__ __volatile__(".set noreorder \n" 0108 "1: ll %[tmp], %[val] \n" 0109 /* if lock held, fail immediately */ 0110 " bnez %[tmp], 2f \n" 0111 " li %[tmp], 1 \n" 0112 " sc %[tmp], %[val] \n" 0113 " beqz %[tmp], 1b \n" 0114 " li %[tmp], 0 \n" 0115 "2: \n" 0116 ".set reorder \n" : 0117 [val] "+m"(lock->value), [tmp] "=&r"(tmp) 0118 : : "memory"); 0119 0120 return tmp != 0; /* normalize to 0 or 1 */ 0121 } 0122 0123 /** 0124 * Gets lock, spins until lock is taken 0125 * 0126 * @lock: pointer to lock structure 0127 */ 0128 static inline void cvmx_spinlock_lock(cvmx_spinlock_t *lock) 0129 { 0130 unsigned int tmp; 0131 0132 __asm__ __volatile__(".set noreorder \n" 0133 "1: ll %[tmp], %[val] \n" 0134 " bnez %[tmp], 1b \n" 0135 " li %[tmp], 1 \n" 0136 " sc %[tmp], %[val] \n" 0137 " beqz %[tmp], 1b \n" 0138 " nop \n" 0139 ".set reorder \n" : 0140 [val] "+m"(lock->value), [tmp] "=&r"(tmp) 0141 : : "memory"); 0142 0143 } 0144 0145 /** ******************************************************************** 0146 * Bit spinlocks 0147 * These spinlocks use a single bit (bit 31) of a 32 bit word for locking. 0148 * The rest of the bits in the word are left undisturbed. This enables more 0149 * compact data structures as only 1 bit is consumed for the lock. 0150 * 0151 */ 0152 0153 /** 0154 * Gets lock, spins until lock is taken 0155 * Preserves the low 31 bits of the 32 bit 0156 * word used for the lock. 0157 * 0158 * 0159 * @word: word to lock bit 31 of 0160 */ 0161 static inline void cvmx_spinlock_bit_lock(uint32_t *word) 0162 { 0163 unsigned int tmp; 0164 unsigned int sav; 0165 0166 __asm__ __volatile__(".set noreorder \n" 0167 ".set noat \n" 0168 "1: ll %[tmp], %[val] \n" 0169 " bbit1 %[tmp], 31, 1b \n" 0170 " li $at, 1 \n" 0171 " ins %[tmp], $at, 31, 1 \n" 0172 " sc %[tmp], %[val] \n" 0173 " beqz %[tmp], 1b \n" 0174 " nop \n" 0175 ".set at \n" 0176 ".set reorder \n" : 0177 [val] "+m"(*word), [tmp] "=&r"(tmp), [sav] "=&r"(sav) 0178 : : "memory"); 0179 0180 } 0181 0182 /** 0183 * Attempts to get lock, returns immediately with success/failure 0184 * Preserves the low 31 bits of the 32 bit 0185 * word used for the lock. 0186 * 0187 * 0188 * @word: word to lock bit 31 of 0189 * Returns 0: lock successfully taken 0190 * 1: lock not taken, held by someone else 0191 * These return values match the Linux semantics. 0192 */ 0193 static inline unsigned int cvmx_spinlock_bit_trylock(uint32_t *word) 0194 { 0195 unsigned int tmp; 0196 0197 __asm__ __volatile__(".set noreorder\n\t" 0198 ".set noat\n" 0199 "1: ll %[tmp], %[val] \n" 0200 /* if lock held, fail immediately */ 0201 " bbit1 %[tmp], 31, 2f \n" 0202 " li $at, 1 \n" 0203 " ins %[tmp], $at, 31, 1 \n" 0204 " sc %[tmp], %[val] \n" 0205 " beqz %[tmp], 1b \n" 0206 " li %[tmp], 0 \n" 0207 "2: \n" 0208 ".set at \n" 0209 ".set reorder \n" : 0210 [val] "+m"(*word), [tmp] "=&r"(tmp) 0211 : : "memory"); 0212 0213 return tmp != 0; /* normalize to 0 or 1 */ 0214 } 0215 0216 /** 0217 * Releases bit lock 0218 * 0219 * Unconditionally clears bit 31 of the lock word. Note that this is 0220 * done non-atomically, as this implementation assumes that the rest 0221 * of the bits in the word are protected by the lock. 0222 * 0223 * @word: word to unlock bit 31 in 0224 */ 0225 static inline void cvmx_spinlock_bit_unlock(uint32_t *word) 0226 { 0227 CVMX_SYNCWS; 0228 *word &= ~(1UL << 31); 0229 CVMX_SYNCWS; 0230 } 0231 0232 #endif /* __CVMX_SPINLOCK_H__ */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |