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

📄 ipmi_watchdog.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	.read    = ipmi_read,	.poll    = ipmi_poll,	.write   = ipmi_write,	.ioctl   = ipmi_ioctl,	.open    = ipmi_open,	.release = ipmi_close,	.fasync  = ipmi_fasync,};static struct miscdevice ipmi_wdog_miscdev = {	.minor		= WATCHDOG_MINOR,	.name		= "watchdog",	.fops		= &ipmi_wdog_fops};static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,				  void                 *handler_data){	if (msg->msg.data[0] != 0) {		printk(KERN_ERR PFX "response: Error %x on cmd %x\n",		       msg->msg.data[0],		       msg->msg.cmd);	}		ipmi_free_recv_msg(msg);}static void ipmi_wdog_pretimeout_handler(void *handler_data){	if (preaction_val != WDOG_PRETIMEOUT_NONE) {		if (preop_val == WDOG_PREOP_PANIC) {			if (atomic_inc_and_test(&preop_panic_excl))				panic("Watchdog pre-timeout");		} else if (preop_val == WDOG_PREOP_GIVE_DATA) {			spin_lock(&ipmi_read_lock);			data_to_read = 1;			wake_up_interruptible(&read_q);			kill_fasync(&fasync_q, SIGIO, POLL_IN);			spin_unlock(&ipmi_read_lock);		}	}	/* On some machines, the heartbeat will give	   an error and not work unless we re-enable	   the timer.   So do so. */	pretimeout_since_last_heartbeat = 1;}static struct ipmi_user_hndl ipmi_hndlrs ={	.ipmi_recv_hndl           = ipmi_wdog_msg_handler,	.ipmi_watchdog_pretimeout = ipmi_wdog_pretimeout_handler};static void ipmi_register_watchdog(int ipmi_intf){	int rv = -EBUSY;	down_write(&register_sem);	if (watchdog_user)		goto out;	rv = ipmi_create_user(ipmi_intf, &ipmi_hndlrs, NULL, &watchdog_user);	if (rv < 0) {		printk(KERN_CRIT PFX "Unable to register with ipmi\n");		goto out;	}	ipmi_get_version(watchdog_user,			 &ipmi_version_major,			 &ipmi_version_minor);	rv = misc_register(&ipmi_wdog_miscdev);	if (rv < 0) {		ipmi_destroy_user(watchdog_user);		watchdog_user = NULL;		printk(KERN_CRIT PFX "Unable to register misc device\n");	} out:	up_write(&register_sem);	if ((start_now) && (rv == 0)) {		/* Run from startup, so start the timer now. */		start_now = 0; /* Disable this function after first startup. */		ipmi_watchdog_state = action_val;		ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);		printk(KERN_INFO PFX "Starting now!\n");	}}#ifdef HAVE_NMI_HANDLERstatic intipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled){        /* If we are not expecting a timeout, ignore it. */	if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)		return NOTIFY_DONE;	/* If no one else handled the NMI, we assume it was the IPMI           watchdog. */	if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) {		/* On some machines, the heartbeat will give		   an error and not work unless we re-enable		   the timer.   So do so. */		pretimeout_since_last_heartbeat = 1;		if (atomic_inc_and_test(&preop_panic_excl))			panic(PFX "pre-timeout");	}	return NOTIFY_DONE;}static struct nmi_handler ipmi_nmi_handler ={	.link     = LIST_HEAD_INIT(ipmi_nmi_handler.link),	.dev_name = "ipmi_watchdog",	.dev_id   = NULL,	.handler  = ipmi_nmi,	.priority = 0, /* Call us last. */};int nmi_handler_registered;#endifstatic int wdog_reboot_handler(struct notifier_block *this,			       unsigned long         code,			       void                  *unused){	static int reboot_event_handled = 0;	if ((watchdog_user) && (!reboot_event_handled)) {		/* Make sure we only do this once. */		reboot_event_handled = 1;		if (code == SYS_DOWN || code == SYS_HALT) {			/* Disable the WDT if we are shutting down. */			ipmi_watchdog_state = WDOG_TIMEOUT_NONE;			panic_halt_ipmi_set_timeout();		} else {			/* Set a long timer to let the reboot happens, but			   reboot if it hangs. */			timeout = 120;			pretimeout = 0;			ipmi_watchdog_state = WDOG_TIMEOUT_RESET;			panic_halt_ipmi_set_timeout();		}	}	return NOTIFY_OK;}static struct notifier_block wdog_reboot_notifier = {	.notifier_call	= wdog_reboot_handler,	.next		= NULL,	.priority	= 0};static int wdog_panic_handler(struct notifier_block *this,			      unsigned long         event,			      void                  *unused){	static int panic_event_handled = 0;	/* On a panic, if we have a panic timeout, make sure that the thing	   reboots, even if it hangs during that panic. */	if (watchdog_user && !panic_event_handled) {		/* Make sure the panic doesn't hang, and make sure we		   do this only once. */		panic_event_handled = 1;	    		timeout = 255;		pretimeout = 0;		ipmi_watchdog_state = WDOG_TIMEOUT_RESET;		panic_halt_ipmi_set_timeout();	}	return NOTIFY_OK;}static struct notifier_block wdog_panic_notifier = {	.notifier_call	= wdog_panic_handler,	.next		= NULL,	.priority	= 150	/* priority: INT_MAX >= x >= 0 */};static void ipmi_new_smi(int if_num){	ipmi_register_watchdog(if_num);}static void ipmi_smi_gone(int if_num){	/* This can never be called, because once the watchdog is	   registered, the interface can't go away until the watchdog	   is unregistered. */}static struct ipmi_smi_watcher smi_watcher ={	.owner    = THIS_MODULE,	.new_smi  = ipmi_new_smi,	.smi_gone = ipmi_smi_gone};static int action_op(const char *inval, char *outval){	if (outval)		strcpy(outval, action);	if (!inval)		return 0;	if (strcmp(inval, "reset") == 0)		action_val = WDOG_TIMEOUT_RESET;	else if (strcmp(inval, "none") == 0)		action_val = WDOG_TIMEOUT_NONE;	else if (strcmp(inval, "power_cycle") == 0)		action_val = WDOG_TIMEOUT_POWER_CYCLE;	else if (strcmp(inval, "power_off") == 0)		action_val = WDOG_TIMEOUT_POWER_DOWN;	else		return -EINVAL;	strcpy(action, inval);	return 0;}static int preaction_op(const char *inval, char *outval){	if (outval)		strcpy(outval, preaction);	if (!inval)		return 0;	if (strcmp(inval, "pre_none") == 0)		preaction_val = WDOG_PRETIMEOUT_NONE;	else if (strcmp(inval, "pre_smi") == 0)		preaction_val = WDOG_PRETIMEOUT_SMI;#ifdef HAVE_NMI_HANDLER	else if (strcmp(inval, "pre_nmi") == 0)		preaction_val = WDOG_PRETIMEOUT_NMI;#endif	else if (strcmp(inval, "pre_int") == 0)		preaction_val = WDOG_PRETIMEOUT_MSG_INT;	else		return -EINVAL;	strcpy(preaction, inval);	return 0;}static int preop_op(const char *inval, char *outval){	if (outval)		strcpy(outval, preop);	if (!inval)		return 0;	if (strcmp(inval, "preop_none") == 0)		preop_val = WDOG_PREOP_NONE;	else if (strcmp(inval, "preop_panic") == 0)		preop_val = WDOG_PREOP_PANIC;	else if (strcmp(inval, "preop_give_data") == 0)		preop_val = WDOG_PREOP_GIVE_DATA;	else		return -EINVAL;	strcpy(preop, inval);	return 0;}static void check_parms(void){#ifdef HAVE_NMI_HANDLER	int do_nmi = 0;	int rv;	if (preaction_val == WDOG_PRETIMEOUT_NMI) {		do_nmi = 1;		if (preop_val == WDOG_PREOP_GIVE_DATA) {			printk(KERN_WARNING PFX "Pretimeout op is to give data"			       " but NMI pretimeout is enabled, setting"			       " pretimeout op to none\n");			preop_op("preop_none", NULL);			do_nmi = 0;		}#ifdef CONFIG_X86_LOCAL_APIC		if (nmi_watchdog == NMI_IO_APIC) {			printk(KERN_WARNING PFX "nmi_watchdog is set to IO APIC"			       " mode (value is %d), that is incompatible"			       " with using NMI in the IPMI watchdog."			       " Disabling IPMI nmi pretimeout.\n",			       nmi_watchdog);			preaction_val = WDOG_PRETIMEOUT_NONE;			do_nmi = 0;		}#endif	}	if (do_nmi && !nmi_handler_registered) {		rv = request_nmi(&ipmi_nmi_handler);		if (rv) {			printk(KERN_WARNING PFX			       "Can't register nmi handler\n");			return;		} else			nmi_handler_registered = 1;	} else if (!do_nmi && nmi_handler_registered) {		release_nmi(&ipmi_nmi_handler);		nmi_handler_registered = 0;	}#endif}static int __init ipmi_wdog_init(void){	int rv;	if (action_op(action, NULL)) {		action_op("reset", NULL);		printk(KERN_INFO PFX "Unknown action '%s', defaulting to"		       " reset\n", action);	}	if (preaction_op(preaction, NULL)) {		preaction_op("pre_none", NULL);		printk(KERN_INFO PFX "Unknown preaction '%s', defaulting to"		       " none\n", preaction);	}	if (preop_op(preop, NULL)) {		preop_op("preop_none", NULL);		printk(KERN_INFO PFX "Unknown preop '%s', defaulting to"		       " none\n", preop);	}	check_parms();	rv = ipmi_smi_watcher_register(&smi_watcher);	if (rv) {#ifdef HAVE_NMI_HANDLER		if (preaction_val == WDOG_PRETIMEOUT_NMI)			release_nmi(&ipmi_nmi_handler);#endif		printk(KERN_WARNING PFX "can't register smi watcher\n");		return rv;	}	register_reboot_notifier(&wdog_reboot_notifier);	notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier);	printk(KERN_INFO PFX "driver initialized\n");	return 0;}static __exit void ipmi_unregister_watchdog(void){	int rv;	down_write(&register_sem);#ifdef HAVE_NMI_HANDLER	if (nmi_handler_registered)		release_nmi(&ipmi_nmi_handler);#endif	notifier_chain_unregister(&panic_notifier_list, &wdog_panic_notifier);	unregister_reboot_notifier(&wdog_reboot_notifier);	if (! watchdog_user)		goto out;	/* Make sure no one can call us any more. */	misc_deregister(&ipmi_wdog_miscdev);	/* Wait to make sure the message makes it out.  The lower layer has	   pointers to our buffers, we want to make sure they are done before	   we release our memory. */	while (atomic_read(&set_timeout_tofree))		schedule_timeout_uninterruptible(1);	/* Disconnect from IPMI. */	rv = ipmi_destroy_user(watchdog_user);	if (rv) {		printk(KERN_WARNING PFX "error unlinking from IPMI: %d\n",		       rv);	}	watchdog_user = NULL; out:	up_write(&register_sem);}static void __exit ipmi_wdog_exit(void){	ipmi_smi_watcher_unregister(&smi_watcher);	ipmi_unregister_watchdog();}module_exit(ipmi_wdog_exit);module_init(ipmi_wdog_init);MODULE_LICENSE("GPL");MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");MODULE_DESCRIPTION("watchdog timer based upon the IPMI interface.");

⌨️ 快捷键说明

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