diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2012-05-13 20:19:22 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2012-05-13 20:19:22 -0400 |
commit | 8b6ee04067310a6397476f05f06e52dabd8b0bb6 (patch) | |
tree | 022a153b777a9e38f49d46e4fb8f1e6747d4a5f4 /arch/powerpc/kernel | |
parent | b48d441a8ab8a89bd32a3a981a05b8a26905dfc7 (diff) | |
parent | 7c0482e3d055e5de056d3c693b821e39205b99ae (diff) |
Merge branch 'merge' into next
We want the irq fixes from the "merge" branch.
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/entry_64.S | 44 | ||||
-rw-r--r-- | arch/powerpc/kernel/irq.c | 13 |
2 files changed, 44 insertions, 13 deletions
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 29f13570214d..ed1718feb9d9 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -584,23 +584,19 @@ _GLOBAL(ret_from_except_lite) | |||
584 | fast_exc_return_irq: | 584 | fast_exc_return_irq: |
585 | restore: | 585 | restore: |
586 | /* | 586 | /* |
587 | * This is the main kernel exit path, we first check if we | 587 | * This is the main kernel exit path. First we check if we |
588 | * have to change our interrupt state. | 588 | * are about to re-enable interrupts |
589 | */ | 589 | */ |
590 | ld r5,SOFTE(r1) | 590 | ld r5,SOFTE(r1) |
591 | lbz r6,PACASOFTIRQEN(r13) | 591 | lbz r6,PACASOFTIRQEN(r13) |
592 | cmpwi cr1,r5,0 | 592 | cmpwi cr0,r5,0 |
593 | cmpw cr0,r5,r6 | 593 | beq restore_irq_off |
594 | beq cr0,4f | ||
595 | 594 | ||
596 | /* We do, handle disable first, which is easy */ | 595 | /* We are enabling, were we already enabled ? Yes, just return */ |
597 | bne cr1,3f; | 596 | cmpwi cr0,r6,1 |
598 | li r0,0 | 597 | beq cr0,do_restore |
599 | stb r0,PACASOFTIRQEN(r13); | ||
600 | TRACE_DISABLE_INTS | ||
601 | b 4f | ||
602 | 598 | ||
603 | 3: /* | 599 | /* |
604 | * We are about to soft-enable interrupts (we are hard disabled | 600 | * We are about to soft-enable interrupts (we are hard disabled |
605 | * at this point). We check if there's anything that needs to | 601 | * at this point). We check if there's anything that needs to |
606 | * be replayed first. | 602 | * be replayed first. |
@@ -622,7 +618,7 @@ restore_no_replay: | |||
622 | /* | 618 | /* |
623 | * Final return path. BookE is handled in a different file | 619 | * Final return path. BookE is handled in a different file |
624 | */ | 620 | */ |
625 | 4: | 621 | do_restore: |
626 | #ifdef CONFIG_PPC_BOOK3E | 622 | #ifdef CONFIG_PPC_BOOK3E |
627 | b .exception_return_book3e | 623 | b .exception_return_book3e |
628 | #else | 624 | #else |
@@ -696,6 +692,25 @@ fast_exception_return: | |||
696 | #endif /* CONFIG_PPC_BOOK3E */ | 692 | #endif /* CONFIG_PPC_BOOK3E */ |
697 | 693 | ||
698 | /* | 694 | /* |
695 | * We are returning to a context with interrupts soft disabled. | ||
696 | * | ||
697 | * However, we may also about to hard enable, so we need to | ||
698 | * make sure that in this case, we also clear PACA_IRQ_HARD_DIS | ||
699 | * or that bit can get out of sync and bad things will happen | ||
700 | */ | ||
701 | restore_irq_off: | ||
702 | ld r3,_MSR(r1) | ||
703 | lbz r7,PACAIRQHAPPENED(r13) | ||
704 | andi. r0,r3,MSR_EE | ||
705 | beq 1f | ||
706 | rlwinm r7,r7,0,~PACA_IRQ_HARD_DIS | ||
707 | stb r7,PACAIRQHAPPENED(r13) | ||
708 | 1: li r0,0 | ||
709 | stb r0,PACASOFTIRQEN(r13); | ||
710 | TRACE_DISABLE_INTS | ||
711 | b do_restore | ||
712 | |||
713 | /* | ||
699 | * Something did happen, check if a re-emit is needed | 714 | * Something did happen, check if a re-emit is needed |
700 | * (this also clears paca->irq_happened) | 715 | * (this also clears paca->irq_happened) |
701 | */ | 716 | */ |
@@ -744,6 +759,9 @@ restore_check_irq_replay: | |||
744 | #endif /* CONFIG_PPC_BOOK3E */ | 759 | #endif /* CONFIG_PPC_BOOK3E */ |
745 | 1: b .ret_from_except /* What else to do here ? */ | 760 | 1: b .ret_from_except /* What else to do here ? */ |
746 | 761 | ||
762 | |||
763 | |||
764 | 3: | ||
747 | do_work: | 765 | do_work: |
748 | #ifdef CONFIG_PREEMPT | 766 | #ifdef CONFIG_PREEMPT |
749 | andi. r0,r3,MSR_PR /* Returning to user mode? */ | 767 | andi. r0,r3,MSR_PR /* Returning to user mode? */ |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index c6c6f3b7f8cd..641da9e868ce 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -229,6 +229,19 @@ notrace void arch_local_irq_restore(unsigned long en) | |||
229 | */ | 229 | */ |
230 | if (unlikely(irq_happened != PACA_IRQ_HARD_DIS)) | 230 | if (unlikely(irq_happened != PACA_IRQ_HARD_DIS)) |
231 | __hard_irq_disable(); | 231 | __hard_irq_disable(); |
232 | #ifdef CONFIG_TRACE_IRQFLAG | ||
233 | else { | ||
234 | /* | ||
235 | * We should already be hard disabled here. We had bugs | ||
236 | * where that wasn't the case so let's dbl check it and | ||
237 | * warn if we are wrong. Only do that when IRQ tracing | ||
238 | * is enabled as mfmsr() can be costly. | ||
239 | */ | ||
240 | if (WARN_ON(mfmsr() & MSR_EE)) | ||
241 | __hard_irq_disable(); | ||
242 | } | ||
243 | #endif /* CONFIG_TRACE_IRQFLAG */ | ||
244 | |||
232 | set_soft_enabled(0); | 245 | set_soft_enabled(0); |
233 | 246 | ||
234 | /* | 247 | /* |