⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sn2_smp.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
				if ((deadlock = wait_piowc())) {					if (flush_opt == 1)						goto done;					sn2_ptc_deadlock_recovery(nasids, ibegin, i, mynasid, ptc0, data0, ptc1, data1);					if (reset_max_active_on_deadlock())						max_active = 1;				}				active = 0;				ibegin = i + 1;			}		}		start += (1UL << nbits);	} while (start < end);done:	itc2 = ia64_get_itc() - itc2;	__get_cpu_var(ptcstats).shub_itc_clocks += itc2;	if (itc2 > __get_cpu_var(ptcstats).shub_itc_clocks_max)		__get_cpu_var(ptcstats).shub_itc_clocks_max = itc2;	if (old_rr) {		ia64_set_rr(start, old_rr);		ia64_srlz_d();	}	spin_unlock_irqrestore(PTC_LOCK(shub1), flags);	if (flush_opt == 1 && deadlock) {		__get_cpu_var(ptcstats).deadlocks++;		sn2_ipi_flush_all_tlb(mm);	}	preempt_enable();}/* * sn2_ptc_deadlock_recovery * * Recover from PTC deadlocks conditions. Recovery requires stepping thru each  * TLB flush transaction.  The recovery sequence is somewhat tricky & is * coded in assembly language. */voidsn2_ptc_deadlock_recovery(short *nasids, short ib, short ie, int mynasid,			  volatile unsigned long *ptc0, unsigned long data0,			  volatile unsigned long *ptc1, unsigned long data1){	short nasid, i;	unsigned long *piows, zeroval, n;	__get_cpu_var(ptcstats).deadlocks++;	piows = (unsigned long *) pda->pio_write_status_addr;	zeroval = pda->pio_write_status_val;	for (i=ib; i <= ie; i++) {		nasid = nasids[i];		if (local_node_uses_ptc_ga(is_shub1()) && nasid == mynasid)			continue;		ptc0 = CHANGE_NASID(nasid, ptc0);		if (ptc1)			ptc1 = CHANGE_NASID(nasid, ptc1);		n = sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval);		__get_cpu_var(ptcstats).deadlocks2 += n;	}}/** * 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 * * Sends an IPI (interprocessor interrupt) to the processor specified by * @physid * * @delivery_mode can be one of the following * * %IA64_IPI_DM_INT - pend an interrupt * %IA64_IPI_DM_PMI - pend a PMI * %IA64_IPI_DM_NMI - pend an NMI * %IA64_IPI_DM_INIT - pend an INIT interrupt */void sn_send_IPI_phys(int nasid, long physid, int vector, int delivery_mode){	long val;	unsigned long flags = 0;	volatile long *p;	p = (long *)GLOBAL_MMR_PHYS_ADDR(nasid, SH_IPI_INT);	val = (1UL << SH_IPI_INT_SEND_SHFT) |	    (physid << SH_IPI_INT_PID_SHFT) |	    ((long)delivery_mode << SH_IPI_INT_TYPE_SHFT) |	    ((long)vector << SH_IPI_INT_IDX_SHFT) |	    (0x000feeUL << SH_IPI_INT_BASE_SHFT);	mb();	if (enable_shub_wars_1_1()) {		spin_lock_irqsave(&sn2_global_ptc_lock, flags);	}	pio_phys_write_mmr(p, val);	if (enable_shub_wars_1_1()) {		wait_piowc();		spin_unlock_irqrestore(&sn2_global_ptc_lock, flags);	}}EXPORT_SYMBOL(sn_send_IPI_phys);/** * sn2_send_IPI - send an IPI to a processor * @cpuid: target of the IPI * @vector: command to send * @delivery_mode: delivery mechanism * @redirect: redirect the IPI? * * Sends an IPI (InterProcessor Interrupt) to the processor specified by * @cpuid.  @vector specifies the command to send, while @delivery_mode can  * be one of the following * * %IA64_IPI_DM_INT - pend an interrupt * %IA64_IPI_DM_PMI - pend a PMI * %IA64_IPI_DM_NMI - pend an NMI * %IA64_IPI_DM_INIT - pend an INIT interrupt */void sn2_send_IPI(int cpuid, int vector, int delivery_mode, int redirect){	long physid;	int nasid;	physid = cpu_physical_id(cpuid);	nasid = cpuid_to_nasid(cpuid);	/* the following is used only when starting cpus at boot time */	if (unlikely(nasid == -1))		ia64_sn_get_sapic_info(physid, &nasid, NULL, NULL);	sn_send_IPI_phys(nasid, physid, vector, delivery_mode);}#ifdef CONFIG_HOTPLUG_CPU/** * sn_cpu_disable_allowed - Determine if a CPU can be disabled. * @cpu - CPU that is requested to be disabled. * * CPU disable is only allowed on SHub2 systems running with a PROM * that supports CPU disable. It is not permitted to disable the boot processor. */bool sn_cpu_disable_allowed(int cpu){	if (is_shub2() && sn_prom_feature_available(PRF_CPU_DISABLE_SUPPORT)) {		if (cpu != 0)			return true;		else			printk(KERN_WARNING			      "Disabling the boot processor is not allowed.\n");	} else		printk(KERN_WARNING		       "CPU disable is not supported on this system.\n");	return false;}#endif /* CONFIG_HOTPLUG_CPU */#ifdef CONFIG_PROC_FS#define PTC_BASENAME	"sgi_sn/ptc_statistics"static void *sn2_ptc_seq_start(struct seq_file *file, loff_t * offset){	if (*offset < NR_CPUS)		return offset;	return NULL;}static void *sn2_ptc_seq_next(struct seq_file *file, void *data, loff_t * offset){	(*offset)++;	if (*offset < NR_CPUS)		return offset;	return NULL;}static void sn2_ptc_seq_stop(struct seq_file *file, void *data){}static int sn2_ptc_seq_show(struct seq_file *file, void *data){	struct ptc_stats *stat;	int cpu;	cpu = *(loff_t *) data;	if (!cpu) {		seq_printf(file,			   "# cpu ptc_l newrid ptc_flushes nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max not_my_mm deadlock2 ipi_fluches ipi_nsec\n");		seq_printf(file, "# ptctest %d, flushopt %d\n", sn2_ptctest, sn2_flush_opt);	}	if (cpu < NR_CPUS && cpu_online(cpu)) {		stat = &per_cpu(ptcstats, cpu);		seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l,				stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed,				stat->deadlocks,				1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec,				1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec,				1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec,				stat->shub_ptc_flushes_not_my_mm,				stat->deadlocks2,				stat->shub_ipi_flushes,				1000 * stat->shub_ipi_flushes_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec);	}	return 0;}static ssize_t sn2_ptc_proc_write(struct file *file, const char __user *user, size_t count, loff_t *data){	int cpu;	char optstr[64];	if (copy_from_user(optstr, user, count))		return -EFAULT;	optstr[count - 1] = '\0';	sn2_flush_opt = simple_strtoul(optstr, NULL, 0);	for_each_online_cpu(cpu)		memset(&per_cpu(ptcstats, cpu), 0, sizeof(struct ptc_stats));	return count;}static struct seq_operations sn2_ptc_seq_ops = {	.start = sn2_ptc_seq_start,	.next = sn2_ptc_seq_next,	.stop = sn2_ptc_seq_stop,	.show = sn2_ptc_seq_show};static int sn2_ptc_proc_open(struct inode *inode, struct file *file){	return seq_open(file, &sn2_ptc_seq_ops);}static const struct file_operations proc_sn2_ptc_operations = {	.open = sn2_ptc_proc_open,	.read = seq_read,	.write = sn2_ptc_proc_write,	.llseek = seq_lseek,	.release = seq_release,};static struct proc_dir_entry *proc_sn2_ptc;static int __init sn2_ptc_init(void){	if (!ia64_platform_is("sn2"))		return 0;	if (!(proc_sn2_ptc = create_proc_entry(PTC_BASENAME, 0444, NULL))) {		printk(KERN_ERR "unable to create %s proc entry", PTC_BASENAME);		return -EINVAL;	}	proc_sn2_ptc->proc_fops = &proc_sn2_ptc_operations;	spin_lock_init(&sn2_global_ptc_lock);	return 0;}static void __exit sn2_ptc_exit(void){	remove_proc_entry(PTC_BASENAME, NULL);}module_init(sn2_ptc_init);module_exit(sn2_ptc_exit);#endif /* CONFIG_PROC_FS */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -