• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   */
__mips_set_bit(unsigned long nr,volatile unsigned long * addr)20  void __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  }
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   */
__mips_clear_bit(unsigned long nr,volatile unsigned long * addr)42  void __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  }
55  EXPORT_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   */
__mips_change_bit(unsigned long nr,volatile unsigned long * addr)64  void __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  }
77  EXPORT_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   */
__mips_test_and_set_bit(unsigned long nr,volatile unsigned long * addr)86  int __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  }
103  EXPORT_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   */
__mips_test_and_set_bit_lock(unsigned long nr,volatile unsigned long * addr)112  int __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  }
129  EXPORT_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   */
__mips_test_and_clear_bit(unsigned long nr,volatile unsigned long * addr)138  int __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  }
154  EXPORT_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   */
__mips_test_and_change_bit(unsigned long nr,volatile unsigned long * addr)163  int __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  }
179  EXPORT_SYMBOL(__mips_test_and_change_bit);
180