diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-29 14:03:42 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-29 14:03:42 -0700 |
| commit | 6e98ee75c3ab99db48ecc0615c2246dc193111a9 (patch) | |
| tree | afdad9dc968ebef3787e7dc16a41290a525f18f5 /arch/sparc64/kernel/irq.c | |
| parent | 486b4ce13221aa6cd0cbc9fff6993f444d8a52b5 (diff) | |
| parent | 7db35f31cbb8ca1dbaba03d74b7db79ace084358 (diff) | |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6:
[SPARC64]: Fill holes in hypervisor APIs and fix KTSB registry.
[SPARC64]: Fix two bugs wrt. kernel 4MB TSB.
[SPARC]: Mark as emulating cmpxchg, add appropriate depends for DRM.
[SPARC]: Emulate cmpxchg like parisc
[SPARC64]: Fix _PAGE_EXEC_4U check in sun4u I-TLB miss handler.
[SPARC]: Linux always started with 9600 8N1
[SPARC64]: arch/sparc64/time.c doesn't compile on Ultra 1 (no PCI)
[SPARC64]: Eliminate NR_CPUS limitations.
[SPARC64]: Use machine description and OBP properly for cpu probing.
[SPARC64]: Negotiate hypervisor API for PCI services.
[SPARC64]: Report proper system soft state to the hypervisor.
[SPARC64]: Fix typo in sun4v_hvapi_register error handling.
[SCSI] ESP: Kill SCSI_ESP_CORE and link directly just like jazz_esp
[SCSI] jazz_esp: Converted to use esp_core.
[SPARC64]: PCI device scan is way too verbose by default.
[SERIAL] sunzilog: section mismatch fix
[SPARC32]: Removes mismatch section warnigs in sparc time.c file
[SPARC64]: Don't be picky about virtual-dma values on sun4v.
[SPARC64]: Kill unused DIE_PAGE_FAULT enum value.
[SCSI] pluto: Use wait_for_completion_timeout.
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: return 0; } -extern unsigned long real_hard_smp_processor_id(void); - static unsigned int sun4u_compute_tid(unsigned long imap, unsigned long cpuid) { unsigned int tid; @@ -694,9 +692,20 @@ void init_irqwork_curcpu(void) trap_block[cpu].irq_worklist = 0; } -static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type) +/* Please be very careful with register_one_mondo() and + * sun4v_register_mondo_queues(). + * + * On SMP this gets invoked from the CPU trampoline before + * the cpu has fully taken over the trap table from OBP, + * and it's kernel stack + %g6 thread register state is + * not fully cooked yet. + * + * Therefore you cannot make any OBP calls, not even prom_printf, + * from these two routines. + */ +static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type, unsigned long qmask) { - unsigned long num_entries = 128; + unsigned long num_entries = (qmask + 1) / 64; unsigned long status; status = sun4v_cpu_qconf(type, paddr, num_entries); @@ -711,44 +720,58 @@ static void __cpuinit sun4v_register_mondo_queues(int this_cpu) { struct trap_per_cpu *tb = &trap_block[this_cpu]; - register_one_mondo(tb->cpu_mondo_pa, HV_CPU_QUEUE_CPU_MONDO); - register_one_mondo(tb->dev_mondo_pa, HV_CPU_QUEUE_DEVICE_MONDO); - register_one_mondo(tb->resum_mondo_pa, HV_CPU_QUEUE_RES_ERROR); - register_one_mondo(tb->nonresum_mondo_pa, HV_CPU_QUEUE_NONRES_ERROR); + register_one_mondo(tb->cpu_mondo_pa, HV_CPU_QUEUE_CPU_MONDO, + tb->cpu_mondo_qmask); + register_one_mondo(tb->dev_mondo_pa, HV_CPU_QUEUE_DEVICE_MONDO, + tb->dev_mondo_qmask); + register_one_mondo(tb->resum_mondo_pa, HV_CPU_QUEUE_RES_ERROR, + tb->resum_qmask); + register_one_mondo(tb->nonresum_mondo_pa, HV_CPU_QUEUE_NONRES_ERROR, + tb->nonresum_qmask); } -static void __cpuinit alloc_one_mondo(unsigned long *pa_ptr, int use_bootmem) +static void __cpuinit alloc_one_mondo(unsigned long *pa_ptr, unsigned long qmask, int use_bootmem) { - void *page; + unsigned long size = PAGE_ALIGN(qmask + 1); + unsigned long order = get_order(size); + void *p = NULL; - if (use_bootmem) - page = alloc_bootmem_low_pages(PAGE_SIZE); - else - page = (void *) get_zeroed_page(GFP_ATOMIC); + if (use_bootmem) { + p = __alloc_bootmem_low(size, size, 0); + } else { + struct page *page = alloc_pages(GFP_ATOMIC | __GFP_ZERO, order); + if (page) + p = page_address(page); + } - if (!page) { + if (!p) { prom_printf("SUN4V: Error, cannot allocate mondo queue.\n"); prom_halt(); } - *pa_ptr = __pa(page); + *pa_ptr = __pa(p); } -static void __cpuinit alloc_one_kbuf(unsigned long *pa_ptr, int use_bootmem) +static void __cpuinit alloc_one_kbuf(unsigned long *pa_ptr, unsigned long qmask, int use_bootmem) { - void *page; + unsigned long size = PAGE_ALIGN(qmask + 1); + unsigned long order = get_order(size); + void *p = NULL; - if (use_bootmem) - page = alloc_bootmem_low_pages(PAGE_SIZE); - else - page = (void *) get_zeroed_page(GFP_ATOMIC); + if (use_bootmem) { + p = __alloc_bootmem_low(size, size, 0); + } else { + struct page *page = alloc_pages(GFP_ATOMIC | __GFP_ZERO, order); + if (page) + p = page_address(page); + } - if (!page) { + if (!p) { prom_printf("SUN4V: Error, cannot allocate kbuf page.\n"); prom_halt(); } - *pa_ptr = __pa(page); + *pa_ptr = __pa(p); } 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 struct trap_per_cpu *tb = &trap_block[cpu]; if (alloc) { - alloc_one_mondo(&tb->cpu_mondo_pa, use_bootmem); - alloc_one_mondo(&tb->dev_mondo_pa, use_bootmem); - alloc_one_mondo(&tb->resum_mondo_pa, use_bootmem); - alloc_one_kbuf(&tb->resum_kernel_buf_pa, use_bootmem); - alloc_one_mondo(&tb->nonresum_mondo_pa, use_bootmem); - alloc_one_kbuf(&tb->nonresum_kernel_buf_pa, use_bootmem); + alloc_one_mondo(&tb->cpu_mondo_pa, tb->cpu_mondo_qmask, use_bootmem); + alloc_one_mondo(&tb->dev_mondo_pa, tb->dev_mondo_qmask, use_bootmem); + alloc_one_mondo(&tb->resum_mondo_pa, tb->resum_qmask, use_bootmem); + alloc_one_kbuf(&tb->resum_kernel_buf_pa, tb->resum_qmask, use_bootmem); + alloc_one_mondo(&tb->nonresum_mondo_pa, tb->nonresum_qmask, use_bootmem); + alloc_one_kbuf(&tb->nonresum_kernel_buf_pa, tb->nonresum_qmask, use_bootmem); init_cpu_send_mondo_info(tb, use_bootmem); } |
