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

📄 commsup.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 2 页
字号:
		qid = AdapNormCmdQueue;	}	q = &dev->queues->queue[qid];	if(wait)		spin_lock_irqsave(&fibptr->event_lock, flags);	if(aac_queue_get( dev, &index, qid, fib, 1, fibptr, &nointr)<0)		return -EWOULDBLOCK;	dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index));	dprintk((KERN_DEBUG "Fib contents:.\n"));	dprintk((KERN_DEBUG "  Command =               %d.\n", fib->header.Command));	dprintk((KERN_DEBUG "  XferState  =            %x.\n", fib->header.XferState));	/*	 *	Fill in the Callback and CallbackContext if we are not	 *	going to wait.	 */	if (!wait) {		fibptr->callback = callback;		fibptr->callback_data = callback_data;	}	FIB_COUNTER_INCREMENT(aac_config.FibsSent);	list_add_tail(&fibptr->queue, &q->pendingq);	q->numpending++;	fibptr->done = 0;	if(aac_insert_entry(dev, index, qid, (nointr & aac_config.irq_mod)) < 0)		return -EWOULDBLOCK;	/*	 *	If the caller wanted us to wait for response wait now. 	 */    	if (wait) {		spin_unlock_irqrestore(&fibptr->event_lock, flags);		down(&fibptr->event_wait);		if(fibptr->done == 0)			BUG();					if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT))			return -ETIMEDOUT;		else			return 0;	}	/*	 *	If the user does not want a response than return success otherwise	 *	return pending	 */	if (reply)		return -EINPROGRESS;	else		return 0;}/**  *	aac_consumer_get	-	get the top of the queue *	@dev: Adapter *	@q: Queue *	@entry: Return entry * *	Will return a pointer to the entry on the top of the queue requested that * 	we are a consumer of, and return the address of the queue entry. It does *	not change the state of the queue.  */int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry){	u32 index;	int status;	if (*q->headers.producer == *q->headers.consumer) {		status = 0;	} else {		/*		 *	The consumer index must be wrapped if we have reached		 *	the end of the queue, else we just use the entry		 *	pointed to by the header index		 */		if (le32_to_cpu(*q->headers.consumer) >= q->entries) 			index = 0;				else		        index = le32_to_cpu(*q->headers.consumer);		*entry = q->base + index;		status = 1;	}	return(status);}int aac_consumer_avail(struct aac_dev *dev, struct aac_queue * q){	return (*q->headers.producer != *q->headers.consumer);}/** *	aac_consumer_free	-	free consumer entry *	@dev: Adapter *	@q: Queue *	@qid: Queue ident * *	Frees up the current top of the queue we are a consumer of. If the *	queue was full notify the producer that the queue is no longer full. */void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid){	int wasfull = 0;	u32 notify;	if (*q->headers.producer+1 == *q->headers.consumer)		wasfull = 1;        	if (le32_to_cpu(*q->headers.consumer) >= q->entries)		*q->headers.consumer = cpu_to_le32(1);	else		*q->headers.consumer = cpu_to_le32(le32_to_cpu(*q->headers.consumer)+1);        	if (wasfull) {		switch (qid) {		case HostNormCmdQueue:			notify = HostNormCmdNotFull;			break;		case HostHighCmdQueue:			notify = HostHighCmdNotFull;			break;		case HostNormRespQueue:			notify = HostNormRespNotFull;			break;		case HostHighRespQueue:			notify = HostHighRespNotFull;			break;		default:			BUG();			return;		}		aac_adapter_notify(dev, notify);	}}        /** *	fib_adapter_complete	-	complete adapter issued fib *	@fibptr: fib to complete *	@size: size of fib * *	Will do all necessary work to complete a FIB that was sent from *	the adapter. */int fib_adapter_complete(struct fib * fibptr, unsigned short size){	struct hw_fib * fib = fibptr->fib;	struct aac_dev * dev = fibptr->dev;	unsigned long nointr = 0;	if (le32_to_cpu(fib->header.XferState) == 0)        	return 0;	/*	 *	If we plan to do anything check the structure type first.	 */ 	if ( fib->header.StructType != FIB_MAGIC ) {        	return -EINVAL;	}	/*	 *	This block handles the case where the adapter had sent us a	 *	command and we have finished processing the command. We	 *	call completeFib when we are done processing the command 	 *	and want to send a response back to the adapter. This will 	 *	send the completed cdb to the adapter.	 */	if (fib->header.XferState & cpu_to_le32(SentFromAdapter)) {	        fib->header.XferState |= cpu_to_le32(HostProcessed);	        if (fib->header.XferState & cpu_to_le32(HighPriority)) {        		u32 index;       			if (size) 			{				size += sizeof(struct aac_fibhdr);				if (size > le16_to_cpu(fib->header.SenderSize))					return -EMSGSIZE;				fib->header.Size = cpu_to_le16(size);			}			if(aac_queue_get(dev, &index, AdapHighRespQueue, fib, 1, NULL, &nointr) < 0) {				return -EWOULDBLOCK;			}			if (aac_insert_entry(dev, index, AdapHighRespQueue,  (nointr & (int)aac_config.irq_mod)) != 0) {			}		}		else if (fib->header.XferState & NormalPriority) 		{			u32 index;			if (size) {				size += sizeof(struct aac_fibhdr);				if (size > le16_to_cpu(fib->header.SenderSize)) 					return -EMSGSIZE;				fib->header.Size = cpu_to_le16(size);			}			if (aac_queue_get(dev, &index, AdapNormRespQueue, fib, 1, NULL, &nointr) < 0) 				return -EWOULDBLOCK;			if (aac_insert_entry(dev, index, AdapNormRespQueue, 				(nointr & (int)aac_config.irq_mod)) != 0) 			{			}		}	}	else 	{        	printk(KERN_WARNING "fib_complete: Unknown xferstate detected.\n");        	BUG();	}   	return 0;}/** *	fib_complete	-	fib completion handler *	@fib: FIB to complete * *	Will do all necessary work to complete a FIB. */ int fib_complete(struct fib * fibptr){	struct hw_fib * fib = fibptr->fib;	/*	 *	Check for a fib which has already been completed	 */	if (fib->header.XferState == cpu_to_le32(0))        	return 0;	/*	 *	If we plan to do anything check the structure type first.	 */ 	if (fib->header.StructType != FIB_MAGIC)	        return -EINVAL;	/*	 *	This block completes a cdb which orginated on the host and we 	 *	just need to deallocate the cdb or reinit it. At this point the	 *	command is complete that we had sent to the adapter and this	 *	cdb could be reused.	 */	if((fib->header.XferState & cpu_to_le32(SentFromHost)) &&		(fib->header.XferState & cpu_to_le32(AdapterProcessed)))	{		fib_dealloc(fibptr);	}	else if(fib->header.XferState & cpu_to_le32(SentFromHost))	{		/*		 *	This handles the case when the host has aborted the I/O		 *	to the adapter because the adapter is not responding		 */		fib_dealloc(fibptr);	} else if(fib->header.XferState & cpu_to_le32(HostOwned)) {		fib_dealloc(fibptr);	} else {		BUG();	}   	return 0;}/** *	aac_printf	-	handle printf from firmware *	@dev: Adapter *	@val: Message info * *	Print a message passed to us by the controller firmware on the *	Adaptec board */void aac_printf(struct aac_dev *dev, u32 val){	int length = val & 0xffff;	int level = (val >> 16) & 0xffff;	char *cp = dev->printfbuf;		/*	 *	The size of the printfbuf is set in port.c	 *	There is no variable or define for it	 */	if (length > 255)		length = 255;	if (cp[length] != 0)		cp[length] = 0;	if (level == LOG_HIGH_ERROR)		printk(KERN_WARNING "aacraid:%s.\n", cp);	else		printk(KERN_INFO "aacraid:%s.\n", cp);	memset(cp, 0,  256);}/** *	aac_handle_aif		-	Handle a message from the firmware *	@dev: Which adapter this fib is from *	@fibptr: Pointer to fibptr from adapter * *	This routine handles a driver notify fib from the adapter and *	dispatches it to the appropriate routine for handling. */static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr){	struct hw_fib * fib = fibptr->fib;	/*	 * Set the status of this FIB to be Invalid parameter.	 *	 *	*(u32 *)fib->data = ST_INVAL;	 */	*(u32 *)fib->data = cpu_to_le32(ST_OK);	fib_adapter_complete(fibptr, sizeof(u32));}/** *	aac_command_thread	-	command processing thread *	@dev: Adapter to monitor * *	Waits on the commandready event in it's queue. When the event gets set *	it will pull FIBs off it's queue. It will continue to pull FIBs off *	until the queue is empty. When the queue is empty it will wait for *	more FIBs. */ int aac_command_thread(struct aac_dev * dev){	struct hw_fib *fib, *newfib;	struct fib fibptr; /* for error logging */	struct aac_queue_block *queues = dev->queues;	struct aac_fib_context *fibctx;	unsigned long flags;	DECLARE_WAITQUEUE(wait, current);	/*	 *	We can only have one thread per adapter for AIF's.	 */	if (dev->aif_thread)		return -EINVAL;	/*	 *	Set up the name that will appear in 'ps'	 *	stored in  task_struct.comm[16].	 */	sprintf(current->comm, "aacraid");	daemonize();	/*	 *	Let the DPC know it has a place to send the AIF's to.	 */	dev->aif_thread = 1;	memset(&fibptr, 0, sizeof(struct fib));	add_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait);	set_current_state(TASK_INTERRUPTIBLE);	while(1) 	{		spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags);		while(!list_empty(&(queues->queue[HostNormCmdQueue].cmdq))) {			struct list_head *entry;			struct aac_aifcmd * aifcmd;			set_current_state(TASK_RUNNING);					entry = queues->queue[HostNormCmdQueue].cmdq.next;			list_del(entry);						spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags);			fib = list_entry(entry, struct hw_fib, header.FibLinks);			/*			 *	We will process the FIB here or pass it to a 			 *	worker thread that is TBD. We Really can't 			 *	do anything at this point since we don't have			 *	anything defined for this thread to do.			 */			memset(&fibptr, 0, sizeof(struct fib));			fibptr.type = FSAFS_NTC_FIB_CONTEXT;			fibptr.size = sizeof( struct fib );			fibptr.fib = fib;			fibptr.data = fib->data;			fibptr.dev = dev;			/*			 *	We only handle AifRequest fibs from the adapter.			 */			aifcmd = (struct aac_aifcmd *) fib->data;			if (aifcmd->command == le16_to_cpu(AifCmdDriverNotify)) {				aac_handle_aif(dev, &fibptr);			} else {				/* The u32 here is important and intended. We are using				   32bit wrapping time to fit the adapter field */				   				u32 time_now, time_last;				unsigned long flagv;								time_now = jiffies/HZ;				spin_lock_irqsave(&dev->fib_lock, flagv);				entry = dev->fib_list.next;				/*				 * For each Context that is on the 				 * fibctxList, make a copy of the				 * fib, and then set the event to wake up the				 * thread that is waiting for it.				 */				while (entry != &dev->fib_list) {					/*					 * Extract the fibctx					 */					fibctx = list_entry(entry, struct aac_fib_context, next);					/*					 * Check if the queue is getting					 * backlogged					 */					if (fibctx->count > 20)					{						time_last = fibctx->jiffies;						/*						 * Has it been > 2 minutes 						 * since the last read off						 * the queue?						 */						if ((time_now - time_last) > 120) {							entry = entry->next;							aac_close_fib_context(dev, fibctx);							continue;						}					}					/*					 * Warning: no sleep allowed while					 * holding spinlock					 */					newfib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC);					if (newfib) {						/*						 * Make the copy of the FIB						 */						memcpy(newfib, fib, sizeof(struct hw_fib));						/*						 * Put the FIB onto the						 * fibctx's fibs						 */						list_add_tail(&newfib->header.FibLinks, &fibctx->fibs);						fibctx->count++;						/* 						 * Set the event to wake up the						 * thread that will waiting.						 */						up(&fibctx->wait_sem);					} else {						printk(KERN_WARNING "aifd: didn't allocate NewFib.\n");					}					entry = entry->next;				}				/*				 *	Set the status of this FIB				 */				*(u32 *)fib->data = cpu_to_le32(ST_OK);				fib_adapter_complete(&fibptr, sizeof(u32));				spin_unlock_irqrestore(&dev->fib_lock, flagv);			}			spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags);		}		/*		 *	There are no more AIF's		 */		spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags);		schedule();		if(signal_pending(current))			break;		set_current_state(TASK_INTERRUPTIBLE);	}	remove_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait);	dev->aif_thread = 0;	complete_and_exit(&dev->aif_completion, 0);}

⌨️ 快捷键说明

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