1/* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 * 6 * Copyright (c) 1994-1997, 99, 2000, 06, 07 Ralf Baechle (ralf@linux-mips.org) 7 * Copyright (c) 1999, 2000 Silicon Graphics, Inc. 8 */ 9#include <linux/bitops.h> 10#include <linux/irqflags.h> 11#include <linux/export.h> 12 13 14/** 15 * __mips_set_bit - Atomically set a bit in memory. This is called by 16 * set_bit() if it cannot find a faster solution. 17 * @nr: the bit to set 18 * @addr: the address to start counting from 19 */ 20void __mips_set_bit(unsigned long nr, volatile unsigned long *addr) 21{ 22 unsigned long *a = (unsigned long *)addr; 23 unsigned bit = nr & SZLONG_MASK; 24 unsigned long mask; 25 unsigned long flags; 26 27 a += nr >> SZLONG_LOG; 28 mask = 1UL << bit; 29 raw_local_irq_save(flags); 30 *a |= mask; 31 raw_local_irq_restore(flags); 32} 33EXPORT_SYMBOL(__mips_set_bit); 34 35 36/** 37 * __mips_clear_bit - Clears a bit in memory. This is called by clear_bit() if 38 * it cannot find a faster solution. 39 * @nr: Bit to clear 40 * @addr: Address to start counting from 41 */ 42void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr) 43{ 44 unsigned long *a = (unsigned long *)addr; 45 unsigned bit = nr & SZLONG_MASK; 46 unsigned long mask; 47 unsigned long flags; 48 49 a += nr >> SZLONG_LOG; 50 mask = 1UL << bit; 51 raw_local_irq_save(flags); 52 *a &= ~mask; 53 raw_local_irq_restore(flags); 54} 55EXPORT_SYMBOL(__mips_clear_bit); 56 57 58/** 59 * __mips_change_bit - Toggle a bit in memory. This is called by change_bit() 60 * if it cannot find a faster solution. 61 * @nr: Bit to change 62 * @addr: Address to start counting from 63 */ 64void __mips_change_bit(unsigned long nr, volatile unsigned long *addr) 65{ 66 unsigned long *a = (unsigned long *)addr; 67 unsigned bit = nr & SZLONG_MASK; 68 unsigned long mask; 69 unsigned long flags; 70 71 a += nr >> SZLONG_LOG; 72 mask = 1UL << bit; 73 raw_local_irq_save(flags); 74 *a ^= mask; 75 raw_local_irq_restore(flags); 76} 77EXPORT_SYMBOL(__mips_change_bit); 78 79 80/** 81 * __mips_test_and_set_bit - Set a bit and return its old value. This is 82 * called by test_and_set_bit() if it cannot find a faster solution. 83 * @nr: Bit to set 84 * @addr: Address to count from 85 */ 86int __mips_test_and_set_bit(unsigned long nr, 87 volatile unsigned long *addr) 88{ 89 unsigned long *a = (unsigned long *)addr; 90 unsigned bit = nr & SZLONG_MASK; 91 unsigned long mask; 92 unsigned long flags; 93 int res; 94 95 a += nr >> SZLONG_LOG; 96 mask = 1UL << bit; 97 raw_local_irq_save(flags); 98 res = (mask & *a) != 0; 99 *a |= mask; 100 raw_local_irq_restore(flags); 101 return res; 102} 103EXPORT_SYMBOL(__mips_test_and_set_bit); 104 105 106/** 107 * __mips_test_and_set_bit_lock - Set a bit and return its old value. This is 108 * called by test_and_set_bit_lock() if it cannot find a faster solution. 109 * @nr: Bit to set 110 * @addr: Address to count from 111 */ 112int __mips_test_and_set_bit_lock(unsigned long nr, 113 volatile unsigned long *addr) 114{ 115 unsigned long *a = (unsigned long *)addr; 116 unsigned bit = nr & SZLONG_MASK; 117 unsigned long mask; 118 unsigned long flags; 119 int res; 120 121 a += nr >> SZLONG_LOG; 122 mask = 1UL << bit; 123 raw_local_irq_save(flags); 124 res = (mask & *a) != 0; 125 *a |= mask; 126 raw_local_irq_restore(flags); 127 return res; 128} 129EXPORT_SYMBOL(__mips_test_and_set_bit_lock); 130 131 132/** 133 * __mips_test_and_clear_bit - Clear a bit and return its old value. This is 134 * called by test_and_clear_bit() if it cannot find a faster solution. 135 * @nr: Bit to clear 136 * @addr: Address to count from 137 */ 138int __mips_test_and_clear_bit(unsigned long nr, volatile unsigned long *addr) 139{ 140 unsigned long *a = (unsigned long *)addr; 141 unsigned bit = nr & SZLONG_MASK; 142 unsigned long mask; 143 unsigned long flags; 144 int res; 145 146 a += nr >> SZLONG_LOG; 147 mask = 1UL << bit; 148 raw_local_irq_save(flags); 149 res = (mask & *a) != 0; 150 *a &= ~mask; 151 raw_local_irq_restore(flags); 152 return res; 153} 154EXPORT_SYMBOL(__mips_test_and_clear_bit); 155 156 157/** 158 * __mips_test_and_change_bit - Change a bit and return its old value. This is 159 * called by test_and_change_bit() if it cannot find a faster solution. 160 * @nr: Bit to change 161 * @addr: Address to count from 162 */ 163int __mips_test_and_change_bit(unsigned long nr, volatile unsigned long *addr) 164{ 165 unsigned long *a = (unsigned long *)addr; 166 unsigned bit = nr & SZLONG_MASK; 167 unsigned long mask; 168 unsigned long flags; 169 int res; 170 171 a += nr >> SZLONG_LOG; 172 mask = 1UL << bit; 173 raw_local_irq_save(flags); 174 res = (mask & *a) != 0; 175 *a ^= mask; 176 raw_local_irq_restore(flags); 177 return res; 178} 179EXPORT_SYMBOL(__mips_test_and_change_bit); 180