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

📄 i2o_core.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	/*	 * Clear event registration as this can cause weird behavior	 */	if(c->status_block->iop_state == ADAPTER_STATE_OPERATIONAL)		i2o_event_register(c, core_context, 0, 0, 0);	down(&i2o_configuration_lock);	if((users=atomic_read(&c->users)))	{		dprintk(KERN_INFO "I2O: %d users for controller %s\n", users,			c->name);		up(&i2o_configuration_lock);		return -EBUSY;	}	while(c->devices)	{		if(__i2o_delete_device(c->devices)<0)		{			/* Shouldnt happen */			c->bus_disable(c);			up(&i2o_configuration_lock);			return -EBUSY;		}	}	/*	 * If this is shutdown time, the thread's already been killed	 */	if(c->lct_running) {		stat = kill_proc(c->lct_pid, SIGTERM, 1);		if(!stat) {			int count = 10 * 100;			while(c->lct_running && --count) {				current->state = TASK_INTERRUPTIBLE;				schedule_timeout(1);			}					if(!count)				printk(KERN_ERR 					"%s: LCT thread still running!\n", 					c->name);		}	}	p=&i2o_controller_chain;	while(*p)	{		if(*p==c)		{ 			/* Ask the IOP to switch to RESET state */			i2o_reset_controller(c);			/* Release IRQ */			c->destructor(c);			*p=c->next;			up(&i2o_configuration_lock);			if(c->page_frame)			{				pci_unmap_single(c->pdev, c->page_frame_map, MSG_POOL_SIZE, PCI_DMA_FROMDEVICE);				kfree(c->page_frame);			}			if(c->hrt)				kfree(c->hrt);			if(c->lct)				kfree(c->lct);			if(c->status_block)				kfree(c->status_block);			if(c->dlct)				kfree(c->dlct);			i2o_controllers[c->unit]=NULL;			memcpy(name, c->name, strlen(c->name)+1);			kfree(c);			dprintk(KERN_INFO "%s: Deleted from controller chain.\n", name);						i2o_num_controllers--;			return 0;		}		p=&((*p)->next);	}	up(&i2o_configuration_lock);	printk(KERN_ERR "i2o_delete_controller: bad pointer!\n");	return -ENOENT;}/** *	i2o_unlock_controller	-	unlock a controller *	@c: controller to unlock * *	Take a lock on an i2o controller. This prevents it being deleted. *	i2o controllers are not refcounted so a deletion of an in use device *	will fail, not take affect on the last dereference. */ void i2o_unlock_controller(struct i2o_controller *c){	atomic_dec(&c->users);}/** *	i2o_find_controller - return a locked controller *	@n: controller number * *	Returns a pointer to the controller object. The controller is locked *	on return. NULL is returned if the controller is not found. */ struct i2o_controller *i2o_find_controller(int n){	struct i2o_controller *c;		if(n<0 || n>=MAX_I2O_CONTROLLERS)		return NULL;		down(&i2o_configuration_lock);	c=i2o_controllers[n];	if(c!=NULL)		atomic_inc(&c->users);	up(&i2o_configuration_lock);	return c;}/** *	i2o_issue_claim	- claim or release a device *	@cmd: command *	@c: controller to claim for *	@tid: i2o task id *	@type: type of claim * *	Issue I2O UTIL_CLAIM and UTIL_RELEASE messages. The message to be sent *	is set by cmd. The tid is the task id of the object to claim and the *	type is the claim type (see the i2o standard) * *	Zero is returned on success. */ static int i2o_issue_claim(u32 cmd, struct i2o_controller *c, int tid, u32 type){	u32 msg[5];	msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;	msg[1] = cmd << 24 | HOST_TID<<12 | tid;	msg[3] = 0;	msg[4] = type;		return i2o_post_wait(c, msg, sizeof(msg), 60);}/* * 	i2o_claim_device - claim a device for use by an OSM *	@d: device to claim *	@h: handler for this device * *	Do the leg work to assign a device to a given OSM on Linux. The *	kernel updates the internal handler data for the device and then *	performs an I2O claim for the device, attempting to claim the *	device as primary. If the attempt fails a negative errno code *	is returned. On success zero is returned. */ int i2o_claim_device(struct i2o_device *d, struct i2o_handler *h){	down(&i2o_configuration_lock);	if (d->owner) {		printk(KERN_INFO "Device claim called, but dev already owned by %s!",		       h->name);		up(&i2o_configuration_lock);		return -EBUSY;	}	d->owner=h;	if(i2o_issue_claim(I2O_CMD_UTIL_CLAIM ,d->controller,d->lct_data.tid, 			   I2O_CLAIM_PRIMARY))	{		d->owner = NULL;		return -EBUSY;	}	up(&i2o_configuration_lock);	return 0;}/** *	i2o_release_device - release a device that the OSM is using *	@d: device to claim *	@h: handler for this device * *	Drop a claim by an OSM on a given I2O device. The handler is cleared *	and 0 is returned on success. * *	AC - some devices seem to want to refuse an unclaim until they have *	finished internal processing. It makes sense since you don't want a *	new device to go reconfiguring the entire system until you are done. *	Thus we are prepared to wait briefly. */int i2o_release_device(struct i2o_device *d, struct i2o_handler *h){	int err = 0;	int tries;	down(&i2o_configuration_lock);	if (d->owner != h) {		printk(KERN_INFO "Claim release called, but not owned by %s!\n",		       h->name);		up(&i2o_configuration_lock);		return -ENOENT;	}		for(tries=0;tries<10;tries++)	{		d->owner = NULL;		/*		 *	If the controller takes a nonblocking approach to		 *	releases we have to sleep/poll for a few times.		 */		 		if((err=i2o_issue_claim(I2O_CMD_UTIL_RELEASE, d->controller, d->lct_data.tid, I2O_CLAIM_PRIMARY)) )		{			err = -ENXIO;			current->state = TASK_UNINTERRUPTIBLE;			schedule_timeout(HZ);		}		else		{			err=0;			break;		}	}	up(&i2o_configuration_lock);	return err;}/** * 	i2o_device_notify_on	-	Enable deletion notifiers *	@d: device for notification *	@h: handler to install * *	Called by OSMs to let the core know that they want to be *	notified if the given device is deleted from the system. */int i2o_device_notify_on(struct i2o_device *d, struct i2o_handler *h){	int i;	if(d->num_managers == I2O_MAX_MANAGERS)		return -ENOSPC;	for(i = 0; i < I2O_MAX_MANAGERS; i++)	{		if(!d->managers[i])		{			d->managers[i] = h;			break;		}	}		d->num_managers++;		return 0;}/** * 	i2o_device_notify_off	-	Remove deletion notifiers *	@d: device for notification *	@h: handler to remove * * Called by OSMs to let the core know that they no longer * are interested in the fate of the given device. */int i2o_device_notify_off(struct i2o_device *d, struct i2o_handler *h){	int i;	for(i=0; i < I2O_MAX_MANAGERS; i++)	{		if(d->managers[i] == h)		{			d->managers[i] = NULL;			d->num_managers--;			return 0;		}	}	return -ENOENT;}/** *	i2o_event_register	-	register interest in an event * 	@c: Controller to register interest with *	@tid: I2O task id *	@init_context: initiator context to use with this notifier *	@tr_context: transaction context to use with this notifier *	@evt_mask: mask of events * *	Create and posts an event registration message to the task. No reply *	is waited for, or expected. Errors in posting will be reported. */ int i2o_event_register(struct i2o_controller *c, u32 tid, 		u32 init_context, u32 tr_context, u32 evt_mask){	u32 msg[5];	// Not performance critical, so we just 			// i2o_post_this it instead of building it			// in IOP memory		msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;	msg[1] = I2O_CMD_UTIL_EVT_REGISTER<<24 | HOST_TID<<12 | tid;	msg[2] = init_context;	msg[3] = tr_context;	msg[4] = evt_mask;	return i2o_post_this(c, msg, sizeof(msg));}/* * 	i2o_event_ack	-	acknowledge an event *	@c: controller  *	@msg: pointer to the UTIL_EVENT_REGISTER reply we received * *	We just take a pointer to the original UTIL_EVENT_REGISTER reply *	message and change the function code since that's what spec *	describes an EventAck message looking like. */ int i2o_event_ack(struct i2o_controller *c, u32 *msg){	struct i2o_message *m = (struct i2o_message *)msg;	m->function = I2O_CMD_UTIL_EVT_ACK;	return i2o_post_wait(c, msg, m->size * 4, 2);}/* * Core event handler.  Runs as a separate thread and is woken * up whenever there is an Executive class event. */static int i2o_core_evt(void *reply_data){	struct reply_info *reply = (struct reply_info *) reply_data;	u32 *msg = reply->msg;	struct i2o_controller *c = NULL;	unsigned long flags;	lock_kernel();	daemonize();	unlock_kernel();	strcpy(current->comm, "i2oevtd");	evt_running = 1;	while(1)	{		if(down_interruptible(&evt_sem))		{			dprintk(KERN_INFO "I2O event thread dead\n");			printk("exiting...");			evt_running = 0;			complete_and_exit(&evt_dead, 0);		}		/* 		 * Copy the data out of the queue so that we don't have to lock		 * around the whole function and just around the qlen update		 */		spin_lock_irqsave(&i2o_evt_lock, flags);		memcpy(reply, &events[evt_out], sizeof(struct reply_info));		MODINC(evt_out, I2O_EVT_Q_LEN);		evt_q_len--;		spin_unlock_irqrestore(&i2o_evt_lock, flags);			c = reply->iop;	 	dprintk(KERN_INFO "I2O IRTOS EVENT: iop%d, event %#10x\n", c->unit, msg[4]);		/* 		 * We do not attempt to delete/quiesce/etc. the controller if		 * some sort of error indidication occurs.  We may want to do		 * so in the future, but for now we just let the user deal with 		 * it.  One reason for this is that what to do with an error		 * or when to send what 鎟ror is not really agreed on, so		 * we get errors that may not be fatal but just look like they		 * are...so let the user deal with it.		 */		switch(msg[4])		{			case I2O_EVT_IND_EXEC_RESOURCE_LIMITS:				printk(KERN_ERR "%s: Out of resources\n", c->name);				break;			case I2O_EVT_IND_EXEC_POWER_FAIL:				printk(KERN_ERR "%s: Power failure\n", c->name);				break;			case I2O_EVT_IND_EXEC_HW_FAIL:			{				char *fail[] = 					{ 						"Unknown Error",						"Power Lost",						"Code Violation",						"Parity Error",						"Code Execution Exception",						"Watchdog Timer Expired" 					};				if(msg[5] <= 6)					printk(KERN_ERR "%s: Hardware Failure: %s\n", 						c->name, fail[msg[5]]);				else					printk(KERN_ERR "%s: Unknown Hardware Failure\n", c->name);				break;			}			/*		 	 * New device created		 	 * - Create a new i2o_device entry		 	 * - Inform all interested drivers about this device's existence		 	 */			case I2O_EVT_IND_EXEC_NEW_LCT_ENTRY:			{				struct i2o_device *d = (struct i2o_device *)					kmalloc(sizeof(struct i2o_device), GFP_KERNEL);				int i;				if (d == NULL) {					printk(KERN_EMERG "i2oevtd: out of memory\n");					break;				}				memcpy(&d->lct_data, &msg[5], sizeof(i2o_lct_entry));					d->next = NULL;				d->controller = c;				d->flags = 0;					i2o_report_controller_unit(c, d);				i2o_install_device(c,d);					for(i = 0; i < MAX_I2O_MODULES; i++)				{					if(i2o_handlers[i] && 						i2o_handlers[i]->new_dev_notify &&						(i2o_handlers[i]->class&d->lct_data.class_id))						{						spin_lock(&i2o_dev_lock);						i2o_handlers[i]->new_dev_notify(c,d);						spin_unlock(&i2o_dev_lock);						}				}							break;			}				/* 		 	 * LCT entry for a device has been modified, so update it		 	 * internally.		 	 */			case I2O_EVT_IND_EXEC_MODIFIED_LCT:			{				struct i2o_device *d;				i2o_lct_entry *new_lct = (i2o_lct_entry *)&msg[5];				for(d = c->devices; d; d = d->next)				{					if(d->lct_data.tid == new_lct->tid)					{						memcpy(&d->lct_data, new_lct, sizeof(i2o_lct_entry));						break;					}				}				break;			}				case I2O_EVT_IND_CONFIGURATION_FLAG:				printk(KERN_WARNING "%s requires user configuration\n", c->name);				break;				case I2O_EVT_IND_GENERAL_WARNING:				printk(KERN_WARNING "%s: Warning notification received!"					"Check configuration for errors!\n", c->name);				break;							case I2O_EVT_IND_EVT_MASK_MODIFIED:				/* Well I guess that was us hey .. */				break;								default:				printk(KERN_WARNING "%s: No handler for event (0x%08x)\n", c->name, msg[4]);				break;		}	}	return 0;}/* * Dynamic LCT update.  This compares the LCT with the currently * installed devices to check for device deletions..this needed b/c there * is no DELETED_LCT_ENTRY EventIndicator for the Executive class so * we can't just have the event handler do this...annoying * * This is a hole in the spec that will hopefully be fixed someday. */static int i2o_dyn_lct(void *foo){	struct i2o_controller *c = (struct i2o_controller *)foo;	struct i2o_device *d = NULL;	struct i2o_device *d1 = NULL;	int i = 0;	int found = 0;	int entries;	void *tmp;	char name[16];	lock_kernel();	daemonize();	unlock_kernel();	sprintf(name, "iop%d_lctd", c->unit);	strcpy(current->comm, name);			c->lct_running = 1;	while(1)	{		down_interruptible(&c->lct_sem);		if(signal_pending(current))		{			dprintk(KERN_ERR "%s: LCT thread dead\n", c->name);			c->lct_running = 0;			return 0;		}		entries = c->dlct->table_size;		entries -= 3;		entries /= 9;		dprintk(KERN_INFO "%s: Dynamic LCT Update\n",c->name);		dprintk(KERN_INFO "%s: Dynamic LCT contains %d entries\n", c->name, entries);		if(!entries)		{			printk(KERN_INFO "%s: Empty LCT???\n", c->name);

⌨️ 快捷键说明

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