diff options
-rw-r--r-- | arch/blackfin/kernel/irqchip.c | 43 |
1 files changed, 25 insertions, 18 deletions
diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index 7378440792a4..4b5fd36187d9 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c | |||
@@ -104,6 +104,29 @@ static void check_stack_overflow(int irq) | |||
104 | static inline void check_stack_overflow(int irq) { } | 104 | static inline void check_stack_overflow(int irq) { } |
105 | #endif | 105 | #endif |
106 | 106 | ||
107 | #ifndef CONFIG_IPIPE | ||
108 | static void maybe_lower_to_irq14(void) | ||
109 | { | ||
110 | unsigned short pending, other_ints; | ||
111 | |||
112 | /* | ||
113 | * If we're the only interrupt running (ignoring IRQ15 which | ||
114 | * is for syscalls), lower our priority to IRQ14 so that | ||
115 | * softirqs run at that level. If there's another, | ||
116 | * lower-level interrupt, irq_exit will defer softirqs to | ||
117 | * that. If the interrupt pipeline is enabled, we are already | ||
118 | * running at IRQ14 priority, so we don't need this code. | ||
119 | */ | ||
120 | CSYNC(); | ||
121 | pending = bfin_read_IPEND() & ~0x8000; | ||
122 | other_ints = pending & (pending - 1); | ||
123 | if (other_ints == 0) | ||
124 | lower_to_irq14(); | ||
125 | } | ||
126 | #else | ||
127 | static inline void maybe_lower_to_irq14(void) { } | ||
128 | #endif | ||
129 | |||
107 | /* | 130 | /* |
108 | * do_IRQ handles all hardware IRQs. Decoded IRQs should not | 131 | * do_IRQ handles all hardware IRQs. Decoded IRQs should not |
109 | * come via this function. Instead, they should provide their | 132 | * come via this function. Instead, they should provide their |
@@ -114,9 +137,6 @@ __attribute__((l1_text)) | |||
114 | #endif | 137 | #endif |
115 | asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) | 138 | asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) |
116 | { | 139 | { |
117 | #ifndef CONFIG_IPIPE | ||
118 | unsigned short pending, other_ints; | ||
119 | #endif | ||
120 | struct pt_regs *old_regs = set_irq_regs(regs); | 140 | struct pt_regs *old_regs = set_irq_regs(regs); |
121 | 141 | ||
122 | irq_enter(); | 142 | irq_enter(); |
@@ -132,21 +152,8 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) | |||
132 | else | 152 | else |
133 | generic_handle_irq(irq); | 153 | generic_handle_irq(irq); |
134 | 154 | ||
135 | #ifndef CONFIG_IPIPE | 155 | maybe_lower_to_irq14(); |
136 | /* | 156 | |
137 | * If we're the only interrupt running (ignoring IRQ15 which | ||
138 | * is for syscalls), lower our priority to IRQ14 so that | ||
139 | * softirqs run at that level. If there's another, | ||
140 | * lower-level interrupt, irq_exit will defer softirqs to | ||
141 | * that. If the interrupt pipeline is enabled, we are already | ||
142 | * running at IRQ14 priority, so we don't need this code. | ||
143 | */ | ||
144 | CSYNC(); | ||
145 | pending = bfin_read_IPEND() & ~0x8000; | ||
146 | other_ints = pending & (pending - 1); | ||
147 | if (other_ints == 0) | ||
148 | lower_to_irq14(); | ||
149 | #endif /* !CONFIG_IPIPE */ | ||
150 | irq_exit(); | 157 | irq_exit(); |
151 | 158 | ||
152 | set_irq_regs(old_regs); | 159 | set_irq_regs(old_regs); |