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

📄 ipmi_msghandler.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	int          rv = 0;	unsigned int i;	for (i=intf->curr_seq;	     (i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq;	     i=(i+1)%IPMI_IPMB_NUM_SEQ)	{		if (! intf->seq_table[i].inuse)			break;	}	if (! intf->seq_table[i].inuse) {		intf->seq_table[i].recv_msg = recv_msg;		/* Start with the maximum timeout, when the send response		   comes in we will start the real timer. */		intf->seq_table[i].timeout = MAX_MSG_TIMEOUT;		intf->seq_table[i].orig_timeout = timeout;		intf->seq_table[i].retries_left = retries;		intf->seq_table[i].broadcast = broadcast;		intf->seq_table[i].inuse = 1;		intf->seq_table[i].seqid = NEXT_SEQID(intf->seq_table[i].seqid);		*seq = i;		*seqid = intf->seq_table[i].seqid;		intf->curr_seq = (i+1)%IPMI_IPMB_NUM_SEQ;	} else {		rv = -EAGAIN;	}		return rv;}/* Return the receive message for the given sequence number and   release the sequence number so it can be reused.  Some other data   is passed in to be sure the message matches up correctly (to help   guard against message coming in after their timeout and the   sequence number being reused). */static int intf_find_seq(ipmi_smi_t           intf,			 unsigned char        seq,			 short                channel,			 unsigned char        cmd,			 unsigned char        netfn,			 struct ipmi_addr     *addr,			 struct ipmi_recv_msg **recv_msg){	int           rv = -ENODEV;	unsigned long flags;	if (seq >= IPMI_IPMB_NUM_SEQ)		return -EINVAL;	spin_lock_irqsave(&(intf->seq_lock), flags);	if (intf->seq_table[seq].inuse) {		struct ipmi_recv_msg *msg = intf->seq_table[seq].recv_msg;		if ((msg->addr.channel == channel)		    && (msg->msg.cmd == cmd)		    && (msg->msg.netfn == netfn)		    && (ipmi_addr_equal(addr, &(msg->addr))))		{			*recv_msg = msg;			intf->seq_table[seq].inuse = 0;			rv = 0;		}	}	spin_unlock_irqrestore(&(intf->seq_lock), flags);	return rv;}/* Start the timer for a specific sequence table entry. */static int intf_start_seq_timer(ipmi_smi_t intf,				long       msgid){	int           rv = -ENODEV;	unsigned long flags;	unsigned char seq;	unsigned long seqid;	GET_SEQ_FROM_MSGID(msgid, seq, seqid);	spin_lock_irqsave(&(intf->seq_lock), flags);	/* We do this verification because the user can be deleted           while a message is outstanding. */	if ((intf->seq_table[seq].inuse)	    && (intf->seq_table[seq].seqid == seqid))	{		struct seq_table *ent = &(intf->seq_table[seq]);		ent->timeout = ent->orig_timeout;		rv = 0;	}	spin_unlock_irqrestore(&(intf->seq_lock), flags);	return rv;}/* Got an error for the send message for a specific sequence number. */static int intf_err_seq(ipmi_smi_t   intf,			long         msgid,			unsigned int err){	int                  rv = -ENODEV;	unsigned long        flags;	unsigned char        seq;	unsigned long        seqid;	struct ipmi_recv_msg *msg = NULL;	GET_SEQ_FROM_MSGID(msgid, seq, seqid);	spin_lock_irqsave(&(intf->seq_lock), flags);	/* We do this verification because the user can be deleted           while a message is outstanding. */	if ((intf->seq_table[seq].inuse)	    && (intf->seq_table[seq].seqid == seqid))	{		struct seq_table *ent = &(intf->seq_table[seq]);		ent->inuse = 0;		msg = ent->recv_msg;		rv = 0;	}	spin_unlock_irqrestore(&(intf->seq_lock), flags);	if (msg) {		msg->recv_type = IPMI_RESPONSE_RECV_TYPE;		msg->msg_data[0] = err;		msg->msg.netfn |= 1; /* Convert to a response. */		msg->msg.data_len = 1;		msg->msg.data = msg->msg_data;		deliver_response(msg);	}	return rv;}int ipmi_create_user(unsigned int          if_num,		     struct ipmi_user_hndl *handler,		     void                  *handler_data,		     ipmi_user_t           *user){	unsigned long flags;	ipmi_user_t   new_user;	int           rv = 0;	/* There is no module usecount here, because it's not           required.  Since this can only be used by and called from           other modules, they will implicitly use this module, and           thus this can't be removed unless the other modules are           removed. */	if (handler == NULL)		return -EINVAL;	/* Make sure the driver is actually initialized, this handles	   problems with initialization order. */	if (!initialized) {		rv = ipmi_init_msghandler();		if (rv)			return rv;		/* The init code doesn't return an error if it was turned		   off, but it won't initialize.  Check that. */		if (!initialized)			return -ENODEV;	}	new_user = kmalloc(sizeof(*new_user), GFP_KERNEL);	if (! new_user)		return -ENOMEM;	down_read(&interfaces_sem);	if ((if_num > MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL)	{		rv = -EINVAL;		goto out_unlock;	}	new_user->handler = handler;	new_user->handler_data = handler_data;	new_user->intf = ipmi_interfaces[if_num];	new_user->gets_events = 0;	if (!try_module_get(new_user->intf->handlers->owner)) {		rv = -ENODEV;		goto out_unlock;	}	write_lock_irqsave(&new_user->intf->users_lock, flags);	list_add_tail(&new_user->link, &new_user->intf->users);	write_unlock_irqrestore(&new_user->intf->users_lock, flags); out_unlock:		if (rv) {		kfree(new_user);	} else {		*user = new_user;	}	up_read(&interfaces_sem);	return rv;}static int ipmi_destroy_user_nolock(ipmi_user_t user){	int              rv = -ENODEV;	ipmi_user_t      t_user;	struct cmd_rcvr  *rcvr, *rcvr2;	int              i;	unsigned long    flags;	/* Find the user and delete them from the list. */	list_for_each_entry(t_user, &(user->intf->users), link) {		if (t_user == user) {			list_del(&t_user->link);			rv = 0;			break;		}	}	if (rv) {		goto out_unlock;	}	/* Remove the user from the interfaces sequence table. */	spin_lock_irqsave(&(user->intf->seq_lock), flags);	for (i=0; i<IPMI_IPMB_NUM_SEQ; i++) {		if (user->intf->seq_table[i].inuse		    && (user->intf->seq_table[i].recv_msg->user == user))		{			user->intf->seq_table[i].inuse = 0;		}	}	spin_unlock_irqrestore(&(user->intf->seq_lock), flags);	/* Remove the user from the command receiver's table. */	write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags);	list_for_each_entry_safe(rcvr, rcvr2, &(user->intf->cmd_rcvrs), link) {		if (rcvr->user == user) {			list_del(&rcvr->link);			kfree(rcvr);		}	}	write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags);	kfree(user); out_unlock:	return rv;}int ipmi_destroy_user(ipmi_user_t user){	int           rv;	ipmi_smi_t    intf = user->intf;	unsigned long flags;	down_read(&interfaces_sem);	write_lock_irqsave(&intf->users_lock, flags);	rv = ipmi_destroy_user_nolock(user);	if (!rv)		module_put(intf->handlers->owner);			write_unlock_irqrestore(&intf->users_lock, flags);	up_read(&interfaces_sem);	return rv;}void ipmi_get_version(ipmi_user_t   user,		      unsigned char *major,		      unsigned char *minor){	*major = user->intf->version_major;	*minor = user->intf->version_minor;}void ipmi_set_my_address(ipmi_user_t   user,			 unsigned char address){	user->intf->my_address = address;}unsigned char ipmi_get_my_address(ipmi_user_t user){	return user->intf->my_address;}void ipmi_set_my_LUN(ipmi_user_t   user,		     unsigned char LUN){	user->intf->my_lun = LUN & 0x3;}unsigned char ipmi_get_my_LUN(ipmi_user_t user){	return user->intf->my_lun;}int ipmi_set_gets_events(ipmi_user_t user, int val){	unsigned long         flags;	struct ipmi_recv_msg  *msg, *msg2;	read_lock(&(user->intf->users_lock));	spin_lock_irqsave(&(user->intf->events_lock), flags);	user->gets_events = val;	if (val) {		/* Deliver any queued events. */		list_for_each_entry_safe(msg, msg2, &(user->intf->waiting_events), link) {			list_del(&msg->link);			msg->user = user;			deliver_response(msg);		}	}		spin_unlock_irqrestore(&(user->intf->events_lock), flags);	read_unlock(&(user->intf->users_lock));	return 0;}int ipmi_register_for_cmd(ipmi_user_t   user,			  unsigned char netfn,			  unsigned char cmd){	struct cmd_rcvr  *cmp;	unsigned long    flags;	struct cmd_rcvr  *rcvr;	int              rv = 0;	rcvr = kmalloc(sizeof(*rcvr), GFP_KERNEL);	if (! rcvr)		return -ENOMEM;	read_lock(&(user->intf->users_lock));	write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags);	if (user->intf->all_cmd_rcvr != NULL) {		rv = -EBUSY;		goto out_unlock;	}	/* Make sure the command/netfn is not already registered. */	list_for_each_entry(cmp, &(user->intf->cmd_rcvrs), link) {		if ((cmp->netfn == netfn) && (cmp->cmd == cmd)) {			rv = -EBUSY;			break;		}	}	if (! rv) {		rcvr->cmd = cmd;		rcvr->netfn = netfn;		rcvr->user = user;		list_add_tail(&(rcvr->link), &(user->intf->cmd_rcvrs));	} out_unlock:	write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags);	read_unlock(&(user->intf->users_lock));	if (rv)		kfree(rcvr);	return rv;}int ipmi_unregister_for_cmd(ipmi_user_t   user,			    unsigned char netfn,			    unsigned char cmd){	unsigned long    flags;	struct cmd_rcvr  *rcvr;	int              rv = -ENOENT;	read_lock(&(user->intf->users_lock));	write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags);	/* Make sure the command/netfn is not already registered. */	list_for_each_entry(rcvr, &(user->intf->cmd_rcvrs), link) {		if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {			rv = 0;			list_del(&rcvr->link);			kfree(rcvr);			break;		}	}	write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags);	read_unlock(&(user->intf->users_lock));	return rv;}void ipmi_user_set_run_to_completion(ipmi_user_t user, int val){	user->intf->handlers->set_run_to_completion(user->intf->send_info,						    val);}static unsigned charipmb_checksum(unsigned char *data, int size){	unsigned char csum = 0;		for (; size > 0; size--, data++)		csum += *data;	return -csum;}static inline void format_ipmb_msg(struct ipmi_smi_msg   *smi_msg,				   struct kernel_ipmi_msg *msg,				   struct ipmi_ipmb_addr *ipmb_addr,				   long                  msgid,				   unsigned char         ipmb_seq,				   int                   broadcast,				   unsigned char         source_address,				   unsigned char         source_lun){	int i = broadcast;	/* Format the IPMB header data. */	smi_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);	smi_msg->data[1] = IPMI_SEND_MSG_CMD;	smi_msg->data[2] = ipmb_addr->channel;	if (broadcast)		smi_msg->data[3] = 0;	smi_msg->data[i+3] = ipmb_addr->slave_addr;	smi_msg->data[i+4] = (msg->netfn << 2) | (ipmb_addr->lun & 0x3);	smi_msg->data[i+5] = ipmb_checksum(&(smi_msg->data[i+3]), 2);	smi_msg->data[i+6] = source_address;	smi_msg->data[i+7] = (ipmb_seq << 2) | source_lun;	smi_msg->data[i+8] = msg->cmd;	/* Now tack on the data to the message. */	if (msg->data_len > 0)		memcpy(&(smi_msg->data[i+9]), msg->data,		       msg->data_len);	smi_msg->data_size = msg->data_len + 9;	/* Now calculate the checksum and tack it on. */	smi_msg->data[i+smi_msg->data_size]		= ipmb_checksum(&(smi_msg->data[i+6]),				smi_msg->data_size-6);	/* Add on the checksum size and the offset from the	   broadcast. */	smi_msg->data_size += 1 + i;	smi_msg->msgid = msgid;}static inline void format_lan_msg(struct ipmi_smi_msg   *smi_msg,				  struct kernel_ipmi_msg *msg,				  struct ipmi_lan_addr  *lan_addr,				  long                  msgid,				  unsigned char         ipmb_seq,				  unsigned char         source_lun){	/* Format the IPMB header data. */	smi_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);	smi_msg->data[1] = IPMI_SEND_MSG_CMD;	smi_msg->data[2] = lan_addr->channel;	smi_msg->data[3] = lan_addr->session_handle;

⌨️ 快捷键说明

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