📄 commsup.c
字号:
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. */ hw_fib->header.XferState |= cpu_to_le32(NormalPriority); /* * Fill in the Callback and CallbackContext if we are not * going to wait. */ if (!wait) { fibptr->callback = callback; fibptr->callback_data = callback_data; } fibptr->done = 0; fibptr->flags = 0; FIB_COUNTER_INCREMENT(aac_config.FibsSent); dprintk((KERN_DEBUG "Fib contents:.\n")); dprintk((KERN_DEBUG " Command = %d.\n", le32_to_cpu(hw_fib->header.Command))); dprintk((KERN_DEBUG " SubCommand = %d.\n", le32_to_cpu(((struct aac_query_mount *)fib_data(fibptr))->command))); dprintk((KERN_DEBUG " XferState = %x.\n", le32_to_cpu(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)); q = &dev->queues->queue[AdapNormCmdQueue]; if(wait) spin_lock_irqsave(&fibptr->event_lock, flags); spin_lock_irqsave(q->lock, qflags); if (dev->new_comm_interface) { unsigned long count = 10000000L; /* 50 seconds */ list_add_tail(&fibptr->queue, &q->pendingq); q->numpending++; spin_unlock_irqrestore(q->lock, qflags); while (aac_adapter_send(fibptr) != 0) { if (--count == 0) { if (wait) spin_unlock_irqrestore(&fibptr->event_lock, flags); spin_lock_irqsave(q->lock, qflags); q->numpending--; list_del(&fibptr->queue); spin_unlock_irqrestore(q->lock, qflags); return -ETIMEDOUT; } udelay(5); } } else { u32 index; unsigned long nointr = 0; aac_queue_get( dev, &index, AdapNormCmdQueue, hw_fib, 1, fibptr, &nointr); list_add_tail(&fibptr->queue, &q->pendingq); q->numpending++; *(q->headers.producer) = cpu_to_le32(index + 1); spin_unlock_irqrestore(q->lock, qflags); dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index)); if (!(nointr & aac_config.irq_mod)) aac_adapter_notify(dev, AdapNormCmdQueue); } /* * If the caller wanted us to wait for response wait now. */ if (wait) { spin_unlock_irqrestore(&fibptr->event_lock, flags); /* Only set for first known interruptable command */ if (wait < 0) { /* * *VERY* Dangerous to time out a command, the * assumption is made that we have no hope of * functioning because an interrupt routing or other * hardware failure has occurred. */ unsigned long count = 36000000L; /* 3 minutes */ while (down_trylock(&fibptr->event_wait)) { if (--count == 0) { spin_lock_irqsave(q->lock, qflags); q->numpending--; list_del(&fibptr->queue); spin_unlock_irqrestore(q->lock, qflags); if (wait == -1) { printk(KERN_ERR "aacraid: fib_send: first asynchronous command timed out.\n" "Usually a result of a PCI interrupt routing problem;\n" "update mother board BIOS or consider utilizing one of\n" "the SAFE mode kernel options (acpi, apic etc)\n"); } return -ETIMEDOUT; } udelay(5); } } else 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);}/** * 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 HostNormRespQueue: notify = HostNormRespNotFull; 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; struct aac_queue * q; unsigned long nointr = 0; unsigned long qflags; if (hw_fib->header.XferState == 0) { if (dev->new_comm_interface) kfree (hw_fib); return 0; } /* * If we plan to do anything check the structure type first. */ if ( hw_fib->header.StructType != FIB_MAGIC ) { if (dev->new_comm_interface) kfree (hw_fib); 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)) { if (dev->new_comm_interface) { kfree (hw_fib); } else { u32 index; hw_fib->header.XferState |= cpu_to_le32(HostProcessed); 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); } q = &dev->queues->queue[AdapNormRespQueue]; spin_lock_irqsave(q->lock, qflags); aac_queue_get(dev, &index, AdapNormRespQueue, hw_fib, 1, NULL, &nointr); *(q->headers.producer) = cpu_to_le32(index + 1); spin_unlock_irqrestore(q->lock, qflags); if (!(nointr & (int)aac_config.irq_mod)) aac_adapter_notify(dev, AdapNormRespQueue); } } 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 == 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){ char *cp = dev->printfbuf; if (dev->printf_enabled) { int length = val & 0xffff; int level = (val >> 16) & 0xffff; /* * 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_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 * hw_fib = fibptr->hw_fib; struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data; int busy; u32 container; struct scsi_device *device; enum { NOTHING, DELETE, ADD, CHANGE } device_config_needed; /* Sniff for container changes */ if (!dev) return; container = (u32)-1; /* * We have set this up to try and minimize the number of * re-configures that take place. As a result of this when * certain AIF's come in we will set a flag waiting for another * type of AIF before setting the re-config flag. */ switch (le32_to_cpu(aifcmd->command)) { case AifCmdDriverNotify: switch (le32_to_cpu(((u32 *)aifcmd->data)[0])) { /* * Morph or Expand complete */ case AifDenMorphComplete: case AifDenVolumeExtendComplete: container = le32_to_cpu(((u32 *)aifcmd->data)[1]); if (container >= dev->maximum_num_containers) break; /* * Find the scsi_device associated with the SCSI * address. Make sure we have the right array, and if * so set the flag to initiate a new re-config once we * see an AifEnConfigChange AIF come through. */ if ((dev != NULL) && (dev->scsi_host_ptr != NULL)) { device = scsi_device_lookup(dev->scsi_host_ptr, CONTAINER_TO_CHANNEL(container), CONTAINER_TO_ID(container), CONTAINER_TO_LUN(container)); if (device) { dev->fsa_dev[container].config_needed = CHANGE; dev->fsa_dev[container].config_waiting_on = AifEnConfigChange; scsi_device_put(device); } } } /* * If we are waiting on something and this happens to be * that thing then set the re-configure flag. */ if (container != (u32)-1) { if (container >= dev->maximum_num_containers) break; if (dev->fsa_dev[container].config_waiting_on == le32_to_cpu(*(u32 *)aifcmd->data)) dev->fsa_dev[container].config_waiting_on = 0; } else for (container = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -