diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /arch/mips/lib | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'arch/mips/lib')
-rw-r--r-- | arch/mips/lib/Makefile | 25 | ||||
-rw-r--r-- | arch/mips/lib/bitops.c | 179 | ||||
-rw-r--r-- | arch/mips/lib/delay.c | 6 | ||||
-rw-r--r-- | arch/mips/lib/dump_tlb.c | 4 | ||||
-rw-r--r-- | arch/mips/lib/iomap-pci.c | 30 | ||||
-rw-r--r-- | arch/mips/lib/memcpy.S | 11 | ||||
-rw-r--r-- | arch/mips/lib/mips-atomic.c | 176 |
7 files changed, 51 insertions, 380 deletions
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index eeddc58802e..b2cad4fd5fc 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile | |||
@@ -2,16 +2,33 @@ | |||
2 | # Makefile for MIPS-specific library files.. | 2 | # Makefile for MIPS-specific library files.. |
3 | # | 3 | # |
4 | 4 | ||
5 | lib-y += bitops.o csum_partial.o delay.o memcpy.o memset.o \ | 5 | lib-y += csum_partial.o delay.o memcpy.o memcpy-inatomic.o memset.o \ |
6 | mips-atomic.o strlen_user.o strncpy_user.o \ | 6 | strlen_user.o strncpy_user.o strnlen_user.o uncached.o |
7 | strnlen_user.o uncached.o | ||
8 | 7 | ||
9 | obj-y += iomap.o | 8 | obj-y += iomap.o |
10 | obj-$(CONFIG_PCI) += iomap-pci.o | 9 | obj-$(CONFIG_PCI) += iomap-pci.o |
11 | 10 | ||
12 | obj-$(CONFIG_CPU_GENERIC_DUMP_TLB) += dump_tlb.o | 11 | obj-$(CONFIG_CPU_LOONGSON2) += dump_tlb.o |
12 | obj-$(CONFIG_CPU_MIPS32) += dump_tlb.o | ||
13 | obj-$(CONFIG_CPU_MIPS64) += dump_tlb.o | ||
14 | obj-$(CONFIG_CPU_NEVADA) += dump_tlb.o | ||
15 | obj-$(CONFIG_CPU_R10000) += dump_tlb.o | ||
13 | obj-$(CONFIG_CPU_R3000) += r3k_dump_tlb.o | 16 | obj-$(CONFIG_CPU_R3000) += r3k_dump_tlb.o |
17 | obj-$(CONFIG_CPU_R4300) += dump_tlb.o | ||
18 | obj-$(CONFIG_CPU_R4X00) += dump_tlb.o | ||
19 | obj-$(CONFIG_CPU_R5000) += dump_tlb.o | ||
20 | obj-$(CONFIG_CPU_R5432) += dump_tlb.o | ||
21 | obj-$(CONFIG_CPU_R5500) += dump_tlb.o | ||
22 | obj-$(CONFIG_CPU_R6000) += | ||
23 | obj-$(CONFIG_CPU_R8000) += | ||
24 | obj-$(CONFIG_CPU_RM7000) += dump_tlb.o | ||
25 | obj-$(CONFIG_CPU_RM9000) += dump_tlb.o | ||
26 | obj-$(CONFIG_CPU_SB1) += dump_tlb.o | ||
14 | obj-$(CONFIG_CPU_TX39XX) += r3k_dump_tlb.o | 27 | obj-$(CONFIG_CPU_TX39XX) += r3k_dump_tlb.o |
28 | obj-$(CONFIG_CPU_TX49XX) += dump_tlb.o | ||
29 | obj-$(CONFIG_CPU_VR41XX) += dump_tlb.o | ||
30 | obj-$(CONFIG_CPU_CAVIUM_OCTEON) += dump_tlb.o | ||
31 | obj-$(CONFIG_CPU_XLR) += dump_tlb.o | ||
15 | 32 | ||
16 | # libgcc-style stuff needed in the kernel | 33 | # libgcc-style stuff needed in the kernel |
17 | obj-y += ashldi3.o ashrdi3.o cmpdi2.o lshrdi3.o ucmpdi2.o | 34 | obj-y += ashldi3.o ashrdi3.o cmpdi2.o lshrdi3.o ucmpdi2.o |
diff --git a/arch/mips/lib/bitops.c b/arch/mips/lib/bitops.c deleted file mode 100644 index 239a9c957b0..00000000000 --- a/arch/mips/lib/bitops.c +++ /dev/null | |||
@@ -1,179 +0,0 @@ | |||
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 | */ | ||
20 | void __mips_set_bit(unsigned long nr, volatile unsigned long *addr) | ||
21 | { | ||
22 | volatile unsigned long *a = 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 | */ | ||
42 | void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr) | ||
43 | { | ||
44 | volatile unsigned long *a = 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 | */ | ||
64 | void __mips_change_bit(unsigned long nr, volatile unsigned long *addr) | ||
65 | { | ||
66 | volatile unsigned long *a = 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 | */ | ||
86 | int __mips_test_and_set_bit(unsigned long nr, | ||
87 | volatile unsigned long *addr) | ||
88 | { | ||
89 | volatile unsigned long *a = addr; | ||
90 | unsigned bit = nr & SZLONG_MASK; | ||
91 | unsigned long mask; | ||
92 | unsigned long flags; | ||
93 | unsigned long res; | ||
94 | |||
95 | a += nr >> SZLONG_LOG; | ||
96 | mask = 1UL << bit; | ||
97 | raw_local_irq_save(flags); | ||
98 | res = (mask & *a); | ||
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 | */ | ||
112 | int __mips_test_and_set_bit_lock(unsigned long nr, | ||
113 | volatile unsigned long *addr) | ||
114 | { | ||
115 | volatile unsigned long *a = addr; | ||
116 | unsigned bit = nr & SZLONG_MASK; | ||
117 | unsigned long mask; | ||
118 | unsigned long flags; | ||
119 | unsigned long res; | ||
120 | |||
121 | a += nr >> SZLONG_LOG; | ||
122 | mask = 1UL << bit; | ||
123 | raw_local_irq_save(flags); | ||
124 | res = (mask & *a); | ||
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 | */ | ||
138 | int __mips_test_and_clear_bit(unsigned long nr, volatile unsigned long *addr) | ||
139 | { | ||
140 | volatile unsigned long *a = addr; | ||
141 | unsigned bit = nr & SZLONG_MASK; | ||
142 | unsigned long mask; | ||
143 | unsigned long flags; | ||
144 | unsigned long res; | ||
145 | |||
146 | a += nr >> SZLONG_LOG; | ||
147 | mask = 1UL << bit; | ||
148 | raw_local_irq_save(flags); | ||
149 | res = (mask & *a); | ||
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 | */ | ||
163 | int __mips_test_and_change_bit(unsigned long nr, volatile unsigned long *addr) | ||
164 | { | ||
165 | volatile unsigned long *a = addr; | ||
166 | unsigned bit = nr & SZLONG_MASK; | ||
167 | unsigned long mask; | ||
168 | unsigned long flags; | ||
169 | unsigned long res; | ||
170 | |||
171 | a += nr >> SZLONG_LOG; | ||
172 | mask = 1UL << bit; | ||
173 | raw_local_irq_save(flags); | ||
174 | res = (mask & *a); | ||
175 | *a ^= mask; | ||
176 | raw_local_irq_restore(flags); | ||
177 | return res; | ||
178 | } | ||
179 | EXPORT_SYMBOL(__mips_test_and_change_bit); | ||
diff --git a/arch/mips/lib/delay.c b/arch/mips/lib/delay.c index dc81ca8dc0d..5995969e8c4 100644 --- a/arch/mips/lib/delay.c +++ b/arch/mips/lib/delay.c | |||
@@ -15,17 +15,13 @@ | |||
15 | #include <asm/compiler.h> | 15 | #include <asm/compiler.h> |
16 | #include <asm/war.h> | 16 | #include <asm/war.h> |
17 | 17 | ||
18 | void __delay(unsigned long loops) | 18 | inline void __delay(unsigned int loops) |
19 | { | 19 | { |
20 | __asm__ __volatile__ ( | 20 | __asm__ __volatile__ ( |
21 | " .set noreorder \n" | 21 | " .set noreorder \n" |
22 | " .align 3 \n" | 22 | " .align 3 \n" |
23 | "1: bnez %0, 1b \n" | 23 | "1: bnez %0, 1b \n" |
24 | #if __SIZEOF_LONG__ == 4 | ||
25 | " subu %0, 1 \n" | 24 | " subu %0, 1 \n" |
26 | #else | ||
27 | " dsubu %0, 1 \n" | ||
28 | #endif | ||
29 | " .set reorder \n" | 25 | " .set reorder \n" |
30 | : "=r" (loops) | 26 | : "=r" (loops) |
31 | : "0" (loops)); | 27 | : "0" (loops)); |
diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c index a99c1d3fc56..3f69725556a 100644 --- a/arch/mips/lib/dump_tlb.c +++ b/arch/mips/lib/dump_tlb.c | |||
@@ -50,9 +50,8 @@ static void dump_tlb(int first, int last) | |||
50 | { | 50 | { |
51 | unsigned long s_entryhi, entryhi, asid; | 51 | unsigned long s_entryhi, entryhi, asid; |
52 | unsigned long long entrylo0, entrylo1; | 52 | unsigned long long entrylo0, entrylo1; |
53 | unsigned int s_index, s_pagemask, pagemask, c0, c1, i; | 53 | unsigned int s_index, pagemask, c0, c1, i; |
54 | 54 | ||
55 | s_pagemask = read_c0_pagemask(); | ||
56 | s_entryhi = read_c0_entryhi(); | 55 | s_entryhi = read_c0_entryhi(); |
57 | s_index = read_c0_index(); | 56 | s_index = read_c0_index(); |
58 | asid = s_entryhi & 0xff; | 57 | asid = s_entryhi & 0xff; |
@@ -104,7 +103,6 @@ static void dump_tlb(int first, int last) | |||
104 | 103 | ||
105 | write_c0_entryhi(s_entryhi); | 104 | write_c0_entryhi(s_entryhi); |
106 | write_c0_index(s_index); | 105 | write_c0_index(s_index); |
107 | write_c0_pagemask(s_pagemask); | ||
108 | } | 106 | } |
109 | 107 | ||
110 | void dump_tlb_all(void) | 108 | void dump_tlb_all(void) |
diff --git a/arch/mips/lib/iomap-pci.c b/arch/mips/lib/iomap-pci.c index fd35daa4531..2ab899c4b4c 100644 --- a/arch/mips/lib/iomap-pci.c +++ b/arch/mips/lib/iomap-pci.c | |||
@@ -10,8 +10,8 @@ | |||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <asm/io.h> | 11 | #include <asm/io.h> |
12 | 12 | ||
13 | void __iomem *__pci_ioport_map(struct pci_dev *dev, | 13 | static void __iomem *ioport_map_pci(struct pci_dev *dev, |
14 | unsigned long port, unsigned int nr) | 14 | unsigned long port, unsigned int nr) |
15 | { | 15 | { |
16 | struct pci_controller *ctrl = dev->bus->sysdata; | 16 | struct pci_controller *ctrl = dev->bus->sysdata; |
17 | unsigned long base = ctrl->io_map_base; | 17 | unsigned long base = ctrl->io_map_base; |
@@ -40,6 +40,32 @@ void __iomem *__pci_ioport_map(struct pci_dev *dev, | |||
40 | return (void __iomem *) (ctrl->io_map_base + port); | 40 | return (void __iomem *) (ctrl->io_map_base + port); |
41 | } | 41 | } |
42 | 42 | ||
43 | /* | ||
44 | * Create a virtual mapping cookie for a PCI BAR (memory or IO) | ||
45 | */ | ||
46 | void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) | ||
47 | { | ||
48 | resource_size_t start = pci_resource_start(dev, bar); | ||
49 | resource_size_t len = pci_resource_len(dev, bar); | ||
50 | unsigned long flags = pci_resource_flags(dev, bar); | ||
51 | |||
52 | if (!len || !start) | ||
53 | return NULL; | ||
54 | if (maxlen && len > maxlen) | ||
55 | len = maxlen; | ||
56 | if (flags & IORESOURCE_IO) | ||
57 | return ioport_map_pci(dev, start, len); | ||
58 | if (flags & IORESOURCE_MEM) { | ||
59 | if (flags & IORESOURCE_CACHEABLE) | ||
60 | return ioremap(start, len); | ||
61 | return ioremap_nocache(start, len); | ||
62 | } | ||
63 | /* What? */ | ||
64 | return NULL; | ||
65 | } | ||
66 | |||
67 | EXPORT_SYMBOL(pci_iomap); | ||
68 | |||
43 | void pci_iounmap(struct pci_dev *dev, void __iomem * addr) | 69 | void pci_iounmap(struct pci_dev *dev, void __iomem * addr) |
44 | { | 70 | { |
45 | iounmap(addr); | 71 | iounmap(addr); |
diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S index 65192c06781..56a1f85a1ce 100644 --- a/arch/mips/lib/memcpy.S +++ b/arch/mips/lib/memcpy.S | |||
@@ -183,14 +183,6 @@ | |||
183 | #endif | 183 | #endif |
184 | 184 | ||
185 | /* | 185 | /* |
186 | * t6 is used as a flag to note inatomic mode. | ||
187 | */ | ||
188 | LEAF(__copy_user_inatomic) | ||
189 | b __copy_user_common | ||
190 | li t6, 1 | ||
191 | END(__copy_user_inatomic) | ||
192 | |||
193 | /* | ||
194 | * A combined memcpy/__copy_user | 186 | * A combined memcpy/__copy_user |
195 | * __copy_user sets len to 0 for success; else to an upper bound of | 187 | * __copy_user sets len to 0 for success; else to an upper bound of |
196 | * the number of uncopied bytes. | 188 | * the number of uncopied bytes. |
@@ -201,8 +193,6 @@ LEAF(memcpy) /* a0=dst a1=src a2=len */ | |||
201 | move v0, dst /* return value */ | 193 | move v0, dst /* return value */ |
202 | .L__memcpy: | 194 | .L__memcpy: |
203 | FEXPORT(__copy_user) | 195 | FEXPORT(__copy_user) |
204 | li t6, 0 /* not inatomic */ | ||
205 | __copy_user_common: | ||
206 | /* | 196 | /* |
207 | * Note: dst & src may be unaligned, len may be 0 | 197 | * Note: dst & src may be unaligned, len may be 0 |
208 | * Temps | 198 | * Temps |
@@ -468,7 +458,6 @@ EXC( lb t1, 0(src), .Ll_exc) | |||
468 | LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address | 458 | LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address |
469 | nop | 459 | nop |
470 | SUB len, AT, t0 # len number of uncopied bytes | 460 | SUB len, AT, t0 # len number of uncopied bytes |
471 | bnez t6, .Ldone /* Skip the zeroing part if inatomic */ | ||
472 | /* | 461 | /* |
473 | * Here's where we rely on src and dst being incremented in tandem, | 462 | * Here's where we rely on src and dst being incremented in tandem, |
474 | * See (3) above. | 463 | * See (3) above. |
diff --git a/arch/mips/lib/mips-atomic.c b/arch/mips/lib/mips-atomic.c deleted file mode 100644 index cd160be3ce4..00000000000 --- a/arch/mips/lib/mips-atomic.c +++ /dev/null | |||
@@ -1,176 +0,0 @@ | |||
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, 95, 96, 97, 98, 99, 2003 by Ralf Baechle | ||
7 | * Copyright (C) 1996 by Paul M. Antoine | ||
8 | * Copyright (C) 1999 Silicon Graphics | ||
9 | * Copyright (C) 2000 MIPS Technologies, Inc. | ||
10 | */ | ||
11 | #include <asm/irqflags.h> | ||
12 | #include <asm/hazards.h> | ||
13 | #include <linux/compiler.h> | ||
14 | #include <linux/preempt.h> | ||
15 | #include <linux/export.h> | ||
16 | |||
17 | #if !defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT_SMTC) | ||
18 | |||
19 | /* | ||
20 | * For cli() we have to insert nops to make sure that the new value | ||
21 | * has actually arrived in the status register before the end of this | ||
22 | * macro. | ||
23 | * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs | ||
24 | * no nops at all. | ||
25 | */ | ||
26 | /* | ||
27 | * For TX49, operating only IE bit is not enough. | ||
28 | * | ||
29 | * If mfc0 $12 follows store and the mfc0 is last instruction of a | ||
30 | * page and fetching the next instruction causes TLB miss, the result | ||
31 | * of the mfc0 might wrongly contain EXL bit. | ||
32 | * | ||
33 | * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008 | ||
34 | * | ||
35 | * Workaround: mask EXL bit of the result or place a nop before mfc0. | ||
36 | */ | ||
37 | __asm__( | ||
38 | " .macro arch_local_irq_disable\n" | ||
39 | " .set push \n" | ||
40 | " .set noat \n" | ||
41 | #ifdef CONFIG_MIPS_MT_SMTC | ||
42 | " mfc0 $1, $2, 1 \n" | ||
43 | " ori $1, 0x400 \n" | ||
44 | " .set noreorder \n" | ||
45 | " mtc0 $1, $2, 1 \n" | ||
46 | #elif defined(CONFIG_CPU_MIPSR2) | ||
47 | /* see irqflags.h for inline function */ | ||
48 | #else | ||
49 | " mfc0 $1,$12 \n" | ||
50 | " ori $1,0x1f \n" | ||
51 | " xori $1,0x1f \n" | ||
52 | " .set noreorder \n" | ||
53 | " mtc0 $1,$12 \n" | ||
54 | #endif | ||
55 | " irq_disable_hazard \n" | ||
56 | " .set pop \n" | ||
57 | " .endm \n"); | ||
58 | |||
59 | notrace void arch_local_irq_disable(void) | ||
60 | { | ||
61 | preempt_disable(); | ||
62 | __asm__ __volatile__( | ||
63 | "arch_local_irq_disable" | ||
64 | : /* no outputs */ | ||
65 | : /* no inputs */ | ||
66 | : "memory"); | ||
67 | preempt_enable(); | ||
68 | } | ||
69 | EXPORT_SYMBOL(arch_local_irq_disable); | ||
70 | |||
71 | |||
72 | __asm__( | ||
73 | " .macro arch_local_irq_save result \n" | ||
74 | " .set push \n" | ||
75 | " .set reorder \n" | ||
76 | " .set noat \n" | ||
77 | #ifdef CONFIG_MIPS_MT_SMTC | ||
78 | " mfc0 \\result, $2, 1 \n" | ||
79 | " ori $1, \\result, 0x400 \n" | ||
80 | " .set noreorder \n" | ||
81 | " mtc0 $1, $2, 1 \n" | ||
82 | " andi \\result, \\result, 0x400 \n" | ||
83 | #elif defined(CONFIG_CPU_MIPSR2) | ||
84 | /* see irqflags.h for inline function */ | ||
85 | #else | ||
86 | " mfc0 \\result, $12 \n" | ||
87 | " ori $1, \\result, 0x1f \n" | ||
88 | " xori $1, 0x1f \n" | ||
89 | " .set noreorder \n" | ||
90 | " mtc0 $1, $12 \n" | ||
91 | #endif | ||
92 | " irq_disable_hazard \n" | ||
93 | " .set pop \n" | ||
94 | " .endm \n"); | ||
95 | |||
96 | notrace unsigned long arch_local_irq_save(void) | ||
97 | { | ||
98 | unsigned long flags; | ||
99 | preempt_disable(); | ||
100 | asm volatile("arch_local_irq_save\t%0" | ||
101 | : "=r" (flags) | ||
102 | : /* no inputs */ | ||
103 | : "memory"); | ||
104 | preempt_enable(); | ||
105 | return flags; | ||
106 | } | ||
107 | EXPORT_SYMBOL(arch_local_irq_save); | ||
108 | |||
109 | |||
110 | __asm__( | ||
111 | " .macro arch_local_irq_restore flags \n" | ||
112 | " .set push \n" | ||
113 | " .set noreorder \n" | ||
114 | " .set noat \n" | ||
115 | #ifdef CONFIG_MIPS_MT_SMTC | ||
116 | "mfc0 $1, $2, 1 \n" | ||
117 | "andi \\flags, 0x400 \n" | ||
118 | "ori $1, 0x400 \n" | ||
119 | "xori $1, 0x400 \n" | ||
120 | "or \\flags, $1 \n" | ||
121 | "mtc0 \\flags, $2, 1 \n" | ||
122 | #elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU) | ||
123 | /* see irqflags.h for inline function */ | ||
124 | #elif defined(CONFIG_CPU_MIPSR2) | ||
125 | /* see irqflags.h for inline function */ | ||
126 | #else | ||
127 | " mfc0 $1, $12 \n" | ||
128 | " andi \\flags, 1 \n" | ||
129 | " ori $1, 0x1f \n" | ||
130 | " xori $1, 0x1f \n" | ||
131 | " or \\flags, $1 \n" | ||
132 | " mtc0 \\flags, $12 \n" | ||
133 | #endif | ||
134 | " irq_disable_hazard \n" | ||
135 | " .set pop \n" | ||
136 | " .endm \n"); | ||
137 | |||
138 | notrace void arch_local_irq_restore(unsigned long flags) | ||
139 | { | ||
140 | unsigned long __tmp1; | ||
141 | |||
142 | #ifdef CONFIG_MIPS_MT_SMTC | ||
143 | /* | ||
144 | * SMTC kernel needs to do a software replay of queued | ||
145 | * IPIs, at the cost of branch and call overhead on each | ||
146 | * local_irq_restore() | ||
147 | */ | ||
148 | if (unlikely(!(flags & 0x0400))) | ||
149 | smtc_ipi_replay(); | ||
150 | #endif | ||
151 | preempt_disable(); | ||
152 | __asm__ __volatile__( | ||
153 | "arch_local_irq_restore\t%0" | ||
154 | : "=r" (__tmp1) | ||
155 | : "0" (flags) | ||
156 | : "memory"); | ||
157 | preempt_enable(); | ||
158 | } | ||
159 | EXPORT_SYMBOL(arch_local_irq_restore); | ||
160 | |||
161 | |||
162 | notrace void __arch_local_irq_restore(unsigned long flags) | ||
163 | { | ||
164 | unsigned long __tmp1; | ||
165 | |||
166 | preempt_disable(); | ||
167 | __asm__ __volatile__( | ||
168 | "arch_local_irq_restore\t%0" | ||
169 | : "=r" (__tmp1) | ||
170 | : "0" (flags) | ||
171 | : "memory"); | ||
172 | preempt_enable(); | ||
173 | } | ||
174 | EXPORT_SYMBOL(__arch_local_irq_restore); | ||
175 | |||
176 | #endif /* !defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT_SMTC) */ | ||