aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/irq.c')
-rw-r--r--arch/sparc64/kernel/irq.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index ba43d85e8dde..9b6689d9d570 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -682,10 +682,32 @@ void ack_bad_irq(unsigned int virt_irq)
682 ino, virt_irq); 682 ino, virt_irq);
683} 683}
684 684
685void *hardirq_stack[NR_CPUS];
686void *softirq_stack[NR_CPUS];
687
688static __attribute__((always_inline)) void *set_hardirq_stack(void)
689{
690 void *orig_sp, *sp = hardirq_stack[smp_processor_id()];
691
692 __asm__ __volatile__("mov %%sp, %0" : "=r" (orig_sp));
693 if (orig_sp < sp ||
694 orig_sp > (sp + THREAD_SIZE)) {
695 sp += THREAD_SIZE - 192 - STACK_BIAS;
696 __asm__ __volatile__("mov %0, %%sp" : : "r" (sp));
697 }
698
699 return orig_sp;
700}
701static __attribute__((always_inline)) void restore_hardirq_stack(void *orig_sp)
702{
703 __asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp));
704}
705
685void handler_irq(int irq, struct pt_regs *regs) 706void handler_irq(int irq, struct pt_regs *regs)
686{ 707{
687 unsigned long pstate, bucket_pa; 708 unsigned long pstate, bucket_pa;
688 struct pt_regs *old_regs; 709 struct pt_regs *old_regs;
710 void *orig_sp;
689 711
690 clear_softint(1 << irq); 712 clear_softint(1 << irq);
691 713
@@ -703,6 +725,8 @@ void handler_irq(int irq, struct pt_regs *regs)
703 "i" (PSTATE_IE) 725 "i" (PSTATE_IE)
704 : "memory"); 726 : "memory");
705 727
728 orig_sp = set_hardirq_stack();
729
706 while (bucket_pa) { 730 while (bucket_pa) {
707 struct irq_desc *desc; 731 struct irq_desc *desc;
708 unsigned long next_pa; 732 unsigned long next_pa;
@@ -719,10 +743,38 @@ void handler_irq(int irq, struct pt_regs *regs)
719 bucket_pa = next_pa; 743 bucket_pa = next_pa;
720 } 744 }
721 745
746 restore_hardirq_stack(orig_sp);
747
722 irq_exit(); 748 irq_exit();
723 set_irq_regs(old_regs); 749 set_irq_regs(old_regs);
724} 750}
725 751
752void do_softirq(void)
753{
754 unsigned long flags;
755
756 if (in_interrupt())
757 return;
758
759 local_irq_save(flags);
760
761 if (local_softirq_pending()) {
762 void *orig_sp, *sp = softirq_stack[smp_processor_id()];
763
764 sp += THREAD_SIZE - 192 - STACK_BIAS;
765
766 __asm__ __volatile__("mov %%sp, %0\n\t"
767 "mov %1, %%sp"
768 : "=&r" (orig_sp)
769 : "r" (sp));
770 __do_softirq();
771 __asm__ __volatile__("mov %0, %%sp"
772 : : "r" (orig_sp));
773 }
774
775 local_irq_restore(flags);
776}
777
726#ifdef CONFIG_HOTPLUG_CPU 778#ifdef CONFIG_HOTPLUG_CPU
727void fixup_irqs(void) 779void fixup_irqs(void)
728{ 780{