diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-01-23 14:19:32 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-01-23 14:19:32 -0500 |
commit | d227e87e6c939c6071def92bc7691ad774c733ff (patch) | |
tree | 31fbc74974da765322b26de321e0b33f2f7e1478 | |
parent | f66d45e99eb7ca91822c3e3f6d7a98843c9626cb (diff) | |
parent | 364ca8a897eadb2f0e76b7f0ffe94168f6d83d66 (diff) |
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus:
[MIPS] Vr41xx: Fix after GENERIC_HARDIRQS_NO__DO_IRQ change
[MIPS] SMTC: Instant IPI replay.
-rw-r--r-- | arch/mips/Kconfig | 14 | ||||
-rw-r--r-- | arch/mips/kernel/smtc.c | 54 | ||||
-rw-r--r-- | arch/mips/vr41xx/common/irq.c | 12 | ||||
-rw-r--r-- | drivers/char/vr41xx_giu.c | 114 | ||||
-rw-r--r-- | include/asm-mips/irqflags.h | 22 |
5 files changed, 130 insertions, 86 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index fd2ff0698a85..bbd386f572d9 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -1568,6 +1568,20 @@ config MIPS_MT_FPAFF | |||
1568 | depends on MIPS_MT | 1568 | depends on MIPS_MT |
1569 | default y | 1569 | default y |
1570 | 1570 | ||
1571 | config MIPS_MT_SMTC_INSTANT_REPLAY | ||
1572 | bool "Low-latency Dispatch of Deferred SMTC IPIs" | ||
1573 | depends on MIPS_MT_SMTC | ||
1574 | default y | ||
1575 | help | ||
1576 | SMTC pseudo-interrupts between TCs are deferred and queued | ||
1577 | if the target TC is interrupt-inhibited (IXMT). In the first | ||
1578 | SMTC prototypes, these queued IPIs were serviced on return | ||
1579 | to user mode, or on entry into the kernel idle loop. The | ||
1580 | INSTANT_REPLAY option dispatches them as part of local_irq_restore() | ||
1581 | processing, which adds runtime overhead (hence the option to turn | ||
1582 | it off), but ensures that IPIs are handled promptly even under | ||
1583 | heavy I/O interrupt load. | ||
1584 | |||
1571 | config MIPS_VPE_LOADER_TOM | 1585 | config MIPS_VPE_LOADER_TOM |
1572 | bool "Load VPE program into memory hidden from linux" | 1586 | bool "Load VPE program into memory hidden from linux" |
1573 | depends on MIPS_VPE_LOADER | 1587 | depends on MIPS_VPE_LOADER |
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index a8b387197d5b..44238ab2fc99 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c | |||
@@ -1017,6 +1017,33 @@ void setup_cross_vpe_interrupts(void) | |||
1017 | * SMTC-specific hacks invoked from elsewhere in the kernel. | 1017 | * SMTC-specific hacks invoked from elsewhere in the kernel. |
1018 | */ | 1018 | */ |
1019 | 1019 | ||
1020 | void smtc_ipi_replay(void) | ||
1021 | { | ||
1022 | /* | ||
1023 | * To the extent that we've ever turned interrupts off, | ||
1024 | * we may have accumulated deferred IPIs. This is subtle. | ||
1025 | * If we use the smtc_ipi_qdepth() macro, we'll get an | ||
1026 | * exact number - but we'll also disable interrupts | ||
1027 | * and create a window of failure where a new IPI gets | ||
1028 | * queued after we test the depth but before we re-enable | ||
1029 | * interrupts. So long as IXMT never gets set, however, | ||
1030 | * we should be OK: If we pick up something and dispatch | ||
1031 | * it here, that's great. If we see nothing, but concurrent | ||
1032 | * with this operation, another TC sends us an IPI, IXMT | ||
1033 | * is clear, and we'll handle it as a real pseudo-interrupt | ||
1034 | * and not a pseudo-pseudo interrupt. | ||
1035 | */ | ||
1036 | if (IPIQ[smp_processor_id()].depth > 0) { | ||
1037 | struct smtc_ipi *pipi; | ||
1038 | extern void self_ipi(struct smtc_ipi *); | ||
1039 | |||
1040 | while ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()]))) { | ||
1041 | self_ipi(pipi); | ||
1042 | smtc_cpu_stats[smp_processor_id()].selfipis++; | ||
1043 | } | ||
1044 | } | ||
1045 | } | ||
1046 | |||
1020 | void smtc_idle_loop_hook(void) | 1047 | void smtc_idle_loop_hook(void) |
1021 | { | 1048 | { |
1022 | #ifdef SMTC_IDLE_HOOK_DEBUG | 1049 | #ifdef SMTC_IDLE_HOOK_DEBUG |
@@ -1113,29 +1140,14 @@ void smtc_idle_loop_hook(void) | |||
1113 | if (pdb_msg != &id_ho_db_msg[0]) | 1140 | if (pdb_msg != &id_ho_db_msg[0]) |
1114 | printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg); | 1141 | printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg); |
1115 | #endif /* SMTC_IDLE_HOOK_DEBUG */ | 1142 | #endif /* SMTC_IDLE_HOOK_DEBUG */ |
1143 | |||
1116 | /* | 1144 | /* |
1117 | * To the extent that we've ever turned interrupts off, | 1145 | * Replay any accumulated deferred IPIs. If "Instant Replay" |
1118 | * we may have accumulated deferred IPIs. This is subtle. | 1146 | * is in use, there should never be any. |
1119 | * If we use the smtc_ipi_qdepth() macro, we'll get an | ||
1120 | * exact number - but we'll also disable interrupts | ||
1121 | * and create a window of failure where a new IPI gets | ||
1122 | * queued after we test the depth but before we re-enable | ||
1123 | * interrupts. So long as IXMT never gets set, however, | ||
1124 | * we should be OK: If we pick up something and dispatch | ||
1125 | * it here, that's great. If we see nothing, but concurrent | ||
1126 | * with this operation, another TC sends us an IPI, IXMT | ||
1127 | * is clear, and we'll handle it as a real pseudo-interrupt | ||
1128 | * and not a pseudo-pseudo interrupt. | ||
1129 | */ | 1147 | */ |
1130 | if (IPIQ[smp_processor_id()].depth > 0) { | 1148 | #ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY |
1131 | struct smtc_ipi *pipi; | 1149 | smtc_ipi_replay(); |
1132 | extern void self_ipi(struct smtc_ipi *); | 1150 | #endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */ |
1133 | |||
1134 | if ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()])) != NULL) { | ||
1135 | self_ipi(pipi); | ||
1136 | smtc_cpu_stats[smp_processor_id()].selfipis++; | ||
1137 | } | ||
1138 | } | ||
1139 | } | 1151 | } |
1140 | 1152 | ||
1141 | void smtc_soft_dump(void) | 1153 | void smtc_soft_dump(void) |
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c index 397ba94cd7ec..16decf4ac2f4 100644 --- a/arch/mips/vr41xx/common/irq.c +++ b/arch/mips/vr41xx/common/irq.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Interrupt handing routines for NEC VR4100 series. | 2 | * Interrupt handing routines for NEC VR4100 series. |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2005-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -73,13 +73,19 @@ static void irq_dispatch(unsigned int irq) | |||
73 | if (cascade->get_irq != NULL) { | 73 | if (cascade->get_irq != NULL) { |
74 | unsigned int source_irq = irq; | 74 | unsigned int source_irq = irq; |
75 | desc = irq_desc + source_irq; | 75 | desc = irq_desc + source_irq; |
76 | desc->chip->ack(source_irq); | 76 | if (desc->chip->mask_ack) |
77 | desc->chip->mask_ack(source_irq); | ||
78 | else { | ||
79 | desc->chip->mask(source_irq); | ||
80 | desc->chip->ack(source_irq); | ||
81 | } | ||
77 | irq = cascade->get_irq(irq); | 82 | irq = cascade->get_irq(irq); |
78 | if (irq < 0) | 83 | if (irq < 0) |
79 | atomic_inc(&irq_err_count); | 84 | atomic_inc(&irq_err_count); |
80 | else | 85 | else |
81 | irq_dispatch(irq); | 86 | irq_dispatch(irq); |
82 | desc->chip->end(source_irq); | 87 | if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) |
88 | desc->chip->unmask(source_irq); | ||
83 | } else | 89 | } else |
84 | do_IRQ(irq); | 90 | do_IRQ(irq); |
85 | } | 91 | } |
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c index a744dad9cf45..0cea8d4907df 100644 --- a/drivers/char/vr41xx_giu.c +++ b/drivers/char/vr41xx_giu.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2002 MontaVista Software Inc. | 4 | * Copyright (C) 2002 MontaVista Software Inc. |
5 | * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> | 5 | * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> |
6 | * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 6 | * Copyright (C) 2003-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -125,30 +125,17 @@ static inline uint16_t giu_clear(uint16_t offset, uint16_t clear) | |||
125 | return data; | 125 | return data; |
126 | } | 126 | } |
127 | 127 | ||
128 | static unsigned int startup_giuint_low_irq(unsigned int irq) | 128 | static void ack_giuint_low(unsigned int irq) |
129 | { | 129 | { |
130 | unsigned int pin; | 130 | giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq)); |
131 | |||
132 | pin = GPIO_PIN_OF_IRQ(irq); | ||
133 | giu_write(GIUINTSTATL, 1 << pin); | ||
134 | giu_set(GIUINTENL, 1 << pin); | ||
135 | |||
136 | return 0; | ||
137 | } | 131 | } |
138 | 132 | ||
139 | static void shutdown_giuint_low_irq(unsigned int irq) | 133 | static void mask_giuint_low(unsigned int irq) |
140 | { | 134 | { |
141 | giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | 135 | giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); |
142 | } | 136 | } |
143 | 137 | ||
144 | static void enable_giuint_low_irq(unsigned int irq) | 138 | static void mask_ack_giuint_low(unsigned int irq) |
145 | { | ||
146 | giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
147 | } | ||
148 | |||
149 | #define disable_giuint_low_irq shutdown_giuint_low_irq | ||
150 | |||
151 | static void ack_giuint_low_irq(unsigned int irq) | ||
152 | { | 139 | { |
153 | unsigned int pin; | 140 | unsigned int pin; |
154 | 141 | ||
@@ -157,46 +144,30 @@ static void ack_giuint_low_irq(unsigned int irq) | |||
157 | giu_write(GIUINTSTATL, 1 << pin); | 144 | giu_write(GIUINTSTATL, 1 << pin); |
158 | } | 145 | } |
159 | 146 | ||
160 | static void end_giuint_low_irq(unsigned int irq) | 147 | static void unmask_giuint_low(unsigned int irq) |
161 | { | 148 | { |
162 | if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) | 149 | giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); |
163 | giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
164 | } | 150 | } |
165 | 151 | ||
166 | static struct hw_interrupt_type giuint_low_irq_type = { | 152 | static struct irq_chip giuint_low_irq_chip = { |
167 | .typename = "GIUINTL", | 153 | .name = "GIUINTL", |
168 | .startup = startup_giuint_low_irq, | 154 | .ack = ack_giuint_low, |
169 | .shutdown = shutdown_giuint_low_irq, | 155 | .mask = mask_giuint_low, |
170 | .enable = enable_giuint_low_irq, | 156 | .mask_ack = mask_ack_giuint_low, |
171 | .disable = disable_giuint_low_irq, | 157 | .unmask = unmask_giuint_low, |
172 | .ack = ack_giuint_low_irq, | ||
173 | .end = end_giuint_low_irq, | ||
174 | }; | 158 | }; |
175 | 159 | ||
176 | static unsigned int startup_giuint_high_irq(unsigned int irq) | 160 | static void ack_giuint_high(unsigned int irq) |
177 | { | 161 | { |
178 | unsigned int pin; | 162 | giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); |
179 | |||
180 | pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET; | ||
181 | giu_write(GIUINTSTATH, 1 << pin); | ||
182 | giu_set(GIUINTENH, 1 << pin); | ||
183 | |||
184 | return 0; | ||
185 | } | 163 | } |
186 | 164 | ||
187 | static void shutdown_giuint_high_irq(unsigned int irq) | 165 | static void mask_giuint_high(unsigned int irq) |
188 | { | 166 | { |
189 | giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | 167 | giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); |
190 | } | 168 | } |
191 | 169 | ||
192 | static void enable_giuint_high_irq(unsigned int irq) | 170 | static void mask_ack_giuint_high(unsigned int irq) |
193 | { | ||
194 | giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
195 | } | ||
196 | |||
197 | #define disable_giuint_high_irq shutdown_giuint_high_irq | ||
198 | |||
199 | static void ack_giuint_high_irq(unsigned int irq) | ||
200 | { | 171 | { |
201 | unsigned int pin; | 172 | unsigned int pin; |
202 | 173 | ||
@@ -205,20 +176,17 @@ static void ack_giuint_high_irq(unsigned int irq) | |||
205 | giu_write(GIUINTSTATH, 1 << pin); | 176 | giu_write(GIUINTSTATH, 1 << pin); |
206 | } | 177 | } |
207 | 178 | ||
208 | static void end_giuint_high_irq(unsigned int irq) | 179 | static void unmask_giuint_high(unsigned int irq) |
209 | { | 180 | { |
210 | if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) | 181 | giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); |
211 | giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
212 | } | 182 | } |
213 | 183 | ||
214 | static struct hw_interrupt_type giuint_high_irq_type = { | 184 | static struct irq_chip giuint_high_irq_chip = { |
215 | .typename = "GIUINTH", | 185 | .name = "GIUINTH", |
216 | .startup = startup_giuint_high_irq, | 186 | .ack = ack_giuint_high, |
217 | .shutdown = shutdown_giuint_high_irq, | 187 | .mask = mask_giuint_high, |
218 | .enable = enable_giuint_high_irq, | 188 | .mask_ack = mask_ack_giuint_high, |
219 | .disable = disable_giuint_high_irq, | 189 | .unmask = unmask_giuint_high, |
220 | .ack = ack_giuint_high_irq, | ||
221 | .end = end_giuint_high_irq, | ||
222 | }; | 190 | }; |
223 | 191 | ||
224 | static int giu_get_irq(unsigned int irq) | 192 | static int giu_get_irq(unsigned int irq) |
@@ -282,9 +250,15 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_ | |||
282 | break; | 250 | break; |
283 | } | 251 | } |
284 | } | 252 | } |
253 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
254 | &giuint_low_irq_chip, | ||
255 | handle_edge_irq); | ||
285 | } else { | 256 | } else { |
286 | giu_clear(GIUINTTYPL, mask); | 257 | giu_clear(GIUINTTYPL, mask); |
287 | giu_clear(GIUINTHTSELL, mask); | 258 | giu_clear(GIUINTHTSELL, mask); |
259 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
260 | &giuint_low_irq_chip, | ||
261 | handle_level_irq); | ||
288 | } | 262 | } |
289 | giu_write(GIUINTSTATL, mask); | 263 | giu_write(GIUINTSTATL, mask); |
290 | } else if (pin < GIUINT_HIGH_MAX) { | 264 | } else if (pin < GIUINT_HIGH_MAX) { |
@@ -311,9 +285,15 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_ | |||
311 | break; | 285 | break; |
312 | } | 286 | } |
313 | } | 287 | } |
288 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
289 | &giuint_high_irq_chip, | ||
290 | handle_edge_irq); | ||
314 | } else { | 291 | } else { |
315 | giu_clear(GIUINTTYPH, mask); | 292 | giu_clear(GIUINTTYPH, mask); |
316 | giu_clear(GIUINTHTSELH, mask); | 293 | giu_clear(GIUINTHTSELH, mask); |
294 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
295 | &giuint_high_irq_chip, | ||
296 | handle_level_irq); | ||
317 | } | 297 | } |
318 | giu_write(GIUINTSTATH, mask); | 298 | giu_write(GIUINTSTATH, mask); |
319 | } | 299 | } |
@@ -617,10 +597,11 @@ static const struct file_operations gpio_fops = { | |||
617 | static int __devinit giu_probe(struct platform_device *dev) | 597 | static int __devinit giu_probe(struct platform_device *dev) |
618 | { | 598 | { |
619 | unsigned long start, size, flags = 0; | 599 | unsigned long start, size, flags = 0; |
620 | unsigned int nr_pins = 0; | 600 | unsigned int nr_pins = 0, trigger, i, pin; |
621 | struct resource *res1, *res2 = NULL; | 601 | struct resource *res1, *res2 = NULL; |
622 | void *base; | 602 | void *base; |
623 | int retval, i; | 603 | struct irq_chip *chip; |
604 | int retval; | ||
624 | 605 | ||
625 | switch (current_cpu_data.cputype) { | 606 | switch (current_cpu_data.cputype) { |
626 | case CPU_VR4111: | 607 | case CPU_VR4111: |
@@ -688,11 +669,20 @@ static int __devinit giu_probe(struct platform_device *dev) | |||
688 | giu_write(GIUINTENL, 0); | 669 | giu_write(GIUINTENL, 0); |
689 | giu_write(GIUINTENH, 0); | 670 | giu_write(GIUINTENH, 0); |
690 | 671 | ||
672 | trigger = giu_read(GIUINTTYPH) << 16; | ||
673 | trigger |= giu_read(GIUINTTYPL); | ||
691 | for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { | 674 | for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { |
692 | if (i < GIU_IRQ(GIUINT_HIGH_OFFSET)) | 675 | pin = GPIO_PIN_OF_IRQ(i); |
693 | irq_desc[i].chip = &giuint_low_irq_type; | 676 | if (pin < GIUINT_HIGH_OFFSET) |
677 | chip = &giuint_low_irq_chip; | ||
694 | else | 678 | else |
695 | irq_desc[i].chip = &giuint_high_irq_type; | 679 | chip = &giuint_high_irq_chip; |
680 | |||
681 | if (trigger & (1 << pin)) | ||
682 | set_irq_chip_and_handler(i, chip, handle_edge_irq); | ||
683 | else | ||
684 | set_irq_chip_and_handler(i, chip, handle_level_irq); | ||
685 | |||
696 | } | 686 | } |
697 | 687 | ||
698 | return cascade_irq(GIUINT_IRQ, giu_get_irq); | 688 | return cascade_irq(GIUINT_IRQ, giu_get_irq); |
diff --git a/include/asm-mips/irqflags.h b/include/asm-mips/irqflags.h index 46bf5de5ac72..af3b07dfad4b 100644 --- a/include/asm-mips/irqflags.h +++ b/include/asm-mips/irqflags.h | |||
@@ -15,6 +15,27 @@ | |||
15 | 15 | ||
16 | #include <asm/hazards.h> | 16 | #include <asm/hazards.h> |
17 | 17 | ||
18 | /* | ||
19 | * CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY does prompt replay of deferred IPIs, | ||
20 | * at the cost of branch and call overhead on each local_irq_restore() | ||
21 | */ | ||
22 | |||
23 | #ifdef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY | ||
24 | |||
25 | extern void smtc_ipi_replay(void); | ||
26 | |||
27 | #define irq_restore_epilog(flags) \ | ||
28 | do { \ | ||
29 | if (!(flags & 0x0400)) \ | ||
30 | smtc_ipi_replay(); \ | ||
31 | } while (0) | ||
32 | |||
33 | #else | ||
34 | |||
35 | #define irq_restore_epilog(ignore) do { } while (0) | ||
36 | |||
37 | #endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */ | ||
38 | |||
18 | __asm__ ( | 39 | __asm__ ( |
19 | " .macro raw_local_irq_enable \n" | 40 | " .macro raw_local_irq_enable \n" |
20 | " .set push \n" | 41 | " .set push \n" |
@@ -193,6 +214,7 @@ do { \ | |||
193 | : "=r" (__tmp1) \ | 214 | : "=r" (__tmp1) \ |
194 | : "0" (flags) \ | 215 | : "0" (flags) \ |
195 | : "memory"); \ | 216 | : "memory"); \ |
217 | irq_restore_epilog(flags); \ | ||
196 | } while(0) | 218 | } while(0) |
197 | 219 | ||
198 | static inline int raw_irqs_disabled_flags(unsigned long flags) | 220 | static inline int raw_irqs_disabled_flags(unsigned long flags) |