diff options
Diffstat (limited to 'arch/sparc64/kernel/irq.c')
-rw-r--r-- | arch/sparc64/kernel/irq.c | 83 |
1 files changed, 53 insertions, 30 deletions
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 3edc18e1b818..a36f8dd0c021 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c | |||
@@ -171,8 +171,6 @@ skip: | |||
171 | return 0; | 171 | return 0; |
172 | } | 172 | } |
173 | 173 | ||
174 | extern unsigned long real_hard_smp_processor_id(void); | ||
175 | |||
176 | static unsigned int sun4u_compute_tid(unsigned long imap, unsigned long cpuid) | 174 | static unsigned int sun4u_compute_tid(unsigned long imap, unsigned long cpuid) |
177 | { | 175 | { |
178 | unsigned int tid; | 176 | unsigned int tid; |
@@ -694,9 +692,20 @@ void init_irqwork_curcpu(void) | |||
694 | trap_block[cpu].irq_worklist = 0; | 692 | trap_block[cpu].irq_worklist = 0; |
695 | } | 693 | } |
696 | 694 | ||
697 | static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type) | 695 | /* Please be very careful with register_one_mondo() and |
696 | * sun4v_register_mondo_queues(). | ||
697 | * | ||
698 | * On SMP this gets invoked from the CPU trampoline before | ||
699 | * the cpu has fully taken over the trap table from OBP, | ||
700 | * and it's kernel stack + %g6 thread register state is | ||
701 | * not fully cooked yet. | ||
702 | * | ||
703 | * Therefore you cannot make any OBP calls, not even prom_printf, | ||
704 | * from these two routines. | ||
705 | */ | ||
706 | static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type, unsigned long qmask) | ||
698 | { | 707 | { |
699 | unsigned long num_entries = 128; | 708 | unsigned long num_entries = (qmask + 1) / 64; |
700 | unsigned long status; | 709 | unsigned long status; |
701 | 710 | ||
702 | status = sun4v_cpu_qconf(type, paddr, num_entries); | 711 | status = sun4v_cpu_qconf(type, paddr, num_entries); |
@@ -711,44 +720,58 @@ static void __cpuinit sun4v_register_mondo_queues(int this_cpu) | |||
711 | { | 720 | { |
712 | struct trap_per_cpu *tb = &trap_block[this_cpu]; | 721 | struct trap_per_cpu *tb = &trap_block[this_cpu]; |
713 | 722 | ||
714 | register_one_mondo(tb->cpu_mondo_pa, HV_CPU_QUEUE_CPU_MONDO); | 723 | register_one_mondo(tb->cpu_mondo_pa, HV_CPU_QUEUE_CPU_MONDO, |
715 | register_one_mondo(tb->dev_mondo_pa, HV_CPU_QUEUE_DEVICE_MONDO); | 724 | tb->cpu_mondo_qmask); |
716 | register_one_mondo(tb->resum_mondo_pa, HV_CPU_QUEUE_RES_ERROR); | 725 | register_one_mondo(tb->dev_mondo_pa, HV_CPU_QUEUE_DEVICE_MONDO, |
717 | register_one_mondo(tb->nonresum_mondo_pa, HV_CPU_QUEUE_NONRES_ERROR); | 726 | tb->dev_mondo_qmask); |
727 | register_one_mondo(tb->resum_mondo_pa, HV_CPU_QUEUE_RES_ERROR, | ||
728 | tb->resum_qmask); | ||
729 | register_one_mondo(tb->nonresum_mondo_pa, HV_CPU_QUEUE_NONRES_ERROR, | ||
730 | tb->nonresum_qmask); | ||
718 | } | 731 | } |
719 | 732 | ||
720 | static void __cpuinit alloc_one_mondo(unsigned long *pa_ptr, int use_bootmem) | 733 | static void __cpuinit alloc_one_mondo(unsigned long *pa_ptr, unsigned long qmask, int use_bootmem) |
721 | { | 734 | { |
722 | void *page; | 735 | unsigned long size = PAGE_ALIGN(qmask + 1); |
736 | unsigned long order = get_order(size); | ||
737 | void *p = NULL; | ||
723 | 738 | ||
724 | if (use_bootmem) | 739 | if (use_bootmem) { |
725 | page = alloc_bootmem_low_pages(PAGE_SIZE); | 740 | p = __alloc_bootmem_low(size, size, 0); |
726 | else | 741 | } else { |
727 | page = (void *) get_zeroed_page(GFP_ATOMIC); | 742 | struct page *page = alloc_pages(GFP_ATOMIC | __GFP_ZERO, order); |
743 | if (page) | ||
744 | p = page_address(page); | ||
745 | } | ||
728 | 746 | ||
729 | if (!page) { | 747 | if (!p) { |
730 | prom_printf("SUN4V: Error, cannot allocate mondo queue.\n"); | 748 | prom_printf("SUN4V: Error, cannot allocate mondo queue.\n"); |
731 | prom_halt(); | 749 | prom_halt(); |
732 | } | 750 | } |
733 | 751 | ||
734 | *pa_ptr = __pa(page); | 752 | *pa_ptr = __pa(p); |
735 | } | 753 | } |
736 | 754 | ||
737 | static void __cpuinit alloc_one_kbuf(unsigned long *pa_ptr, int use_bootmem) | 755 | static void __cpuinit alloc_one_kbuf(unsigned long *pa_ptr, unsigned long qmask, int use_bootmem) |
738 | { | 756 | { |
739 | void *page; | 757 | unsigned long size = PAGE_ALIGN(qmask + 1); |
758 | unsigned long order = get_order(size); | ||
759 | void *p = NULL; | ||
740 | 760 | ||
741 | if (use_bootmem) | 761 | if (use_bootmem) { |
742 | page = alloc_bootmem_low_pages(PAGE_SIZE); | 762 | p = __alloc_bootmem_low(size, size, 0); |
743 | else | 763 | } else { |
744 | page = (void *) get_zeroed_page(GFP_ATOMIC); | 764 | struct page *page = alloc_pages(GFP_ATOMIC | __GFP_ZERO, order); |
765 | if (page) | ||
766 | p = page_address(page); | ||
767 | } | ||
745 | 768 | ||
746 | if (!page) { | 769 | if (!p) { |
747 | prom_printf("SUN4V: Error, cannot allocate kbuf page.\n"); | 770 | prom_printf("SUN4V: Error, cannot allocate kbuf page.\n"); |
748 | prom_halt(); | 771 | prom_halt(); |
749 | } | 772 | } |
750 | 773 | ||
751 | *pa_ptr = __pa(page); | 774 | *pa_ptr = __pa(p); |
752 | } | 775 | } |
753 | 776 | ||
754 | static void __cpuinit init_cpu_send_mondo_info(struct trap_per_cpu *tb, int use_bootmem) | 777 | static void __cpuinit init_cpu_send_mondo_info(struct trap_per_cpu *tb, int use_bootmem) |
@@ -779,12 +802,12 @@ void __cpuinit sun4v_init_mondo_queues(int use_bootmem, int cpu, int alloc, int | |||
779 | struct trap_per_cpu *tb = &trap_block[cpu]; | 802 | struct trap_per_cpu *tb = &trap_block[cpu]; |
780 | 803 | ||
781 | if (alloc) { | 804 | if (alloc) { |
782 | alloc_one_mondo(&tb->cpu_mondo_pa, use_bootmem); | 805 | alloc_one_mondo(&tb->cpu_mondo_pa, tb->cpu_mondo_qmask, use_bootmem); |
783 | alloc_one_mondo(&tb->dev_mondo_pa, use_bootmem); | 806 | alloc_one_mondo(&tb->dev_mondo_pa, tb->dev_mondo_qmask, use_bootmem); |
784 | alloc_one_mondo(&tb->resum_mondo_pa, use_bootmem); | 807 | alloc_one_mondo(&tb->resum_mondo_pa, tb->resum_qmask, use_bootmem); |
785 | alloc_one_kbuf(&tb->resum_kernel_buf_pa, use_bootmem); | 808 | alloc_one_kbuf(&tb->resum_kernel_buf_pa, tb->resum_qmask, use_bootmem); |
786 | alloc_one_mondo(&tb->nonresum_mondo_pa, use_bootmem); | 809 | alloc_one_mondo(&tb->nonresum_mondo_pa, tb->nonresum_qmask, use_bootmem); |
787 | alloc_one_kbuf(&tb->nonresum_kernel_buf_pa, use_bootmem); | 810 | alloc_one_kbuf(&tb->nonresum_kernel_buf_pa, tb->nonresum_qmask, use_bootmem); |
788 | 811 | ||
789 | init_cpu_send_mondo_info(tb, use_bootmem); | 812 | init_cpu_send_mondo_info(tb, use_bootmem); |
790 | } | 813 | } |