diff options
Diffstat (limited to 'kernel/irq/chip.c')
-rw-r--r-- | kernel/irq/chip.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index f856330e684a..5765aad94998 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -222,6 +222,34 @@ int set_irq_chip_data(unsigned int irq, void *data) | |||
222 | } | 222 | } |
223 | EXPORT_SYMBOL(set_irq_chip_data); | 223 | EXPORT_SYMBOL(set_irq_chip_data); |
224 | 224 | ||
225 | /** | ||
226 | * set_irq_nested_thread - Set/Reset the IRQ_NESTED_THREAD flag of an irq | ||
227 | * | ||
228 | * @irq: Interrupt number | ||
229 | * @nest: 0 to clear / 1 to set the IRQ_NESTED_THREAD flag | ||
230 | * | ||
231 | * The IRQ_NESTED_THREAD flag indicates that on | ||
232 | * request_threaded_irq() no separate interrupt thread should be | ||
233 | * created for the irq as the handler are called nested in the | ||
234 | * context of a demultiplexing interrupt handler thread. | ||
235 | */ | ||
236 | void set_irq_nested_thread(unsigned int irq, int nest) | ||
237 | { | ||
238 | struct irq_desc *desc = irq_to_desc(irq); | ||
239 | unsigned long flags; | ||
240 | |||
241 | if (!desc) | ||
242 | return; | ||
243 | |||
244 | spin_lock_irqsave(&desc->lock, flags); | ||
245 | if (nest) | ||
246 | desc->status |= IRQ_NESTED_THREAD; | ||
247 | else | ||
248 | desc->status &= ~IRQ_NESTED_THREAD; | ||
249 | spin_unlock_irqrestore(&desc->lock, flags); | ||
250 | } | ||
251 | EXPORT_SYMBOL_GPL(set_irq_nested_thread); | ||
252 | |||
225 | /* | 253 | /* |
226 | * default enable function | 254 | * default enable function |
227 | */ | 255 | */ |
@@ -299,6 +327,45 @@ static inline void mask_ack_irq(struct irq_desc *desc, int irq) | |||
299 | } | 327 | } |
300 | } | 328 | } |
301 | 329 | ||
330 | /* | ||
331 | * handle_nested_irq - Handle a nested irq from a irq thread | ||
332 | * @irq: the interrupt number | ||
333 | * | ||
334 | * Handle interrupts which are nested into a threaded interrupt | ||
335 | * handler. The handler function is called inside the calling | ||
336 | * threads context. | ||
337 | */ | ||
338 | void handle_nested_irq(unsigned int irq) | ||
339 | { | ||
340 | struct irq_desc *desc = irq_to_desc(irq); | ||
341 | struct irqaction *action; | ||
342 | irqreturn_t action_ret; | ||
343 | |||
344 | might_sleep(); | ||
345 | |||
346 | spin_lock_irq(&desc->lock); | ||
347 | |||
348 | kstat_incr_irqs_this_cpu(irq, desc); | ||
349 | |||
350 | action = desc->action; | ||
351 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) | ||
352 | goto out_unlock; | ||
353 | |||
354 | desc->status |= IRQ_INPROGRESS; | ||
355 | spin_unlock_irq(&desc->lock); | ||
356 | |||
357 | action_ret = action->thread_fn(action->irq, action->dev_id); | ||
358 | if (!noirqdebug) | ||
359 | note_interrupt(irq, desc, action_ret); | ||
360 | |||
361 | spin_lock_irq(&desc->lock); | ||
362 | desc->status &= ~IRQ_INPROGRESS; | ||
363 | |||
364 | out_unlock: | ||
365 | spin_unlock_irq(&desc->lock); | ||
366 | } | ||
367 | EXPORT_SYMBOL_GPL(handle_nested_irq); | ||
368 | |||
302 | /** | 369 | /** |
303 | * handle_simple_irq - Simple and software-decoded IRQs. | 370 | * handle_simple_irq - Simple and software-decoded IRQs. |
304 | * @irq: the interrupt number | 371 | * @irq: the interrupt number |