aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/chip.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/irq/chip.c')
-rw-r--r--kernel/irq/chip.c92
1 files changed, 78 insertions, 14 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index c687ba4363f2..ba566c261adc 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -166,11 +166,11 @@ int set_irq_data(unsigned int irq, void *data)
166EXPORT_SYMBOL(set_irq_data); 166EXPORT_SYMBOL(set_irq_data);
167 167
168/** 168/**
169 * set_irq_data - set irq type data for an irq 169 * set_irq_msi - set MSI descriptor data for an irq
170 * @irq: Interrupt number 170 * @irq: Interrupt number
171 * @entry: Pointer to MSI descriptor data 171 * @entry: Pointer to MSI descriptor data
172 * 172 *
173 * Set the hardware irq controller data for an irq 173 * Set the MSI descriptor entry for an irq
174 */ 174 */
175int set_irq_msi(unsigned int irq, struct msi_desc *entry) 175int set_irq_msi(unsigned int irq, struct msi_desc *entry)
176{ 176{
@@ -222,6 +222,34 @@ int set_irq_chip_data(unsigned int irq, void *data)
222} 222}
223EXPORT_SYMBOL(set_irq_chip_data); 223EXPORT_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 */
236void 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}
251EXPORT_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 */
338void 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
364out_unlock:
365 spin_unlock_irq(&desc->lock);
366}
367EXPORT_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
@@ -359,7 +426,6 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
359 426
360 spin_lock(&desc->lock); 427 spin_lock(&desc->lock);
361 mask_ack_irq(desc, irq); 428 mask_ack_irq(desc, irq);
362 desc = irq_remap_to_desc(irq, desc);
363 429
364 if (unlikely(desc->status & IRQ_INPROGRESS)) 430 if (unlikely(desc->status & IRQ_INPROGRESS))
365 goto out_unlock; 431 goto out_unlock;
@@ -383,7 +449,10 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
383 449
384 spin_lock(&desc->lock); 450 spin_lock(&desc->lock);
385 desc->status &= ~IRQ_INPROGRESS; 451 desc->status &= ~IRQ_INPROGRESS;
386 if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) 452
453 if (unlikely(desc->status & IRQ_ONESHOT))
454 desc->status |= IRQ_MASKED;
455 else if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
387 desc->chip->unmask(irq); 456 desc->chip->unmask(irq);
388out_unlock: 457out_unlock:
389 spin_unlock(&desc->lock); 458 spin_unlock(&desc->lock);
@@ -438,7 +507,6 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
438 desc->status &= ~IRQ_INPROGRESS; 507 desc->status &= ~IRQ_INPROGRESS;
439out: 508out:
440 desc->chip->eoi(irq); 509 desc->chip->eoi(irq);
441 desc = irq_remap_to_desc(irq, desc);
442 510
443 spin_unlock(&desc->lock); 511 spin_unlock(&desc->lock);
444} 512}
@@ -475,7 +543,6 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
475 !desc->action)) { 543 !desc->action)) {
476 desc->status |= (IRQ_PENDING | IRQ_MASKED); 544 desc->status |= (IRQ_PENDING | IRQ_MASKED);
477 mask_ack_irq(desc, irq); 545 mask_ack_irq(desc, irq);
478 desc = irq_remap_to_desc(irq, desc);
479 goto out_unlock; 546 goto out_unlock;
480 } 547 }
481 kstat_incr_irqs_this_cpu(irq, desc); 548 kstat_incr_irqs_this_cpu(irq, desc);
@@ -483,7 +550,6 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
483 /* Start handling the irq */ 550 /* Start handling the irq */
484 if (desc->chip->ack) 551 if (desc->chip->ack)
485 desc->chip->ack(irq); 552 desc->chip->ack(irq);
486 desc = irq_remap_to_desc(irq, desc);
487 553
488 /* Mark the IRQ currently in progress.*/ 554 /* Mark the IRQ currently in progress.*/
489 desc->status |= IRQ_INPROGRESS; 555 desc->status |= IRQ_INPROGRESS;
@@ -524,7 +590,7 @@ out_unlock:
524} 590}
525 591
526/** 592/**
527 * handle_percpu_IRQ - Per CPU local irq handler 593 * handle_percpu_irq - Per CPU local irq handler
528 * @irq: the interrupt number 594 * @irq: the interrupt number
529 * @desc: the interrupt description structure for this irq 595 * @desc: the interrupt description structure for this irq
530 * 596 *
@@ -544,10 +610,8 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc)
544 if (!noirqdebug) 610 if (!noirqdebug)
545 note_interrupt(irq, desc, action_ret); 611 note_interrupt(irq, desc, action_ret);
546 612
547 if (desc->chip->eoi) { 613 if (desc->chip->eoi)
548 desc->chip->eoi(irq); 614 desc->chip->eoi(irq);
549 desc = irq_remap_to_desc(irq, desc);
550 }
551} 615}
552 616
553void 617void
@@ -578,14 +642,13 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
578 desc->chip = &dummy_irq_chip; 642 desc->chip = &dummy_irq_chip;
579 } 643 }
580 644
645 chip_bus_lock(irq, desc);
581 spin_lock_irqsave(&desc->lock, flags); 646 spin_lock_irqsave(&desc->lock, flags);
582 647
583 /* Uninstall? */ 648 /* Uninstall? */
584 if (handle == handle_bad_irq) { 649 if (handle == handle_bad_irq) {
585 if (desc->chip != &no_irq_chip) { 650 if (desc->chip != &no_irq_chip)
586 mask_ack_irq(desc, irq); 651 mask_ack_irq(desc, irq);
587 desc = irq_remap_to_desc(irq, desc);
588 }
589 desc->status |= IRQ_DISABLED; 652 desc->status |= IRQ_DISABLED;
590 desc->depth = 1; 653 desc->depth = 1;
591 } 654 }
@@ -599,6 +662,7 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
599 desc->chip->startup(irq); 662 desc->chip->startup(irq);
600 } 663 }
601 spin_unlock_irqrestore(&desc->lock, flags); 664 spin_unlock_irqrestore(&desc->lock, flags);
665 chip_bus_sync_unlock(irq, desc);
602} 666}
603EXPORT_SYMBOL_GPL(__set_irq_handler); 667EXPORT_SYMBOL_GPL(__set_irq_handler);
604 668