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/bits.h> 11 #include <linux/irqflags.h> 12 #include <linux/export.h> 13 14 15 /** 16 * __mips_set_bit - Atomically set a bit in memory. This is called by 17 * set_bit() if it cannot find a faster solution. 18 * @nr: the bit to set 19 * @addr: the address to start counting from 20 */ 21 void __mips_set_bit(unsigned long nr, volatile unsigned long *addr) 22 { 23 volatile unsigned long *a = &addr[BIT_WORD(nr)]; 24 unsigned int bit = nr % BITS_PER_LONG; 25 unsigned long mask; 26 unsigned long flags; 27 28 mask = 1UL << bit; 29 raw_local_irq_save(flags); 30 *a |= mask; 31 raw_local_irq_restore(flags); 32 } 33 EXPORT_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 */ 42 void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr) 43 { 44 volatile unsigned long *a = &addr[BIT_WORD(nr)]; 45 unsigned int bit = nr % BITS_PER_LONG; 46 unsigned long mask; 47 unsigned long flags; 48 49 mask = 1UL << bit; 50 raw_local_irq_save(flags); 51 *a &= ~mask; 52 raw_local_irq_restore(flags); 53 } 54 EXPORT_SYMBOL(__mips_clear_bit); 55 56 57 /** 58 * __mips_change_bit - Toggle a bit in memory. This is called by change_bit() 59 * if it cannot find a faster solution. 60 * @nr: Bit to change 61 * @addr: Address to start counting from 62 */ 63 void __mips_change_bit(unsigned long nr, volatile unsigned long *addr) 64 { 65 volatile unsigned long *a = &addr[BIT_WORD(nr)]; 66 unsigned int bit = nr % BITS_PER_LONG; 67 unsigned long mask; 68 unsigned long flags; 69 70 mask = 1UL << bit; 71 raw_local_irq_save(flags); 72 *a ^= mask; 73 raw_local_irq_restore(flags); 74 } 75 EXPORT_SYMBOL(__mips_change_bit); 76 77 78 /** 79 * __mips_test_and_set_bit_lock - Set a bit and return its old value. This is 80 * called by test_and_set_bit_lock() if it cannot find a faster solution. 81 * @nr: Bit to set 82 * @addr: Address to count from 83 */ 84 int __mips_test_and_set_bit_lock(unsigned long nr, 85 volatile unsigned long *addr) 86 { 87 volatile unsigned long *a = &addr[BIT_WORD(nr)]; 88 unsigned int bit = nr % BITS_PER_LONG; 89 unsigned long mask; 90 unsigned long flags; 91 int res; 92 93 mask = 1UL << bit; 94 raw_local_irq_save(flags); 95 res = (mask & *a) != 0; 96 *a |= mask; 97 raw_local_irq_restore(flags); 98 return res; 99 } 100 EXPORT_SYMBOL(__mips_test_and_set_bit_lock); 101 102 103 /** 104 * __mips_test_and_clear_bit - Clear a bit and return its old value. This is 105 * called by test_and_clear_bit() if it cannot find a faster solution. 106 * @nr: Bit to clear 107 * @addr: Address to count from 108 */ 109 int __mips_test_and_clear_bit(unsigned long nr, volatile unsigned long *addr) 110 { 111 volatile unsigned long *a = &addr[BIT_WORD(nr)]; 112 unsigned int bit = nr % BITS_PER_LONG; 113 unsigned long mask; 114 unsigned long flags; 115 int res; 116 117 mask = 1UL << bit; 118 raw_local_irq_save(flags); 119 res = (mask & *a) != 0; 120 *a &= ~mask; 121 raw_local_irq_restore(flags); 122 return res; 123 } 124 EXPORT_SYMBOL(__mips_test_and_clear_bit); 125 126 127 /** 128 * __mips_test_and_change_bit - Change a bit and return its old value. This is 129 * called by test_and_change_bit() if it cannot find a faster solution. 130 * @nr: Bit to change 131 * @addr: Address to count from 132 */ 133 int __mips_test_and_change_bit(unsigned long nr, volatile unsigned long *addr) 134 { 135 volatile unsigned long *a = &addr[BIT_WORD(nr)]; 136 unsigned int bit = nr % BITS_PER_LONG; 137 unsigned long mask; 138 unsigned long flags; 139 int res; 140 141 mask = 1UL << bit; 142 raw_local_irq_save(flags); 143 res = (mask & *a) != 0; 144 *a ^= mask; 145 raw_local_irq_restore(flags); 146 return res; 147 } 148 EXPORT_SYMBOL(__mips_test_and_change_bit); 149 150 bool __mips_xor_is_negative_byte(unsigned long mask, 151 volatile unsigned long *addr) 152 { 153 unsigned long flags; 154 unsigned long data; 155 156 raw_local_irq_save(flags); 157 data = *addr; 158 *addr = data ^ mask; 159 raw_local_irq_restore(flags); 160 161 return (data & BIT(7)) != 0; 162 } 163