up_read(&interfaces_sem);  
int ipmi_register_smi(struct ipmi_smi_handlers *handlers,		      void		       *send_info,		      unsigned char            version_major,		      unsigned char            version_minor,		      unsigned char            slave_addr,		      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;			for (j = 0; j < IPMI_MAX_CHANNELS; j++) {				new_intf->channels[j].address					= IPMI_BMC_SLAVE_ADDR;				new_intf->channels[j].lun = 2;			}			if (slave_addr != 0)				new_intf->channels[0].address = slave_addr;			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;#ifdef CONFIG_PROC_FS			spin_lock_init(&(new_intf->proc_entry_lock));#endif			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));			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;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/393d2cc354d150b8b4bb888a9da7db4c935e12bd/ipmi_msghandler.c/clean/drivers/char/ipmi/ipmi_msghandler.c