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

📄 ipmi_msghandler.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
}int ipmi_validate_addr(struct ipmi_addr *addr, int len){	if (len < sizeof(struct ipmi_system_interface_addr)) {		return -EINVAL;	}	if (addr->addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) {		if (addr->channel != IPMI_BMC_CHANNEL)			return -EINVAL;		return 0;	}	if ((addr->channel == IPMI_BMC_CHANNEL)	    || (addr->channel >= IPMI_NUM_CHANNELS)	    || (addr->channel < 0))		return -EINVAL;	if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE)	    || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))	{		if (len < sizeof(struct ipmi_ipmb_addr)) {			return -EINVAL;		}		return 0;	}	if (addr->addr_type == IPMI_LAN_ADDR_TYPE) {		if (len < sizeof(struct ipmi_lan_addr)) {			return -EINVAL;		}		return 0;	}	return -EINVAL;}unsigned int ipmi_addr_length(int addr_type){	if (addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)		return sizeof(struct ipmi_system_interface_addr);	if ((addr_type == IPMI_IPMB_ADDR_TYPE)	    || (addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))	{		return sizeof(struct ipmi_ipmb_addr);	}	if (addr_type == IPMI_LAN_ADDR_TYPE)		return sizeof(struct ipmi_lan_addr);	return 0;}static void deliver_response(struct ipmi_recv_msg *msg){	if (! msg->user) {		ipmi_smi_t    intf = msg->user_msg_data;		unsigned long flags;		/* Special handling for NULL users. */		if (intf->null_user_handler) {			intf->null_user_handler(intf, msg);			spin_lock_irqsave(&intf->counter_lock, flags);			intf->handled_local_responses++;			spin_unlock_irqrestore(&intf->counter_lock, flags);		} else {			/* No handler, so give up. */			spin_lock_irqsave(&intf->counter_lock, flags);			intf->unhandled_local_responses++;			spin_unlock_irqrestore(&intf->counter_lock, flags);		}		ipmi_free_recv_msg(msg);	} else {		ipmi_user_t user = msg->user;		user->handler->ipmi_recv_hndl(msg, user->handler_data);	}}/* Find the next sequence number not being used and add the given   message with the given timeout to the sequence table.  This must be   called with the interface's seq_lock held. */static int intf_next_seq(ipmi_smi_t           intf,			 struct ipmi_recv_msg *recv_msg,			 unsigned long        timeout,			 int                  retries,			 int                  broadcast,			 unsigned char        *seq,			 long                 *seqid){	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;	ipmi_smi_t    intf;	/* 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;	spin_lock_irqsave(&interfaces_lock, flags);	intf = ipmi_interfaces[if_num];	if ((if_num >= MAX_IPMI_INTERFACES) || IPMI_INVALID_INTERFACE(intf)) {		spin_unlock_irqrestore(&interfaces_lock, flags);		return -EINVAL;	}	/* Note that each existing user holds a refcount to the interface. */	kref_get(&intf->refcount);	spin_unlock_irqrestore(&interfaces_lock, flags);	kref_init(&new_user->refcount);	new_user->handler = handler;	new_user->handler_data = handler_data;	new_user->intf = intf;	new_user->gets_events = 0;	if (!try_module_get(intf->handlers->owner)) {		rv = -ENODEV;		goto out_err;	}	if (intf->handlers->inc_usecount) {		rv = intf->handlers->inc_usecount(intf->send_info);		if (rv) {			module_put(intf->handlers->owner);			goto out_err;		}	}	new_user->valid = 1;	spin_lock_irqsave(&intf->seq_lock, flags);	list_add_rcu(&new_user->link, &intf->users);	spin_unlock_irqrestore(&intf->seq_lock, flags);	*user = new_user;	return 0; out_err:	kfree(new_user);	kref_put(&intf->refcount, intf_free);	return rv;}static void free_user(struct kref *ref){	ipmi_user_t user = container_of(ref, struct ipmi_user, refcount);	kfree(user);}int ipmi_destroy_user(ipmi_user_t user){	int              rv = -ENODEV;	ipmi_smi_t       intf = user->intf;	int              i;	unsigned long    flags;	struct cmd_rcvr  *rcvr;	struct list_head *entry1, *entry2;	struct cmd_rcvr  *rcvrs = NULL;	user->valid = 1;	/* Remove the user from the interface's sequence table. */	spin_lock_irqsave(&intf->seq_lock, flags);	list_del_rcu(&user->link);	for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) {		if (intf->seq_table[i].inuse		    && (intf->seq_table[i].recv_msg->user == user))		{			intf->seq_table[i].inuse = 0;		}	}	spin_unlock_irqrestore(&intf->seq_lock, flags);	/*	 * Remove the user from the command receiver's table.  First	 * we build a list of everything (not using the standard link,	 * since other things may be using it till we do	 * synchronize_rcu()) then free everything in that list.	 */	down(&intf->cmd_rcvrs_lock);	list_for_each_safe_rcu(entry1, entry2, &intf->cmd_rcvrs) {		rcvr = list_entry(entry1, struct cmd_rcvr, link);		if (rcvr->user == user) {			list_del_rcu(&rcvr->link);			rcvr->next = rcvrs;			rcvrs = rcvr;		}	}	up(&intf->cmd_rcvrs_lock);	synchronize_rcu();	while (rcvrs) {		rcvr = rcvrs;		rcvrs = rcvr->next;		kfree(rcvr);	}	module_put(intf->handlers->owner);	if (intf->handlers->dec_usecount)		intf->handlers->dec_usecount(intf->send_info);	kref_put(&intf->refcount, intf_free);	kref_put(&user->refcount, free_user);	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;}int ipmi_set_my_address(ipmi_user_t   user,			unsigned int  channel,			unsigned char address){	if (channel >= IPMI_MAX_CHANNELS)		return -EINVAL;	user->intf->channels[channel].address = address;	return 0;}int ipmi_get_my_address(ipmi_user_t   user,			unsigned int  channel,			unsigned char *address){	if (channel >= IPMI_MAX_CHANNELS)		return -EINVAL;	*address = user->intf->channels[channel].address;	return 0;}int ipmi_set_my_LUN(ipmi_user_t   user,		    unsigned int  channel,		    unsigned char LUN){	if (channel >= IPMI_MAX_CHANNELS)		return -EINVAL;	user->intf->channels[channel].lun = LUN & 0x3;	return 0;}int ipmi_get_my_LUN(ipmi_user_t   user,		    unsigned int  channel,		    unsigned char *address){	if (channel >= IPMI_MAX_CHANNELS)		return -EINVAL;	*address = user->intf->channels[channel].lun;	return 0;}int ipmi_set_gets_events(ipmi_user_t user, int val){	unsigned long        flags;	ipmi_smi_t           intf = user->intf;	struct ipmi_recv_msg *msg, *msg2;	struct list_head     msgs;	INIT_LIST_HEAD(&msgs);	spin_lock_irqsave(&intf->events_lock, flags);	user->gets_events = val;	if (val) {		/* Deliver any queued events. */		list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link) {			list_del(&msg->link);			list_add_tail(&msg->link, &msgs);		}	}	/* Hold the events lock while doing this to preserve order. */	list_for_each_entry_safe(msg, msg2, &msgs, link) {		msg->user = user;		kref_get(&user->refcount);		deliver_response(msg);	}	spin_unlock_irqrestore(&intf->events_lock, flags);	return 0;}static struct cmd_rcvr *find_cmd_rcvr(ipmi_smi_t    intf,				      unsigned char netfn,				      unsigned char cmd){	struct cmd_rcvr *rcvr;	list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) {		if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd))			return rcvr;	}	return NULL;}

⌨️ 快捷键说明

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