diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-09 14:07:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-09 14:07:29 -0400 |
commit | 6a5beacca8681fb6602649dd8cf5ba50a90befb3 (patch) | |
tree | 2c440c3d4d9ed62f06a5eceda0a2b20f2d773307 | |
parent | 1eef1600af5f7404505f217513946e04c6b95718 (diff) | |
parent | a3512b2dd57cb653bb33645ca9c934436e547e3c (diff) |
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc fixes from Benjamin Herrenschmidt:
"Here are a couple of last minute fixes for 3.4 for regressions
introduced by my rewrite of the lazy irq masking code."
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc:
powerpc/irq: Make alignment & program interrupt behave the same
powerpc/irq: Fix bug with new lazy IRQ handling code
-rw-r--r-- | arch/powerpc/include/asm/exception-64s.h | 7 | ||||
-rw-r--r-- | arch/powerpc/kernel/entry_64.S | 18 | ||||
-rw-r--r-- | arch/powerpc/kernel/exceptions-64s.S | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/irq.c | 8 | ||||
-rw-r--r-- | arch/powerpc/kernel/traps.c | 10 |
5 files changed, 16 insertions, 29 deletions
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index 548da3aa0a30..d58fc4e4149c 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h | |||
@@ -288,13 +288,6 @@ label##_hv: \ | |||
288 | /* Exception addition: Hard disable interrupts */ | 288 | /* Exception addition: Hard disable interrupts */ |
289 | #define DISABLE_INTS SOFT_DISABLE_INTS(r10,r11) | 289 | #define DISABLE_INTS SOFT_DISABLE_INTS(r10,r11) |
290 | 290 | ||
291 | /* Exception addition: Keep interrupt state */ | ||
292 | #define ENABLE_INTS \ | ||
293 | ld r11,PACAKMSR(r13); \ | ||
294 | ld r12,_MSR(r1); \ | ||
295 | rlwimi r11,r12,0,MSR_EE; \ | ||
296 | mtmsrd r11,1 | ||
297 | |||
298 | #define ADD_NVGPRS \ | 291 | #define ADD_NVGPRS \ |
299 | bl .save_nvgprs | 292 | bl .save_nvgprs |
300 | 293 | ||
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index f8a7a1a1a9f4..fc6015027a86 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -767,16 +767,6 @@ do_work: | |||
767 | SOFT_DISABLE_INTS(r3,r4) | 767 | SOFT_DISABLE_INTS(r3,r4) |
768 | 1: bl .preempt_schedule_irq | 768 | 1: bl .preempt_schedule_irq |
769 | 769 | ||
770 | /* Hard-disable interrupts again (and update PACA) */ | ||
771 | #ifdef CONFIG_PPC_BOOK3E | ||
772 | wrteei 0 | ||
773 | #else | ||
774 | ld r10,PACAKMSR(r13) /* Get kernel MSR without EE */ | ||
775 | mtmsrd r10,1 | ||
776 | #endif /* CONFIG_PPC_BOOK3E */ | ||
777 | li r0,PACA_IRQ_HARD_DIS | ||
778 | stb r0,PACAIRQHAPPENED(r13) | ||
779 | |||
780 | /* Re-test flags and eventually loop */ | 770 | /* Re-test flags and eventually loop */ |
781 | clrrdi r9,r1,THREAD_SHIFT | 771 | clrrdi r9,r1,THREAD_SHIFT |
782 | ld r4,TI_FLAGS(r9) | 772 | ld r4,TI_FLAGS(r9) |
@@ -787,14 +777,6 @@ do_work: | |||
787 | user_work: | 777 | user_work: |
788 | #endif /* CONFIG_PREEMPT */ | 778 | #endif /* CONFIG_PREEMPT */ |
789 | 779 | ||
790 | /* Enable interrupts */ | ||
791 | #ifdef CONFIG_PPC_BOOK3E | ||
792 | wrteei 1 | ||
793 | #else | ||
794 | ori r10,r10,MSR_EE | ||
795 | mtmsrd r10,1 | ||
796 | #endif /* CONFIG_PPC_BOOK3E */ | ||
797 | |||
798 | andi. r0,r4,_TIF_NEED_RESCHED | 780 | andi. r0,r4,_TIF_NEED_RESCHED |
799 | beq 1f | 781 | beq 1f |
800 | bl .restore_interrupts | 782 | bl .restore_interrupts |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index cb705fdbb458..8f880bc77c56 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -768,8 +768,8 @@ alignment_common: | |||
768 | std r3,_DAR(r1) | 768 | std r3,_DAR(r1) |
769 | std r4,_DSISR(r1) | 769 | std r4,_DSISR(r1) |
770 | bl .save_nvgprs | 770 | bl .save_nvgprs |
771 | DISABLE_INTS | ||
771 | addi r3,r1,STACK_FRAME_OVERHEAD | 772 | addi r3,r1,STACK_FRAME_OVERHEAD |
772 | ENABLE_INTS | ||
773 | bl .alignment_exception | 773 | bl .alignment_exception |
774 | b .ret_from_except | 774 | b .ret_from_except |
775 | 775 | ||
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 43eb74fcedde..c6c6f3b7f8cd 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -260,11 +260,17 @@ EXPORT_SYMBOL(arch_local_irq_restore); | |||
260 | * if they are currently disabled. This is typically called before | 260 | * if they are currently disabled. This is typically called before |
261 | * schedule() or do_signal() when returning to userspace. We do it | 261 | * schedule() or do_signal() when returning to userspace. We do it |
262 | * in C to avoid the burden of dealing with lockdep etc... | 262 | * in C to avoid the burden of dealing with lockdep etc... |
263 | * | ||
264 | * NOTE: This is called with interrupts hard disabled but not marked | ||
265 | * as such in paca->irq_happened, so we need to resync this. | ||
263 | */ | 266 | */ |
264 | void restore_interrupts(void) | 267 | void restore_interrupts(void) |
265 | { | 268 | { |
266 | if (irqs_disabled()) | 269 | if (irqs_disabled()) { |
270 | local_paca->irq_happened |= PACA_IRQ_HARD_DIS; | ||
267 | local_irq_enable(); | 271 | local_irq_enable(); |
272 | } else | ||
273 | __hard_irq_enable(); | ||
268 | } | 274 | } |
269 | 275 | ||
270 | #endif /* CONFIG_PPC64 */ | 276 | #endif /* CONFIG_PPC64 */ |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 6aa0c663e247..158972341a2d 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -248,7 +248,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) | |||
248 | addr, regs->nip, regs->link, code); | 248 | addr, regs->nip, regs->link, code); |
249 | } | 249 | } |
250 | 250 | ||
251 | if (!arch_irq_disabled_regs(regs)) | 251 | if (arch_irqs_disabled() && !arch_irq_disabled_regs(regs)) |
252 | local_irq_enable(); | 252 | local_irq_enable(); |
253 | 253 | ||
254 | memset(&info, 0, sizeof(info)); | 254 | memset(&info, 0, sizeof(info)); |
@@ -1019,7 +1019,9 @@ void __kprobes program_check_exception(struct pt_regs *regs) | |||
1019 | return; | 1019 | return; |
1020 | } | 1020 | } |
1021 | 1021 | ||
1022 | local_irq_enable(); | 1022 | /* We restore the interrupt state now */ |
1023 | if (!arch_irq_disabled_regs(regs)) | ||
1024 | local_irq_enable(); | ||
1023 | 1025 | ||
1024 | #ifdef CONFIG_MATH_EMULATION | 1026 | #ifdef CONFIG_MATH_EMULATION |
1025 | /* (reason & REASON_ILLEGAL) would be the obvious thing here, | 1027 | /* (reason & REASON_ILLEGAL) would be the obvious thing here, |
@@ -1069,6 +1071,10 @@ void alignment_exception(struct pt_regs *regs) | |||
1069 | { | 1071 | { |
1070 | int sig, code, fixed = 0; | 1072 | int sig, code, fixed = 0; |
1071 | 1073 | ||
1074 | /* We restore the interrupt state now */ | ||
1075 | if (!arch_irq_disabled_regs(regs)) | ||
1076 | local_irq_enable(); | ||
1077 | |||
1072 | /* we don't implement logging of alignment exceptions */ | 1078 | /* we don't implement logging of alignment exceptions */ |
1073 | if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS)) | 1079 | if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS)) |
1074 | fixed = fix_alignment(regs); | 1080 | fixed = fix_alignment(regs); |