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

📄 xpc_main.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
				spin_lock(&part->IPI_lock);				XPC_SET_IPI_FLAGS(part->local_IPI_amo,					ch->number, ch->delayed_IPI_flags);				spin_unlock(&part->IPI_lock);				wakeup_channel_mgr = 1;			}			ch->delayed_IPI_flags = 0;		}		ch->flags &= ~XPC_C_WDISCONNECT;		spin_unlock_irqrestore(&ch->lock, irq_flags);		if (wakeup_channel_mgr) {			xpc_wakeup_channel_mgr(part);		}		xpc_part_deref(part);	}}static voidxpc_do_exit(enum xpc_retval reason){	partid_t partid;	int active_part_count;	struct xpc_partition *part;	unsigned long printmsg_time;	/* a 'rmmod XPC' and a 'reboot' cannot both end up here together */	DBUG_ON(xpc_exiting == 1);	/*	 * Let the heartbeat checker thread and the discovery thread	 * (if one is running) know that they should exit. Also wake up	 * the heartbeat checker thread in case it's sleeping.	 */	xpc_exiting = 1;	wake_up_interruptible(&xpc_act_IRQ_wq);	/* ignore all incoming interrupts */	free_irq(SGI_XPC_ACTIVATE, NULL);	/* wait for the discovery thread to exit */	down(&xpc_discovery_exited);	/* wait for the heartbeat checker thread to exit */	down(&xpc_hb_checker_exited);	/* sleep for a 1/3 of a second or so */	(void) msleep_interruptible(300);	/* wait for all partitions to become inactive */	printmsg_time = jiffies;	do {		active_part_count = 0;		for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {			part = &xpc_partitions[partid];			if (xpc_partition_disengaged(part) &&					part->act_state == XPC_P_INACTIVE) {				continue;			}			active_part_count++;			XPC_DEACTIVATE_PARTITION(part, reason);		}		if (active_part_count == 0) {			break;		}		if (jiffies >= printmsg_time) {			dev_info(xpc_part, "waiting for partitions to "				"deactivate/disengage, active count=%d, remote "				"engaged=0x%lx\n", active_part_count,				xpc_partition_engaged(1UL << partid));			printmsg_time = jiffies +					(XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ);		}		/* sleep for a 1/3 of a second or so */		(void) msleep_interruptible(300);	} while (1);	DBUG_ON(xpc_partition_engaged(-1UL));	/* indicate to others that our reserved page is uninitialized */	xpc_rsvd_page->vars_pa = 0;	/* now it's time to eliminate our heartbeat */	del_timer_sync(&xpc_hb_timer);	DBUG_ON(xpc_vars->heartbeating_to_mask != 0);	/* take ourselves off of the reboot_notifier_list */	(void) unregister_reboot_notifier(&xpc_reboot_notifier);	/* take ourselves off of the die_notifier list */	(void) unregister_die_notifier(&xpc_die_notifier);	/* close down protections for IPI operations */	xpc_restrict_IPI_ops();	/* clear the interface to XPC's functions */	xpc_clear_interface();	if (xpc_sysctl) {		unregister_sysctl_table(xpc_sysctl);	}}/* * Called when the system is about to be either restarted or halted. */static voidxpc_die_disengage(void){	struct xpc_partition *part;	partid_t partid;	unsigned long engaged;	long time, print_time, disengage_request_timeout;	/* keep xpc_hb_checker thread from doing anything (just in case) */	xpc_exiting = 1;	xpc_vars->heartbeating_to_mask = 0;  /* indicate we're deactivated */	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {		part = &xpc_partitions[partid];		if (!XPC_SUPPORTS_DISENGAGE_REQUEST(part->							remote_vars_version)) {			/* just in case it was left set by an earlier XPC */			xpc_clear_partition_engaged(1UL << partid);			continue;		}		if (xpc_partition_engaged(1UL << partid) ||					part->act_state != XPC_P_INACTIVE) {			xpc_request_partition_disengage(part);			xpc_mark_partition_disengaged(part);			xpc_IPI_send_disengage(part);		}	}	print_time = rtc_time();	disengage_request_timeout = print_time +		(xpc_disengage_request_timelimit * sn_rtc_cycles_per_second);	/* wait for all other partitions to disengage from us */	while ((engaged = xpc_partition_engaged(-1UL)) &&			(time = rtc_time()) < disengage_request_timeout) {		if (time >= print_time) {			dev_info(xpc_part, "waiting for remote partitions to "				"disengage, engaged=0x%lx\n", engaged);			print_time = time + (XPC_DISENGAGE_PRINTMSG_INTERVAL *						sn_rtc_cycles_per_second);		}	}	dev_info(xpc_part, "finished waiting for remote partitions to "				"disengage, engaged=0x%lx\n", engaged);}/* * This function is called when the system is being rebooted. */static intxpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused){	enum xpc_retval reason;	switch (event) {	case SYS_RESTART:		reason = xpcSystemReboot;		break;	case SYS_HALT:		reason = xpcSystemHalt;		break;	case SYS_POWER_OFF:		reason = xpcSystemPoweroff;		break;	default:		reason = xpcSystemGoingDown;	}	xpc_do_exit(reason);	return NOTIFY_DONE;}/* * This function is called when the system is being rebooted. */static intxpc_system_die(struct notifier_block *nb, unsigned long event, void *unused){	switch (event) {	case DIE_MACHINE_RESTART:	case DIE_MACHINE_HALT:		xpc_die_disengage();		break;	case DIE_MCA_MONARCH_ENTER:	case DIE_INIT_MONARCH_ENTER:		xpc_vars->heartbeat++;		xpc_vars->heartbeat_offline = 1;		break;	case DIE_MCA_MONARCH_LEAVE:	case DIE_INIT_MONARCH_LEAVE:		xpc_vars->heartbeat++;		xpc_vars->heartbeat_offline = 0;		break;	}	return NOTIFY_DONE;}int __initxpc_init(void){	int ret;	partid_t partid;	struct xpc_partition *part;	pid_t pid;	if (!ia64_platform_is("sn2")) {		return -ENODEV;	}	/*	 * xpc_remote_copy_buffer is used as a temporary buffer for bte_copy'ng	 * various portions of a partition's reserved page. Its size is based	 * on the size of the reserved page header and part_nasids mask. So we	 * need to ensure that the other items will fit as well.	 */	if (XPC_RP_VARS_SIZE > XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES) {		dev_err(xpc_part, "xpc_remote_copy_buffer is not big enough\n");		return -EPERM;	}	DBUG_ON((u64) xpc_remote_copy_buffer !=				L1_CACHE_ALIGN((u64) xpc_remote_copy_buffer));	snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part");	snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan");	xpc_sysctl = register_sysctl_table(xpc_sys_dir, 1);	/*	 * The first few fields of each entry of xpc_partitions[] need to	 * be initialized now so that calls to xpc_connect() and	 * xpc_disconnect() can be made prior to the activation of any remote	 * partition. NOTE THAT NONE OF THE OTHER FIELDS BELONGING TO THESE	 * ENTRIES ARE MEANINGFUL UNTIL AFTER AN ENTRY'S CORRESPONDING	 * PARTITION HAS BEEN ACTIVATED.	 */	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {		part = &xpc_partitions[partid];		DBUG_ON((u64) part != L1_CACHE_ALIGN((u64) part));		part->act_IRQ_rcvd = 0;		spin_lock_init(&part->act_lock);		part->act_state = XPC_P_INACTIVE;		XPC_SET_REASON(part, 0, 0);		init_timer(&part->disengage_request_timer);		part->disengage_request_timer.function =				xpc_timeout_partition_disengage_request;		part->disengage_request_timer.data = (unsigned long) part;		part->setup_state = XPC_P_UNSET;		init_waitqueue_head(&part->teardown_wq);		atomic_set(&part->references, 0);	}	/*	 * Open up protections for IPI operations (and AMO operations on	 * Shub 1.1 systems).	 */	xpc_allow_IPI_ops();	/*	 * Interrupts being processed will increment this atomic variable and	 * awaken the heartbeat thread which will process the interrupts.	 */	atomic_set(&xpc_act_IRQ_rcvd, 0);	/*	 * This is safe to do before the xpc_hb_checker thread has started	 * because the handler releases a wait queue.  If an interrupt is	 * received before the thread is waiting, it will not go to sleep,	 * but rather immediately process the interrupt.	 */	ret = request_irq(SGI_XPC_ACTIVATE, xpc_act_IRQ_handler, 0,							"xpc hb", NULL);	if (ret != 0) {		dev_err(xpc_part, "can't register ACTIVATE IRQ handler, "			"errno=%d\n", -ret);		xpc_restrict_IPI_ops();		if (xpc_sysctl) {			unregister_sysctl_table(xpc_sysctl);		}		return -EBUSY;	}	/*	 * Fill the partition reserved page with the information needed by	 * other partitions to discover we are alive and establish initial	 * communications.	 */	xpc_rsvd_page = xpc_rsvd_page_init();	if (xpc_rsvd_page == NULL) {		dev_err(xpc_part, "could not setup our reserved page\n");		free_irq(SGI_XPC_ACTIVATE, NULL);		xpc_restrict_IPI_ops();		if (xpc_sysctl) {			unregister_sysctl_table(xpc_sysctl);		}		return -EBUSY;	}	/* add ourselves to the reboot_notifier_list */	ret = register_reboot_notifier(&xpc_reboot_notifier);	if (ret != 0) {		dev_warn(xpc_part, "can't register reboot notifier\n");	}	/* add ourselves to the die_notifier list (i.e., ia64die_chain) */	ret = register_die_notifier(&xpc_die_notifier);	if (ret != 0) {		dev_warn(xpc_part, "can't register die notifier\n");	}	/*	 * Set the beating to other partitions into motion.  This is	 * the last requirement for other partitions' discovery to	 * initiate communications with us.	 */	init_timer(&xpc_hb_timer);	xpc_hb_timer.function = xpc_hb_beater;	xpc_hb_beater(0);	/*	 * The real work-horse behind xpc.  This processes incoming	 * interrupts and monitors remote heartbeats.	 */	pid = kernel_thread(xpc_hb_checker, NULL, 0);	if (pid < 0) {		dev_err(xpc_part, "failed while forking hb check thread\n");		/* indicate to others that our reserved page is uninitialized */		xpc_rsvd_page->vars_pa = 0;		/* take ourselves off of the reboot_notifier_list */		(void) unregister_reboot_notifier(&xpc_reboot_notifier);		/* take ourselves off of the die_notifier list */		(void) unregister_die_notifier(&xpc_die_notifier);		del_timer_sync(&xpc_hb_timer);		free_irq(SGI_XPC_ACTIVATE, NULL);		xpc_restrict_IPI_ops();		if (xpc_sysctl) {			unregister_sysctl_table(xpc_sysctl);		}		return -EBUSY;	}	/*	 * Startup a thread that will attempt to discover other partitions to	 * activate based on info provided by SAL. This new thread is short	 * lived and will exit once discovery is complete.	 */	pid = kernel_thread(xpc_initiate_discovery, NULL, 0);	if (pid < 0) {		dev_err(xpc_part, "failed while forking discovery thread\n");		/* mark this new thread as a non-starter */		up(&xpc_discovery_exited);		xpc_do_exit(xpcUnloading);		return -EBUSY;	}	/* set the interface to point at XPC's functions */	xpc_set_interface(xpc_initiate_connect, xpc_initiate_disconnect,			  xpc_initiate_allocate, xpc_initiate_send,			  xpc_initiate_send_notify, xpc_initiate_received,			  xpc_initiate_partid_to_nasids);	return 0;}module_init(xpc_init);void __exitxpc_exit(void){	xpc_do_exit(xpcUnloading);}module_exit(xpc_exit);MODULE_AUTHOR("Silicon Graphics, Inc.");MODULE_DESCRIPTION("Cross Partition Communication (XPC) support");MODULE_LICENSE("GPL");module_param(xpc_hb_interval, int, 0);MODULE_PARM_DESC(xpc_hb_interval, "Number of seconds between "		"heartbeat increments.");module_param(xpc_hb_check_interval, int, 0);MODULE_PARM_DESC(xpc_hb_check_interval, "Number of seconds between "		"heartbeat checks.");module_param(xpc_disengage_request_timelimit, int, 0);MODULE_PARM_DESC(xpc_disengage_request_timelimit, "Number of seconds to wait "		"for disengage request to complete.");

⌨️ 快捷键说明

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