X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fia64%2Fsn%2Fkernel%2Fsn2%2Fsn2_smp.c;h=7af05a7ac743a2416774ef75245f51b0d0b203a4;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=3ee7c10afe003c8cea77ee56d1f9faefd923bc0b;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c index 3ee7c10af..7af05a7ac 100644 --- a/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c @@ -18,10 +18,11 @@ #include #include #include +#include +#include #include #include -#include #include #include #include @@ -29,46 +30,41 @@ #include #include #include -#include #include #include #include +#include #include -#include +#include #include #include -void sn2_ptc_deadlock_recovery(unsigned long data0, unsigned long data1); +void sn2_ptc_deadlock_recovery(volatile unsigned long *, unsigned long data0, + volatile unsigned long *, unsigned long data1); - -static spinlock_t sn2_global_ptc_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED; +static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock); static unsigned long sn2_ptc_deadlock_count; - -static inline unsigned long -wait_piowc(void) +static inline unsigned long wait_piowc(void) { - volatile unsigned long *piows; - unsigned long ws; + volatile unsigned long *piows, zeroval; + unsigned long ws; piows = pda->pio_write_status_addr; + zeroval = pda->pio_write_status_val; do { - ia64_mfa(); - } while (((ws = *piows) & SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK) != - SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK); + cpu_relax(); + } while (((ws = *piows) & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK) != zeroval); return ws; } - -void -sn_tlb_migrate_finish(struct mm_struct *mm) +void sn_tlb_migrate_finish(struct mm_struct *mm) { if (mm == current->mm) flush_tlb_mm(mm); } - /** * sn2_global_tlb_purge - globally purge translation cache of virtual address range * @start: start of virtual address range @@ -90,22 +86,22 @@ sn_tlb_migrate_finish(struct mm_struct *mm) */ void -sn2_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbits) +sn2_global_tlb_purge(unsigned long start, unsigned long end, + unsigned long nbits) { - int i, cnode, mynasid, cpu, lcpu=0, nasid, flushed=0; - volatile unsigned long *ptc0, *ptc1; - unsigned long flags=0, data0, data1; - struct mm_struct *mm=current->active_mm; - short nasids[NR_NODES], nix; - DECLARE_BITMAP(nodes_flushed, NR_NODES); - - bitmap_zero(nodes_flushed, NR_NODES); - + int i, shub1, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0; + volatile unsigned long *ptc0, *ptc1; + unsigned long flags = 0, data0 = 0, data1 = 0; + struct mm_struct *mm = current->active_mm; + short nasids[MAX_NUMNODES], nix; + nodemask_t nodes_flushed; + + nodes_clear(nodes_flushed); i = 0; for_each_cpu_mask(cpu, mm->cpu_vm_mask) { cnode = cpu_to_node(cpu); - __set_bit(cnode, nodes_flushed); + node_set(cnode, nodes_flushed); lcpu = cpu; i++; } @@ -114,7 +110,7 @@ sn2_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbit if (likely(i == 1 && lcpu == smp_processor_id())) { do { - ia64_ptcl(start, nbits<<2); + ia64_ptcl(start, nbits << 2); start += (1UL << nbits); } while (start < end); ia64_srlz_i(); @@ -128,43 +124,56 @@ sn2_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbit return; } - nix = 0; - for (cnode=find_first_bit(&nodes_flushed, NR_NODES); cnode < NR_NODES; - cnode=find_next_bit(&nodes_flushed, NR_NODES, ++cnode)) + for_each_node_mask(cnode, nodes_flushed) nasids[nix++] = cnodeid_to_nasid(cnode); + shub1 = is_shub1(); + if (shub1) { + data0 = (1UL << SH1_PTC_0_A_SHFT) | + (nbits << SH1_PTC_0_PS_SHFT) | + ((ia64_get_rr(start) >> 8) << SH1_PTC_0_RID_SHFT) | + (1UL << SH1_PTC_0_START_SHFT); + ptc0 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH1_PTC_0); + ptc1 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH1_PTC_1); + } else { + data0 = (1UL << SH2_PTC_A_SHFT) | + (nbits << SH2_PTC_PS_SHFT) | + (1UL << SH2_PTC_START_SHFT); + ptc0 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH2_PTC + + ((ia64_get_rr(start) >> 8) << SH2_PTC_RID_SHFT) ); + ptc1 = NULL; + } + - data0 = (1UL<>8)<pio_write_status_addr; + piows = pda->pio_write_status_addr; + zeroval = pda->pio_write_status_val; mycnode = numa_node_id(); - for (cnode = 0; cnode < numnodes; cnode++) { + for_each_online_node(cnode) { if (is_headless_node(cnode) || cnode == mycnode) continue; nasid = cnodeid_to_nasid(cnode); ptc0 = CHANGE_NASID(nasid, ptc0); - ptc1 = CHANGE_NASID(nasid, ptc1); - sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows); + if (ptc1) + ptc1 = CHANGE_NASID(nasid, ptc1); + sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval); } } /** * sn_send_IPI_phys - send an IPI to a Nasid and slice + * @nasid: nasid to receive the interrupt (may be outside partition) * @physid: physical cpuid to receive the interrupt. * @vector: command to send * @delivery_mode: delivery mechanism @@ -224,34 +236,31 @@ sn2_ptc_deadlock_recovery(unsigned long data0, unsigned long data1) * %IA64_IPI_DM_NMI - pend an NMI * %IA64_IPI_DM_INIT - pend an INIT interrupt */ -void -sn_send_IPI_phys(long physid, int vector, int delivery_mode) +void sn_send_IPI_phys(int nasid, long physid, int vector, int delivery_mode) { - long nasid, slice, val; - unsigned long flags=0; - volatile long *p; - - nasid = cpu_physical_id_to_nasid(physid); - slice = cpu_physical_id_to_slice(physid); + long val; + unsigned long flags = 0; + volatile long *p; - p = (long*)GLOBAL_MMR_PHYS_ADDR(nasid, SH_IPI_INT); - val = (1UL<