📄 commsup.c
字号:
* success. */ static int aac_insert_entry(struct aac_dev * dev, u32 index, u32 qid, unsigned long nonotify) { struct aac_queue * q = &dev->queues->queue[qid]; if(q == NULL) BUG(); *(q->headers.producer) = cpu_to_le32(index + 1); spin_unlock_irqrestore(q->lock, q->SavedIrql); if (qid == AdapHighCmdQueue || qid == AdapNormCmdQueue || qid == AdapHighRespQueue || qid == AdapNormRespQueue) { if (!nonotify) aac_adapter_notify(dev, qid); } else printk("Suprise insert!\n"); return 0;}/* * Define the highest level of host to adapter communication routines. * These routines will support host to adapter FS commuication. These * routines have no knowledge of the commuication method used. This level * sends and receives FIBs. This level has no knowledge of how these FIBs * get passed back and forth. *//** * fib_send - send a fib to the adapter * @command: Command to send * @fibptr: The fib * @size: Size of fib data area * @priority: Priority of Fib * @wait: Async/sync select * @reply: True if a reply is wanted * @callback: Called with reply * @callback_data: Passed to callback * * Sends the requested FIB to the adapter and optionally will wait for a * response FIB. If the caller does not wish to wait for a response than * an event to wait on must be supplied. This event will be set when a * response FIB is received from the adapter. */ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority, int wait, int reply, fib_callback callback, void * callback_data){ u32 index; u32 qid; struct aac_dev * dev = fibptr->dev; unsigned long nointr = 0; struct hw_fib * hw_fib = fibptr->hw_fib; struct aac_queue * q; unsigned long flags = 0; if (!(le32_to_cpu(hw_fib->header.XferState) & HostOwned)) return -EBUSY; /* * There are 5 cases with the wait and reponse requested flags. * The only invalid cases are if the caller requests to wait and * does not request a response and if the caller does not want a * response and the Fibis not allocated from pool. If a response * is not requesed the Fib will just be deallocaed by the DPC * routine when the response comes back from the adapter. No * further processing will be done besides deleting the Fib. We * will have a debug mode where the adapter can notify the host * it had a problem and the host can log that fact. */ if (wait && !reply) { return -EINVAL; } else if (!wait && reply) { hw_fib->header.XferState |= cpu_to_le32(Async | ResponseExpected); FIB_COUNTER_INCREMENT(aac_config.AsyncSent); } else if (!wait && !reply) { hw_fib->header.XferState |= cpu_to_le32(NoResponseExpected); FIB_COUNTER_INCREMENT(aac_config.NoResponseSent); } else if (wait && reply) { hw_fib->header.XferState |= cpu_to_le32(ResponseExpected); FIB_COUNTER_INCREMENT(aac_config.NormalSent); } /* * Map the fib into 32bits by using the fib number */ hw_fib->header.SenderFibAddress = cpu_to_le32(((u32)(fibptr - dev->fibs)) << 1); hw_fib->header.SenderData = (u32)(fibptr - dev->fibs); /* * Set FIB state to indicate where it came from and if we want a * response from the adapter. Also load the command from the * caller. * * Map the hw fib pointer as a 32bit value */ hw_fib->header.Command = cpu_to_le16(command); hw_fib->header.XferState |= cpu_to_le32(SentFromHost); fibptr->hw_fib->header.Flags = 0; /* 0 the flags field - internal only*/ /* * Set the size of the Fib we want to send to the adapter */ hw_fib->header.Size = cpu_to_le16(sizeof(struct aac_fibhdr) + size); if (le16_to_cpu(hw_fib->header.Size) > le16_to_cpu(hw_fib->header.SenderSize)) { return -EMSGSIZE; } /* * Get a queue entry connect the FIB to it and send an notify * the adapter a command is ready. */ if (priority == FsaHigh) { hw_fib->header.XferState |= cpu_to_le32(HighPriority); qid = AdapHighCmdQueue; } else { hw_fib->header.XferState |= cpu_to_le32(NormalPriority); qid = AdapNormCmdQueue; } q = &dev->queues->queue[qid]; if(wait) spin_lock_irqsave(&fibptr->event_lock, flags); if(aac_queue_get( dev, &index, qid, hw_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", hw_fib->header.Command)); dprintk((KERN_DEBUG " XferState = %x.\n", hw_fib->header.XferState)); dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib)); dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa)); dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); /* * 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; fibptr->flags = 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 (le32_to_cpu(*q->headers.producer) == le32_to_cpu(*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 (le32_to_cpu(*q->headers.producer) != le32_to_cpu(*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 ((le32_to_cpu(*q->headers.producer)+1) == le32_to_cpu(*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 * hw_fib = fibptr->hw_fib; struct aac_dev * dev = fibptr->dev; unsigned long nointr = 0; if (le32_to_cpu(hw_fib->header.XferState) == 0) return 0; /* * If we plan to do anything check the structure type first. */ if ( hw_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 (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) { hw_fib->header.XferState |= cpu_to_le32(HostProcessed); if (hw_fib->header.XferState & cpu_to_le32(HighPriority)) { u32 index; if (size) { size += sizeof(struct aac_fibhdr); if (size > le16_to_cpu(hw_fib->header.SenderSize)) return -EMSGSIZE; hw_fib->header.Size = cpu_to_le16(size); } if(aac_queue_get(dev, &index, AdapHighRespQueue, hw_fib, 1, NULL, &nointr) < 0) { return -EWOULDBLOCK; } if (aac_insert_entry(dev, index, AdapHighRespQueue, (nointr & (int)aac_config.irq_mod)) != 0) { } } else if (hw_fib->header.XferState & NormalPriority) { u32 index; if (size) { size += sizeof(struct aac_fibhdr); if (size > le16_to_cpu(hw_fib->header.SenderSize)) return -EMSGSIZE; hw_fib->header.Size = cpu_to_le16(size); } if (aac_queue_get(dev, &index, AdapNormRespQueue, hw_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_adapter_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 * hw_fib = fibptr->hw_fib; /* * Check for a fib which has already been completed */ if (hw_fib->header.XferState == cpu_to_le32(0)) return 0; /* * If we plan to do anything check the structure type first. */ if (hw_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((hw_fib->header.XferState & cpu_to_le32(SentFromHost)) && (hw_fib->header.XferState & cpu_to_le32(AdapterProcessed))) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -