aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/chip.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-10-06 19:17:21 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-10-06 19:17:21 -0400
commit88b42a4883a7783972c8fc607e60bd3f027e24de (patch)
tree8c60a77610bfc7dc95aac4b0b56c7cf4d0185014 /kernel/irq/chip.c
parent1e765cd36bb8242a399f65501650bcfabc2229c9 (diff)
parent27f3d18630cd7fbb03b62bd78a74303cb8c88069 (diff)
Merge branch 'pm-genirq'
* pm-genirq: PM / genirq: Document rules related to system suspend and interrupts PCI / PM: Make PCIe PME interrupts wake up from suspend-to-idle x86 / PM: Set IRQCHIP_SKIP_SET_WAKE for IOAPIC IRQ chip objects genirq: Simplify wakeup mechanism genirq: Mark wakeup sources as armed on suspend genirq: Create helper for flow handler entry check genirq: Distangle edge handler entry genirq: Avoid double loop on suspend genirq: Move MASK_ON_SUSPEND handling into suspend_device_irqs() genirq: Make use of pm misfeature accounting genirq: Add sanity checks for PM options on shared interrupt lines genirq: Move suspend/resume logic into irq/pm code PM / sleep: Mechanism for aborting system suspends unconditionally
Diffstat (limited to 'kernel/irq/chip.c')
-rw-r--r--kernel/irq/chip.c85
1 files changed, 57 insertions, 28 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 6223fab9a9d2..8fb52e9bddc1 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -342,6 +342,31 @@ static bool irq_check_poll(struct irq_desc *desc)
342 return irq_wait_for_poll(desc); 342 return irq_wait_for_poll(desc);
343} 343}
344 344
345static bool irq_may_run(struct irq_desc *desc)
346{
347 unsigned int mask = IRQD_IRQ_INPROGRESS | IRQD_WAKEUP_ARMED;
348
349 /*
350 * If the interrupt is not in progress and is not an armed
351 * wakeup interrupt, proceed.
352 */
353 if (!irqd_has_set(&desc->irq_data, mask))
354 return true;
355
356 /*
357 * If the interrupt is an armed wakeup source, mark it pending
358 * and suspended, disable it and notify the pm core about the
359 * event.
360 */
361 if (irq_pm_check_wakeup(desc))
362 return false;
363
364 /*
365 * Handle a potential concurrent poll on a different core.
366 */
367 return irq_check_poll(desc);
368}
369
345/** 370/**
346 * handle_simple_irq - Simple and software-decoded IRQs. 371 * handle_simple_irq - Simple and software-decoded IRQs.
347 * @irq: the interrupt number 372 * @irq: the interrupt number
@@ -359,9 +384,8 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc)
359{ 384{
360 raw_spin_lock(&desc->lock); 385 raw_spin_lock(&desc->lock);
361 386
362 if (unlikely(irqd_irq_inprogress(&desc->irq_data))) 387 if (!irq_may_run(desc))
363 if (!irq_check_poll(desc)) 388 goto out_unlock;
364 goto out_unlock;
365 389
366 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); 390 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
367 kstat_incr_irqs_this_cpu(irq, desc); 391 kstat_incr_irqs_this_cpu(irq, desc);
@@ -412,9 +436,8 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
412 raw_spin_lock(&desc->lock); 436 raw_spin_lock(&desc->lock);
413 mask_ack_irq(desc); 437 mask_ack_irq(desc);
414 438
415 if (unlikely(irqd_irq_inprogress(&desc->irq_data))) 439 if (!irq_may_run(desc))
416 if (!irq_check_poll(desc)) 440 goto out_unlock;
417 goto out_unlock;
418 441
419 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); 442 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
420 kstat_incr_irqs_this_cpu(irq, desc); 443 kstat_incr_irqs_this_cpu(irq, desc);
@@ -485,9 +508,8 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
485 508
486 raw_spin_lock(&desc->lock); 509 raw_spin_lock(&desc->lock);
487 510
488 if (unlikely(irqd_irq_inprogress(&desc->irq_data))) 511 if (!irq_may_run(desc))
489 if (!irq_check_poll(desc)) 512 goto out;
490 goto out;
491 513
492 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); 514 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
493 kstat_incr_irqs_this_cpu(irq, desc); 515 kstat_incr_irqs_this_cpu(irq, desc);
@@ -541,19 +563,23 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
541 raw_spin_lock(&desc->lock); 563 raw_spin_lock(&desc->lock);
542 564
543 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); 565 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
566
567 if (!irq_may_run(desc)) {
568 desc->istate |= IRQS_PENDING;
569 mask_ack_irq(desc);
570 goto out_unlock;
571 }
572
544 /* 573 /*
545 * If we're currently running this IRQ, or its disabled, 574 * If its disabled or no action available then mask it and get
546 * we shouldn't process the IRQ. Mark it pending, handle 575 * out of here.
547 * the necessary masking and go out
548 */ 576 */
549 if (unlikely(irqd_irq_disabled(&desc->irq_data) || 577 if (irqd_irq_disabled(&desc->irq_data) || !desc->action) {
550 irqd_irq_inprogress(&desc->irq_data) || !desc->action)) { 578 desc->istate |= IRQS_PENDING;
551 if (!irq_check_poll(desc)) { 579 mask_ack_irq(desc);
552 desc->istate |= IRQS_PENDING; 580 goto out_unlock;
553 mask_ack_irq(desc);
554 goto out_unlock;
555 }
556 } 581 }
582
557 kstat_incr_irqs_this_cpu(irq, desc); 583 kstat_incr_irqs_this_cpu(irq, desc);
558 584
559 /* Start handling the irq */ 585 /* Start handling the irq */
@@ -602,18 +628,21 @@ void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc)
602 raw_spin_lock(&desc->lock); 628 raw_spin_lock(&desc->lock);
603 629
604 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); 630 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
631
632 if (!irq_may_run(desc)) {
633 desc->istate |= IRQS_PENDING;
634 goto out_eoi;
635 }
636
605 /* 637 /*
606 * If we're currently running this IRQ, or its disabled, 638 * If its disabled or no action available then mask it and get
607 * we shouldn't process the IRQ. Mark it pending, handle 639 * out of here.
608 * the necessary masking and go out
609 */ 640 */
610 if (unlikely(irqd_irq_disabled(&desc->irq_data) || 641 if (irqd_irq_disabled(&desc->irq_data) || !desc->action) {
611 irqd_irq_inprogress(&desc->irq_data) || !desc->action)) { 642 desc->istate |= IRQS_PENDING;
612 if (!irq_check_poll(desc)) { 643 goto out_eoi;
613 desc->istate |= IRQS_PENDING;
614 goto out_eoi;
615 }
616 } 644 }
645
617 kstat_incr_irqs_this_cpu(irq, desc); 646 kstat_incr_irqs_this_cpu(irq, desc);
618 647
619 do { 648 do {