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

📄 ipmi_msghandler.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		       intf->sent_local_commands);	out += sprintf(out, "handled_local_responses:     %d\n",		       intf->handled_local_responses);	out += sprintf(out, "unhandled_local_responses:   %d\n",		       intf->unhandled_local_responses);	out += sprintf(out, "sent_ipmb_commands:          %d\n",		       intf->sent_ipmb_commands);	out += sprintf(out, "sent_ipmb_command_errs:      %d\n",		       intf->sent_ipmb_command_errs);	out += sprintf(out, "retransmitted_ipmb_commands: %d\n",		       intf->retransmitted_ipmb_commands);	out += sprintf(out, "timed_out_ipmb_commands:     %d\n",		       intf->timed_out_ipmb_commands);	out += sprintf(out, "timed_out_ipmb_broadcasts:   %d\n",		       intf->timed_out_ipmb_broadcasts);	out += sprintf(out, "sent_ipmb_responses:         %d\n",		       intf->sent_ipmb_responses);	out += sprintf(out, "handled_ipmb_responses:      %d\n",		       intf->handled_ipmb_responses);	out += sprintf(out, "invalid_ipmb_responses:      %d\n",		       intf->invalid_ipmb_responses);	out += sprintf(out, "unhandled_ipmb_responses:    %d\n",		       intf->unhandled_ipmb_responses);	out += sprintf(out, "sent_lan_commands:           %d\n",		       intf->sent_lan_commands);	out += sprintf(out, "sent_lan_command_errs:       %d\n",		       intf->sent_lan_command_errs);	out += sprintf(out, "retransmitted_lan_commands:  %d\n",		       intf->retransmitted_lan_commands);	out += sprintf(out, "timed_out_lan_commands:      %d\n",		       intf->timed_out_lan_commands);	out += sprintf(out, "sent_lan_responses:          %d\n",		       intf->sent_lan_responses);	out += sprintf(out, "handled_lan_responses:       %d\n",		       intf->handled_lan_responses);	out += sprintf(out, "invalid_lan_responses:       %d\n",		       intf->invalid_lan_responses);	out += sprintf(out, "unhandled_lan_responses:     %d\n",		       intf->unhandled_lan_responses);	out += sprintf(out, "handled_commands:            %d\n",		       intf->handled_commands);	out += sprintf(out, "invalid_commands:            %d\n",		       intf->invalid_commands);	out += sprintf(out, "unhandled_commands:          %d\n",		       intf->unhandled_commands);	out += sprintf(out, "invalid_events:              %d\n",		       intf->invalid_events);	out += sprintf(out, "events:                      %d\n",		       intf->events);	return (out - ((char *) page));}int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,			    read_proc_t *read_proc, write_proc_t *write_proc,			    void *data, struct module *owner){	struct proc_dir_entry  *file;	int                    rv = 0;	struct ipmi_proc_entry *entry;	/* Create a list element. */	entry = kmalloc(sizeof(*entry), GFP_KERNEL);	if (!entry)		return -ENOMEM;	entry->name = kmalloc(strlen(name)+1, GFP_KERNEL);	if (!entry->name) {		kfree(entry);		return -ENOMEM;	}	strcpy(entry->name, name);	file = create_proc_entry(name, 0, smi->proc_dir);	if (!file) {		kfree(entry->name);		kfree(entry);		rv = -ENOMEM;	} else {		file->nlink = 1;		file->data = data;		file->read_proc = read_proc;		file->write_proc = write_proc;		file->owner = owner;		/* Stick it on the list. */		entry->next = smi->proc_entries;		smi->proc_entries = entry;	}	return rv;}static int add_proc_entries(ipmi_smi_t smi, int num){	int rv = 0;	sprintf(smi->proc_dir_name, "%d", num);	smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root);	if (!smi->proc_dir)		rv = -ENOMEM;	else {		smi->proc_dir->owner = THIS_MODULE;	}	if (rv == 0)		rv = ipmi_smi_add_proc_entry(smi, "stats",					     stat_file_read_proc, NULL,					     smi, THIS_MODULE);	if (rv == 0)		rv = ipmi_smi_add_proc_entry(smi, "ipmb",					     ipmb_file_read_proc, NULL,					     smi, THIS_MODULE);	if (rv == 0)		rv = ipmi_smi_add_proc_entry(smi, "version",					     version_file_read_proc, NULL,					     smi, THIS_MODULE);	return rv;}static void remove_proc_entries(ipmi_smi_t smi){	struct ipmi_proc_entry *entry;	while (smi->proc_entries) {		entry = smi->proc_entries;		smi->proc_entries = entry->next;		remove_proc_entry(entry->name, smi->proc_dir);		kfree(entry->name);		kfree(entry);	}	remove_proc_entry(smi->proc_dir_name, proc_ipmi_root);}static intsend_channel_info_cmd(ipmi_smi_t intf, int chan){	struct kernel_ipmi_msg            msg;	unsigned char                     data[1];	struct ipmi_system_interface_addr si;	si.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;	si.channel = IPMI_BMC_CHANNEL;	si.lun = 0;	msg.netfn = IPMI_NETFN_APP_REQUEST;	msg.cmd = IPMI_GET_CHANNEL_INFO_CMD;	msg.data = data;	msg.data_len = 1;	data[0] = chan;	return i_ipmi_request(NULL,			      intf,			      (struct ipmi_addr *) &si,			      0,			      &msg,			      NULL,			      NULL,			      NULL,			      0,			      intf->my_address,			      intf->my_lun,			      -1, 0);}static voidchannel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg){	int rv = 0;	int chan;	if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2))	    && (msg->rsp[1] == IPMI_GET_CHANNEL_INFO_CMD))	{		/* It's the one we want */		if (msg->rsp[2] != 0) {			/* Got an error from the channel, just go on. */			if (msg->rsp[2] == IPMI_INVALID_COMMAND_ERR) {				/* If the MC does not support this				   command, that is legal.  We just				   assume it has one IPMB at channel				   zero. */				intf->channels[0].medium					= IPMI_CHANNEL_MEDIUM_IPMB;				intf->channels[0].protocol					= IPMI_CHANNEL_PROTOCOL_IPMB;				rv = -ENOSYS;				intf->curr_channel = IPMI_MAX_CHANNELS;				wake_up(&intf->waitq);				goto out;			}			goto next_channel;		}		if (msg->rsp_size < 6) {			/* Message not big enough, just go on. */			goto next_channel;		}		chan = intf->curr_channel;		intf->channels[chan].medium = msg->rsp[4] & 0x7f;		intf->channels[chan].protocol = msg->rsp[5] & 0x1f;	next_channel:		intf->curr_channel++;		if (intf->curr_channel >= IPMI_MAX_CHANNELS)			wake_up(&intf->waitq);		else			rv = send_channel_info_cmd(intf, intf->curr_channel);		if (rv) {			/* Got an error somehow, just give up. */			intf->curr_channel = IPMI_MAX_CHANNELS;			wake_up(&intf->waitq);			printk(KERN_WARNING PFX			       "Error sending channel information: %d\n",			       rv);		}	} out:	return;}int ipmi_register_smi(struct ipmi_smi_handlers *handlers,		      void		       *send_info,		      unsigned char            version_major,		      unsigned char            version_minor,		      ipmi_smi_t               *intf){	int              i, j;	int              rv;	ipmi_smi_t       new_intf;	unsigned long    flags;	/* 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_intf = kmalloc(sizeof(*new_intf), GFP_KERNEL);	if (!new_intf)		return -ENOMEM;	memset(new_intf, 0, sizeof(*new_intf));	new_intf->proc_dir = NULL;	rv = -ENOMEM;	down_write(&interfaces_sem);	for (i=0; i<MAX_IPMI_INTERFACES; i++) {		if (ipmi_interfaces[i] == NULL) {			new_intf->intf_num = i;			new_intf->version_major = version_major;			new_intf->version_minor = version_minor;			new_intf->my_address = IPMI_BMC_SLAVE_ADDR;			new_intf->my_lun = 2;  /* the SMS LUN. */			rwlock_init(&(new_intf->users_lock));			INIT_LIST_HEAD(&(new_intf->users));			new_intf->handlers = handlers;			new_intf->send_info = send_info;			spin_lock_init(&(new_intf->seq_lock));			for (j=0; j<IPMI_IPMB_NUM_SEQ; j++) {				new_intf->seq_table[j].inuse = 0;				new_intf->seq_table[j].seqid = 0;			}			new_intf->curr_seq = 0;			spin_lock_init(&(new_intf->waiting_msgs_lock));			INIT_LIST_HEAD(&(new_intf->waiting_msgs));			spin_lock_init(&(new_intf->events_lock));			INIT_LIST_HEAD(&(new_intf->waiting_events));			new_intf->waiting_events_count = 0;			rwlock_init(&(new_intf->cmd_rcvr_lock));			init_waitqueue_head(&new_intf->waitq);			INIT_LIST_HEAD(&(new_intf->cmd_rcvrs));			new_intf->all_cmd_rcvr = NULL;			spin_lock_init(&(new_intf->counter_lock));			spin_lock_irqsave(&interfaces_lock, flags);			ipmi_interfaces[i] = new_intf;			spin_unlock_irqrestore(&interfaces_lock, flags);			rv = 0;			*intf = new_intf;			break;		}	}	downgrade_write(&interfaces_sem);	if (rv == 0)		rv = add_proc_entries(*intf, i);	if (rv == 0) {		if ((version_major > 1)		    || ((version_major == 1) && (version_minor >= 5)))		{			/* Start scanning the channels to see what is			   available. */			(*intf)->null_user_handler = channel_handler;			(*intf)->curr_channel = 0;			rv = send_channel_info_cmd(*intf, 0);			if (rv)				goto out;			/* Wait for the channel info to be read. */			up_read(&interfaces_sem);			wait_event((*intf)->waitq,				   ((*intf)->curr_channel>=IPMI_MAX_CHANNELS));			down_read(&interfaces_sem);			if (ipmi_interfaces[i] != new_intf)				/* Well, it went away.  Just return. */				goto out;		} else {			/* Assume a single IPMB channel at zero. */			(*intf)->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB;			(*intf)->channels[0].protocol				= IPMI_CHANNEL_PROTOCOL_IPMB;  		}		/* Call all the watcher interfaces to tell		   them that a new interface is available. */		call_smi_watchers(i);	} out:	up_read(&interfaces_sem);	if (rv) {		if (new_intf->proc_dir)			remove_proc_entries(new_intf);		kfree(new_intf);	}	return rv;}static void free_recv_msg_list(struct list_head *q){	struct ipmi_recv_msg *msg, *msg2;	list_for_each_entry_safe(msg, msg2, q, link) {		list_del(&msg->link);		ipmi_free_recv_msg(msg);	}}static void free_cmd_rcvr_list(struct list_head *q){	struct cmd_rcvr  *rcvr, *rcvr2;	list_for_each_entry_safe(rcvr, rcvr2, q, link) {		list_del(&rcvr->link);		kfree(rcvr);	}}static void clean_up_interface_data(ipmi_smi_t intf){	int i;	free_recv_msg_list(&(intf->waiting_msgs));	free_recv_msg_list(&(intf->waiting_events));	free_cmd_rcvr_list(&(intf->cmd_rcvrs));	for (i=0; i<IPMI_IPMB_NUM_SEQ; i++) {		if ((intf->seq_table[i].inuse)		    && (intf->seq_table[i].recv_msg))		{			ipmi_free_recv_msg(intf->seq_table[i].recv_msg);		}		}}int ipmi_unregister_smi(ipmi_smi_t intf){	int                     rv = -ENODEV;	int                     i;	struct ipmi_smi_watcher *w;	unsigned long           flags;	down_write(&interfaces_sem);	if (list_empty(&(intf->users)))	{		for (i=0; i<MAX_IPMI_INTERFACES; i++) {			if (ipmi_interfaces[i] == intf) {				remove_proc_entries(intf);				spin_lock_irqsave(&interfaces_lock, flags);				ipmi_interfaces[i] = NULL;				clean_up_interface_data(intf);				spin_unlock_irqrestore(&interfaces_lock,flags);				kfree(intf);				rv = 0;				goto out_call_watcher;			}		}	} else {		rv = -EBUSY;	}	up_write(&interfaces_sem);	return rv; out_call_watcher:	downgrade_write(&interfaces_sem);	/* Call all the watcher interfaces to tell them that	   an interface is gone. */	down_read(&smi_watchers_sem);	list_for_each_entry(w, &smi_watchers, link) {		w->smi_gone(i);	}	up_read(&smi_watchers_sem);	up_read(&interfaces_sem);	return 0;}static int handle_ipmb_get_msg_rsp(ipmi_smi_t          intf,				   struct ipmi_smi_msg *msg){	struct ipmi_ipmb_addr ipmb_addr;	struct ipmi_recv_msg  *recv_msg;	unsigned long         flags;		/* This is 11, not 10, because the response must contain a	 * completion code. */	if (msg->rsp_size < 11) {		/* Message not big enough, just ignore it. */		spin_lock_irqsave(&intf->counter_lock, flags);		intf->invalid_ipmb_responses++;		spin_unlock_irqrestore(&intf->counter_lock, flags);		return 0;	}	if (msg->rsp[2] != 0) {		/* An error getting the response, just ignore it. */		return 0;	}	ipmb_addr.addr_type = IPMI_IPMB_ADDR_TYPE;	ipmb_addr.slave_addr = msg->rsp[6];	ipmb_addr.channel = msg->rsp[3] & 0x0f;	ipmb_addr.lun = msg->rsp[7] & 3;	/* It's a response from a remote entity.  Look up the sequence	   number and handle the response. */	if (intf_find_seq(intf,			  msg->rsp[7] >> 2,			  msg->rsp[3] & 0x0f,			  msg->rsp[8],			  (msg->rsp[4] >> 2) & (~1),			  (struct ipmi_addr *) &(ipmb_addr),			  &recv_msg))	{

⌨️ 快捷键说明

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