aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-05-13 20:19:22 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-05-13 20:19:22 -0400
commit8b6ee04067310a6397476f05f06e52dabd8b0bb6 (patch)
tree022a153b777a9e38f49d46e4fb8f1e6747d4a5f4 /arch/powerpc/kernel
parentb48d441a8ab8a89bd32a3a981a05b8a26905dfc7 (diff)
parent7c0482e3d055e5de056d3c693b821e39205b99ae (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.S44
-rw-r--r--arch/powerpc/kernel/irq.c13
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)
584fast_exc_return_irq: 584fast_exc_return_irq:
585restore: 585restore:
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
6033: /* 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 */
6254: 621do_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 */
701restore_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)
7081: 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 */
7451: b .ret_from_except /* What else to do here ? */ 7601: b .ret_from_except /* What else to do here ? */
746 761
762
763
7643:
747do_work: 765do_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 /*