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

📄 ipmi_msghandler.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	smi_msg->data[4] = lan_addr->remote_SWID;	smi_msg->data[5] = (msg->netfn << 2) | (lan_addr->lun & 0x3);	smi_msg->data[6] = ipmb_checksum(&(smi_msg->data[4]), 2);	smi_msg->data[7] = lan_addr->local_SWID;	smi_msg->data[8] = (ipmb_seq << 2) | source_lun;	smi_msg->data[9] = msg->cmd;	/* Now tack on the data to the message. */	if (msg->data_len > 0)		memcpy(&(smi_msg->data[10]), msg->data,		       msg->data_len);	smi_msg->data_size = msg->data_len + 10;	/* Now calculate the checksum and tack it on. */	smi_msg->data[smi_msg->data_size]		= ipmb_checksum(&(smi_msg->data[7]),				smi_msg->data_size-7);	/* Add on the checksum size and the offset from the	   broadcast. */	smi_msg->data_size += 1;	smi_msg->msgid = msgid;}/* Separate from ipmi_request so that the user does not have to be   supplied in certain circumstances (mainly at panic time).  If   messages are supplied, they will be freed, even if an error   occurs. */static inline int i_ipmi_request(ipmi_user_t          user,				 ipmi_smi_t           intf,				 struct ipmi_addr     *addr,				 long                 msgid,				 struct kernel_ipmi_msg *msg,				 void                 *user_msg_data,				 void                 *supplied_smi,				 struct ipmi_recv_msg *supplied_recv,				 int                  priority,				 unsigned char        source_address,				 unsigned char        source_lun,				 int                  retries,				 unsigned int         retry_time_ms){	int                  rv = 0;	struct ipmi_smi_msg  *smi_msg;	struct ipmi_recv_msg *recv_msg;	unsigned long        flags;	if (supplied_recv) {		recv_msg = supplied_recv;	} else {		recv_msg = ipmi_alloc_recv_msg();		if (recv_msg == NULL) {			return -ENOMEM;		}	}	recv_msg->user_msg_data = user_msg_data;	if (supplied_smi) {		smi_msg = (struct ipmi_smi_msg *) supplied_smi;	} else {		smi_msg = ipmi_alloc_smi_msg();		if (smi_msg == NULL) {			ipmi_free_recv_msg(recv_msg);			return -ENOMEM;		}	}	recv_msg->user = user;	recv_msg->msgid = msgid;	/* Store the message to send in the receive message so timeout	   responses can get the proper response data. */	recv_msg->msg = *msg;	if (addr->addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) {		struct ipmi_system_interface_addr *smi_addr;		if (msg->netfn & 1) {			/* Responses are not allowed to the SMI. */			rv = -EINVAL;			goto out_err;		}		smi_addr = (struct ipmi_system_interface_addr *) addr;		if (smi_addr->lun > 3) {			spin_lock_irqsave(&intf->counter_lock, flags);			intf->sent_invalid_commands++;			spin_unlock_irqrestore(&intf->counter_lock, flags);			rv = -EINVAL;			goto out_err;		}		memcpy(&recv_msg->addr, smi_addr, sizeof(*smi_addr));		if ((msg->netfn == IPMI_NETFN_APP_REQUEST)		    && ((msg->cmd == IPMI_SEND_MSG_CMD)			|| (msg->cmd == IPMI_GET_MSG_CMD)			|| (msg->cmd == IPMI_READ_EVENT_MSG_BUFFER_CMD)))		{			/* We don't let the user do these, since we manage			   the sequence numbers. */			spin_lock_irqsave(&intf->counter_lock, flags);			intf->sent_invalid_commands++;			spin_unlock_irqrestore(&intf->counter_lock, flags);			rv = -EINVAL;			goto out_err;		}		if ((msg->data_len + 2) > IPMI_MAX_MSG_LENGTH) {			spin_lock_irqsave(&intf->counter_lock, flags);			intf->sent_invalid_commands++;			spin_unlock_irqrestore(&intf->counter_lock, flags);			rv = -EMSGSIZE;			goto out_err;		}		smi_msg->data[0] = (msg->netfn << 2) | (smi_addr->lun & 0x3);		smi_msg->data[1] = msg->cmd;		smi_msg->msgid = msgid;		smi_msg->user_data = recv_msg;		if (msg->data_len > 0)			memcpy(&(smi_msg->data[2]), msg->data, msg->data_len);		smi_msg->data_size = msg->data_len + 2;		spin_lock_irqsave(&intf->counter_lock, flags);		intf->sent_local_commands++;		spin_unlock_irqrestore(&intf->counter_lock, flags);	} else if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE)		   || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))	{		struct ipmi_ipmb_addr *ipmb_addr;		unsigned char         ipmb_seq;		long                  seqid;		int                   broadcast = 0;		if (addr->channel > IPMI_NUM_CHANNELS) {			spin_lock_irqsave(&intf->counter_lock, flags);			intf->sent_invalid_commands++;			spin_unlock_irqrestore(&intf->counter_lock, flags);			rv = -EINVAL;			goto out_err;		}		if (intf->channels[addr->channel].medium		    != IPMI_CHANNEL_MEDIUM_IPMB)		{			spin_lock_irqsave(&intf->counter_lock, flags);			intf->sent_invalid_commands++;			spin_unlock_irqrestore(&intf->counter_lock, flags);			rv = -EINVAL;			goto out_err;		}		if (retries < 0) {		    if (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)			retries = 0; /* Don't retry broadcasts. */		    else			retries = 4;		}		if (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE) {		    /* Broadcasts add a zero at the beginning of the		       message, but otherwise is the same as an IPMB		       address. */		    addr->addr_type = IPMI_IPMB_ADDR_TYPE;		    broadcast = 1;		}		/* Default to 1 second retries. */		if (retry_time_ms == 0)		    retry_time_ms = 1000;		/* 9 for the header and 1 for the checksum, plus                   possibly one for the broadcast. */		if ((msg->data_len + 10 + broadcast) > IPMI_MAX_MSG_LENGTH) {			spin_lock_irqsave(&intf->counter_lock, flags);			intf->sent_invalid_commands++;			spin_unlock_irqrestore(&intf->counter_lock, flags);			rv = -EMSGSIZE;			goto out_err;		}		ipmb_addr = (struct ipmi_ipmb_addr *) addr;		if (ipmb_addr->lun > 3) {			spin_lock_irqsave(&intf->counter_lock, flags);			intf->sent_invalid_commands++;			spin_unlock_irqrestore(&intf->counter_lock, flags);			rv = -EINVAL;			goto out_err;		}		memcpy(&recv_msg->addr, ipmb_addr, sizeof(*ipmb_addr));		if (recv_msg->msg.netfn & 0x1) {			/* It's a response, so use the user's sequence                           from msgid. */			spin_lock_irqsave(&intf->counter_lock, flags);			intf->sent_ipmb_responses++;			spin_unlock_irqrestore(&intf->counter_lock, flags);			format_ipmb_msg(smi_msg, msg, ipmb_addr, msgid,					msgid, broadcast,					source_address, source_lun);			/* Save the receive message so we can use it			   to deliver the response. */			smi_msg->user_data = recv_msg;		} else {			/* It's a command, so get a sequence for it. */			spin_lock_irqsave(&(intf->seq_lock), flags);			spin_lock(&intf->counter_lock);			intf->sent_ipmb_commands++;			spin_unlock(&intf->counter_lock);			/* Create a sequence number with a 1 second                           timeout and 4 retries. */			rv = intf_next_seq(intf,					   recv_msg,					   retry_time_ms,					   retries,					   broadcast,					   &ipmb_seq,					   &seqid);			if (rv) {				/* We have used up all the sequence numbers,				   probably, so abort. */				spin_unlock_irqrestore(&(intf->seq_lock),						       flags);				goto out_err;			}			/* Store the sequence number in the message,                           so that when the send message response                           comes back we can start the timer. */			format_ipmb_msg(smi_msg, msg, ipmb_addr,					STORE_SEQ_IN_MSGID(ipmb_seq, seqid),					ipmb_seq, broadcast,					source_address, source_lun);			/* Copy the message into the recv message data, so we			   can retransmit it later if necessary. */			memcpy(recv_msg->msg_data, smi_msg->data,			       smi_msg->data_size);			recv_msg->msg.data = recv_msg->msg_data;			recv_msg->msg.data_len = smi_msg->data_size;			/* We don't unlock until here, because we need                           to copy the completed message into the                           recv_msg before we release the lock.                           Otherwise, race conditions may bite us.  I                           know that's pretty paranoid, but I prefer                           to be correct. */			spin_unlock_irqrestore(&(intf->seq_lock), flags);		}	} else if (addr->addr_type == IPMI_LAN_ADDR_TYPE) {		struct ipmi_lan_addr  *lan_addr;		unsigned char         ipmb_seq;		long                  seqid;		if (addr->channel > IPMI_NUM_CHANNELS) {			spin_lock_irqsave(&intf->counter_lock, flags);			intf->sent_invalid_commands++;			spin_unlock_irqrestore(&intf->counter_lock, flags);			rv = -EINVAL;			goto out_err;		}		if ((intf->channels[addr->channel].medium		    != IPMI_CHANNEL_MEDIUM_8023LAN)		    && (intf->channels[addr->channel].medium			!= IPMI_CHANNEL_MEDIUM_ASYNC))		{			spin_lock_irqsave(&intf->counter_lock, flags);			intf->sent_invalid_commands++;			spin_unlock_irqrestore(&intf->counter_lock, flags);			rv = -EINVAL;			goto out_err;		}		retries = 4;		/* Default to 1 second retries. */		if (retry_time_ms == 0)		    retry_time_ms = 1000;		/* 11 for the header and 1 for the checksum. */		if ((msg->data_len + 12) > IPMI_MAX_MSG_LENGTH) {			spin_lock_irqsave(&intf->counter_lock, flags);			intf->sent_invalid_commands++;			spin_unlock_irqrestore(&intf->counter_lock, flags);			rv = -EMSGSIZE;			goto out_err;		}		lan_addr = (struct ipmi_lan_addr *) addr;		if (lan_addr->lun > 3) {			spin_lock_irqsave(&intf->counter_lock, flags);			intf->sent_invalid_commands++;			spin_unlock_irqrestore(&intf->counter_lock, flags);			rv = -EINVAL;			goto out_err;		}		memcpy(&recv_msg->addr, lan_addr, sizeof(*lan_addr));		if (recv_msg->msg.netfn & 0x1) {			/* It's a response, so use the user's sequence                           from msgid. */			spin_lock_irqsave(&intf->counter_lock, flags);			intf->sent_lan_responses++;			spin_unlock_irqrestore(&intf->counter_lock, flags);			format_lan_msg(smi_msg, msg, lan_addr, msgid,				       msgid, source_lun);			/* Save the receive message so we can use it			   to deliver the response. */			smi_msg->user_data = recv_msg;		} else {			/* It's a command, so get a sequence for it. */			spin_lock_irqsave(&(intf->seq_lock), flags);			spin_lock(&intf->counter_lock);			intf->sent_lan_commands++;			spin_unlock(&intf->counter_lock);			/* Create a sequence number with a 1 second                           timeout and 4 retries. */			rv = intf_next_seq(intf,					   recv_msg,					   retry_time_ms,					   retries,					   0,					   &ipmb_seq,					   &seqid);			if (rv) {				/* We have used up all the sequence numbers,				   probably, so abort. */				spin_unlock_irqrestore(&(intf->seq_lock),						       flags);				goto out_err;			}			/* Store the sequence number in the message,                           so that when the send message response                           comes back we can start the timer. */			format_lan_msg(smi_msg, msg, lan_addr,				       STORE_SEQ_IN_MSGID(ipmb_seq, seqid),				       ipmb_seq, source_lun);			/* Copy the message into the recv message data, so we			   can retransmit it later if necessary. */			memcpy(recv_msg->msg_data, smi_msg->data,			       smi_msg->data_size);			recv_msg->msg.data = recv_msg->msg_data;			recv_msg->msg.data_len = smi_msg->data_size;			/* We don't unlock until here, because we need                           to copy the completed message into the                           recv_msg before we release the lock.                           Otherwise, race conditions may bite us.  I                           know that's pretty paranoid, but I prefer                           to be correct. */			spin_unlock_irqrestore(&(intf->seq_lock), flags);		}	} else {	    /* Unknown address type. */		spin_lock_irqsave(&intf->counter_lock, flags);		intf->sent_invalid_commands++;		spin_unlock_irqrestore(&intf->counter_lock, flags);		rv = -EINVAL;		goto out_err;	}#ifdef DEBUG_MSGING	{		int m;		for (m=0; m<smi_msg->data_size; m++)			printk(" %2.2x", smi_msg->data[m]);		printk("\n");	}#endif	intf->handlers->sender(intf->send_info, smi_msg, priority);	return 0; out_err:	ipmi_free_smi_msg(smi_msg);	ipmi_free_recv_msg(recv_msg);	return rv;}int ipmi_request_settime(ipmi_user_t      user,			 struct ipmi_addr *addr,			 long             msgid,			 struct kernel_ipmi_msg  *msg,			 void             *user_msg_data,			 int              priority,			 int              retries,			 unsigned int     retry_time_ms){	return i_ipmi_request(user,			      user->intf,			      addr,			      msgid,			      msg,			      user_msg_data,			      NULL, NULL,			      priority,			      user->intf->my_address,			      user->intf->my_lun,			      retries,			      retry_time_ms);}int ipmi_request_supply_msgs(ipmi_user_t          user,			     struct ipmi_addr     *addr,			     long                 msgid,			     struct kernel_ipmi_msg *msg,			     void                 *user_msg_data,			     void                 *supplied_smi,			     struct ipmi_recv_msg *supplied_recv,			     int                  priority){	return i_ipmi_request(user,			      user->intf,			      addr,			      msgid,			      msg,			      user_msg_data,			      supplied_smi,			      supplied_recv,			      priority,			      user->intf->my_address,			      user->intf->my_lun,			      -1, 0);}static int ipmb_file_read_proc(char *page, char **start, off_t off,			       int count, int *eof, void *data){	char       *out = (char *) page;	ipmi_smi_t intf = data;	return sprintf(out, "%x\n", intf->my_address);}static int version_file_read_proc(char *page, char **start, off_t off,				  int count, int *eof, void *data){	char       *out = (char *) page;	ipmi_smi_t intf = data;	return sprintf(out, "%d.%d\n",		       intf->version_major, intf->version_minor);}static int stat_file_read_proc(char *page, char **start, off_t off,			       int count, int *eof, void *data){	char       *out = (char *) page;	ipmi_smi_t intf = data;	out += sprintf(out, "sent_invalid_commands:       %d\n",		       intf->sent_invalid_commands);	out += sprintf(out, "sent_local_commands:         %d\n",

⌨️ 快捷键说明

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