diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-10-06 19:17:21 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-10-06 19:17:21 -0400 |
commit | 88b42a4883a7783972c8fc607e60bd3f027e24de (patch) | |
tree | 8c60a77610bfc7dc95aac4b0b56c7cf4d0185014 /kernel/irq/chip.c | |
parent | 1e765cd36bb8242a399f65501650bcfabc2229c9 (diff) | |
parent | 27f3d18630cd7fbb03b62bd78a74303cb8c88069 (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.c | 85 |
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 | ||
345 | static 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 { |