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

📄 i2o_core.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	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)				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 allready 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. * */int i2o_release_device(struct i2o_device *d, struct i2o_handler *h){	int err = 0;	down(&i2o_configuration_lock);	if (d->owner != h) {		printk(KERN_INFO "Claim release called, but not owned by %s!",		       h->name);		up(&i2o_configuration_lock);		return -ENOENT;	}		d->owner = NULL;	if(i2o_issue_claim(I2O_CMD_UTIL_RELEASE, d->controller, d->lct_data.tid, 			   I2O_CLAIM_PRIMARY))	{		err = -ENXIO;		d->owner = h;	}	up(&i2o_configuration_lock);	return err;}/* * 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;}/* * 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;}/* * Event registration API */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));}/* * Event ack API * * 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;	int flags;	lock_kernel();	daemonize();	unlock_kernel();	strcpy(current->comm, "i2oevtd");	evt_running = 1;	while(1)	{		down_interruptible(&evt_sem);		if(signal_pending(current))		{			dprintk(KERN_INFO "I2O event thread dead\n");			evt_running = 0;			return 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;				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;				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);			continue;		}		/*		 * Loop through all the devices on the IOP looking for their		 * LCT data in the LCT.  We assume that TIDs are not repeated.		 * as that is the only way to really tell.  It's been confirmed		 * by the IRTOS vendor(s?) that TIDs are not reused until they 		 * wrap arround(4096), and I doubt a system will up long enough		 * to create/delete that many devices.		 */		for(d = c->devices; d; )		{			found = 0;			d1 = d->next;						for(i = 0; i < entries; i++) 			{ 				if(d->lct_data.tid == c->dlct->lct_entry[i].tid) 				{ 					found = 1; 					break; 				} 			} 			if(!found) 			{				dprintk(KERN_INFO "i2o_core: Deleted device!\n"); 				spin_lock(&i2o_dev_lock);				i2o_delete_device(d); 				spin_unlock(&i2o_dev_lock);			} 			d = d1; 		}		/* 		 * Tell LCT to renotify us next time there is a change	 	 */		i2o_lct_notify(c);		/*		 * Copy new LCT into public LCT		 *		 * Possible race if someone is reading LCT while  we are copying 		 * over it. If this happens, we'll fix it then. but I doubt that		 * the LCT will get updated often enough or will get read by		 * a user often enough to worry.		 */		if(c->lct->table_size < c->dlct->table_size)		{			tmp = c->lct;			c->lct = kmalloc(c->dlct->table_size<<2, GFP_KERNEL);			if(!c->lct)			{				printk(KERN_ERR "%s: No memory for LCT!\n", c->name);				c->lct = tmp;				continue;			}			kfree(tmp);		}		memcpy(c->lct, c->dlct, c->dlct->table_size<<2);

⌨️ 快捷键说明

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