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

📄 ipmi_watchdog.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
				&set_timeout_recv_msg,				&send_heartbeat_now);	if (rv) {		up(&set_timeout_lock);	} else {		if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB)		    || ((send_heartbeat_now)			&& (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY)))		{			rv = ipmi_heartbeat();		}	}	return rv;}static void dummy_smi_free(struct ipmi_smi_msg *msg){}static void dummy_recv_free(struct ipmi_recv_msg *msg){}static struct ipmi_smi_msg panic_halt_smi_msg ={	.done = dummy_smi_free};static struct ipmi_recv_msg panic_halt_recv_msg ={	.done = dummy_recv_free};/* Special call, doesn't claim any locks.  This is only to be called   at panic or halt time, in run-to-completion mode, when the caller   is the only CPU and the only thing that will be going is these IPMI   calls. */static void panic_halt_ipmi_set_timeout(void){	int send_heartbeat_now;	int rv;	rv = i_ipmi_set_timeout(&panic_halt_smi_msg,				&panic_halt_recv_msg,				&send_heartbeat_now);	if (!rv) {		if (send_heartbeat_now)			panic_halt_ipmi_heartbeat();	}}/* We use a semaphore to make sure that only one thing can send a   heartbeat at one time, because we only have one copy of the data.   The semaphore is claimed when the set_timeout is sent and freed   when both messages are free. */static atomic_t heartbeat_tofree = ATOMIC_INIT(0);static DECLARE_MUTEX(heartbeat_lock);static DECLARE_MUTEX_LOCKED(heartbeat_wait_lock);static void heartbeat_free_smi(struct ipmi_smi_msg *msg){    if (atomic_dec_and_test(&heartbeat_tofree))	    up(&heartbeat_wait_lock);}static void heartbeat_free_recv(struct ipmi_recv_msg *msg){    if (atomic_dec_and_test(&heartbeat_tofree))	    up(&heartbeat_wait_lock);}static struct ipmi_smi_msg heartbeat_smi_msg ={	.done = heartbeat_free_smi};static struct ipmi_recv_msg heartbeat_recv_msg ={	.done = heartbeat_free_recv}; static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg ={	.done = dummy_smi_free};static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg ={	.done = dummy_recv_free}; static int ipmi_heartbeat(void){	struct kernel_ipmi_msg            msg;	int                               rv;	struct ipmi_system_interface_addr addr;	if (ipmi_ignore_heartbeat) {		return 0;	}	if (ipmi_start_timer_on_heartbeat) {		ipmi_start_timer_on_heartbeat = 0;		ipmi_watchdog_state = action_val;		return ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);	} else if (pretimeout_since_last_heartbeat) {		/* A pretimeout occurred, make sure we set the timeout.		   We don't want to set the action, though, we want to		   leave that alone (thus it can't be combined with the		   above operation. */		pretimeout_since_last_heartbeat = 0;		return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);	}	down(&heartbeat_lock);	atomic_set(&heartbeat_tofree, 2);	/* Don't reset the timer if we have the timer turned off, that           re-enables the watchdog. */	if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) {		up(&heartbeat_lock);		return 0;	}	addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;	addr.channel = IPMI_BMC_CHANNEL;	addr.lun = 0;	msg.netfn = 0x06;	msg.cmd = IPMI_WDOG_RESET_TIMER;	msg.data = NULL;	msg.data_len = 0;	rv = ipmi_request_supply_msgs(watchdog_user,				      (struct ipmi_addr *) &addr,				      0,				      &msg,				      NULL,				      &heartbeat_smi_msg,				      &heartbeat_recv_msg,				      1);	if (rv) {		up(&heartbeat_lock);		printk(KERN_WARNING PFX "heartbeat failure: %d\n",		       rv);		return rv;	}	/* Wait for the heartbeat to be sent. */	down(&heartbeat_wait_lock);	if (heartbeat_recv_msg.msg.data[0] != 0) {	    /* Got an error in the heartbeat response.  It was already	       reported in ipmi_wdog_msg_handler, but we should return	       an error here. */	    rv = -EINVAL;	}	up(&heartbeat_lock);	return rv;}static void panic_halt_ipmi_heartbeat(void){	struct kernel_ipmi_msg             msg;	struct ipmi_system_interface_addr addr;	/* Don't reset the timer if we have the timer turned off, that           re-enables the watchdog. */	if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)		return;	addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;	addr.channel = IPMI_BMC_CHANNEL;	addr.lun = 0;	msg.netfn = 0x06;	msg.cmd = IPMI_WDOG_RESET_TIMER;	msg.data = NULL;	msg.data_len = 0;	ipmi_request_supply_msgs(watchdog_user,				 (struct ipmi_addr *) &addr,				 0,				 &msg,				 NULL,				 &panic_halt_heartbeat_smi_msg,				 &panic_halt_heartbeat_recv_msg,				 1);}static struct watchdog_info ident={	.options	= 0,	/* WDIOF_SETTIMEOUT, */	.firmware_version = 1,	.identity	= "IPMI"};static int ipmi_ioctl(struct inode *inode, struct file *file,		      unsigned int cmd, unsigned long arg){	void __user *argp = (void __user *)arg;	int i;	int val;	switch(cmd) {	case WDIOC_GETSUPPORT:		i = copy_to_user(argp, &ident, sizeof(ident));		return i ? -EFAULT : 0;	case WDIOC_SETTIMEOUT:		i = copy_from_user(&val, argp, sizeof(int));		if (i)			return -EFAULT;		timeout = val;		return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);	case WDIOC_GETTIMEOUT:		i = copy_to_user(argp, &timeout, sizeof(timeout));		if (i)			return -EFAULT;		return 0;	case WDIOC_SET_PRETIMEOUT:		i = copy_from_user(&val, argp, sizeof(int));		if (i)			return -EFAULT;		pretimeout = val;		return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);	case WDIOC_GET_PRETIMEOUT:		i = copy_to_user(argp, &pretimeout, sizeof(pretimeout));		if (i)			return -EFAULT;		return 0;	case WDIOC_KEEPALIVE:		return ipmi_heartbeat();	case WDIOC_SETOPTIONS:		i = copy_from_user(&val, argp, sizeof(int));		if (i)			return -EFAULT;		if (val & WDIOS_DISABLECARD)		{			ipmi_watchdog_state = WDOG_TIMEOUT_NONE;			ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);			ipmi_start_timer_on_heartbeat = 0;		}		if (val & WDIOS_ENABLECARD)		{			ipmi_watchdog_state = action_val;			ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);		}		return 0;	case WDIOC_GETSTATUS:		val = 0;		i = copy_to_user(argp, &val, sizeof(val));		if (i)			return -EFAULT;		return 0;	default:		return -ENOIOCTLCMD;	}}static ssize_t ipmi_write(struct file *file,			  const char  __user *buf,			  size_t      len,			  loff_t      *ppos){	int rv;	if (len) {	    	if (!nowayout) {		    	size_t i;			/* In case it was set long ago */			expect_close = 0;    			for (i = 0; i != len; i++) {				char c;				if (get_user(c, buf + i))					return -EFAULT;				if (c == 'V')					expect_close = 42;			}		}		rv = ipmi_heartbeat();		if (rv)			return rv;		return 1;	}	return 0;}static ssize_t ipmi_read(struct file *file,			 char        __user *buf,			 size_t      count,			 loff_t      *ppos){	int          rv = 0;	wait_queue_t wait;	if (count <= 0)		return 0;	/* Reading returns if the pretimeout has gone off, and it only does	   it once per pretimeout. */	spin_lock(&ipmi_read_lock);	if (!data_to_read) {		if (file->f_flags & O_NONBLOCK) {			rv = -EAGAIN;			goto out;		}				init_waitqueue_entry(&wait, current);		add_wait_queue(&read_q, &wait);		while (!data_to_read) {			set_current_state(TASK_INTERRUPTIBLE);			spin_unlock(&ipmi_read_lock);			schedule();			spin_lock(&ipmi_read_lock);		}		remove_wait_queue(&read_q, &wait);	    		if (signal_pending(current)) {			rv = -ERESTARTSYS;			goto out;		}	}	data_to_read = 0; out:	spin_unlock(&ipmi_read_lock);	if (rv == 0) {		if (copy_to_user(buf, &data_to_read, 1))			rv = -EFAULT;		else			rv = 1;	}	return rv;}static int ipmi_open(struct inode *ino, struct file *filep){        switch (iminor(ino)) {        case WATCHDOG_MINOR:		if (test_and_set_bit(0, &ipmi_wdog_open))                        return -EBUSY;		/* Don't start the timer now, let it start on the		   first heartbeat. */		ipmi_start_timer_on_heartbeat = 1;		return nonseekable_open(ino, filep);	default:		return (-ENODEV);        }}static unsigned int ipmi_poll(struct file *file, poll_table *wait){	unsigned int mask = 0;		poll_wait(file, &read_q, wait);	spin_lock(&ipmi_read_lock);	if (data_to_read)		mask |= (POLLIN | POLLRDNORM);	spin_unlock(&ipmi_read_lock);	return mask;}static int ipmi_fasync(int fd, struct file *file, int on){	int result;	result = fasync_helper(fd, file, on, &fasync_q);	return (result);}static int ipmi_close(struct inode *ino, struct file *filep){	if (iminor(ino)==WATCHDOG_MINOR)	{		if (expect_close == 42) {			ipmi_watchdog_state = WDOG_TIMEOUT_NONE;			ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);		} else {			printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");			ipmi_heartbeat();		}		clear_bit(0, &ipmi_wdog_open);	}	ipmi_fasync (-1, filep, 0);	expect_close = 0;	return 0;}static struct file_operations ipmi_wdog_fops = {	.owner   = THIS_MODULE,

⌨️ 快捷键说明

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