📄 commsup.c
字号:
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))) { fib_dealloc(fibptr); } else if(hw_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(hw_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_AAC_HIGH_ERROR) printk(KERN_WARNING "aacraid:%s", cp); else printk(KERN_INFO "aacraid:%s", cp); memset(cp, 0, 256);}/** * 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 *hw_fib, *hw_newfib; struct fib *fib, *newfib; 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]. */ daemonize("aacraid"); allow_signal(SIGKILL); /* * Let the DPC know it has a place to send the AIF's to. */ dev->aif_thread = 1; 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 fib, fiblink); /* * 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. */ hw_fib = fib->hw_fib; memset(fib, 0, sizeof(struct fib)); fib->type = FSAFS_NTC_FIB_CONTEXT; fib->size = sizeof( struct fib ); fib->hw_fib = hw_fib; fib->data = hw_fib->data; fib->dev = dev; /* * We only handle AifRequest fibs from the adapter. */ aifcmd = (struct aac_aifcmd *) hw_fib->data; if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) { /* Handle Driver Notify Events */ *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); fib_adapter_complete(fib, sizeof(u32)); } else { struct list_head *entry; /* 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) { /* * It's *not* jiffies folks, * but jiffies / HZ so do not * panic ... */ 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 */ hw_newfib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC); newfib = kmalloc(sizeof(struct fib), GFP_ATOMIC); if (newfib && hw_newfib) { /* * Make the copy of the FIB */ memcpy(hw_newfib, hw_fib, sizeof(struct hw_fib)); memcpy(newfib, fib, sizeof(struct fib)); newfib->hw_fib = hw_newfib; /* * Put the FIB onto the * fibctx's fibs */ list_add_tail(&newfib->fiblink, &fibctx->fib_list); 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"); if(newfib) kfree(newfib); if(hw_newfib) kfree(hw_newfib); } entry = entry->next; } /* * Set the status of this FIB */ *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); fib_adapter_complete(fib, sizeof(u32)); spin_unlock_irqrestore(&dev->fib_lock, flagv); } spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags); kfree(fib); } /* * 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 + -