int aac_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 "aac_fib_adapter_complete: Unknown xferstate detected.\n"); BUG(); } return 0; }
/** * aac_rx_deliver_producer * @fib: fib to issue * * Will send a fib, returning 0 if successful. */ int aac_rx_deliver_producer(struct fib * fib) { struct aac_dev *dev = fib->dev; struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue]; u32 Index; unsigned long nointr = 0; aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib_va, 1, fib, &nointr); atomic_inc(&q->numpending); *(q->headers.producer) = cpu_to_le32(Index + 1); if (!(nointr & aac_config.irq_mod)) aac_adapter_notify(dev, AdapNormCmdQueue); return 0; }
/** * aac_rx_deliver_producer * @fib: fib to issue * * Will send a fib, returning 0 if successful. */ int aac_rx_deliver_producer(struct fib * fib) { struct aac_dev *dev = fib->dev; struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue]; unsigned long qflags; u32 Index; unsigned long nointr = 0; spin_lock_irqsave(q->lock, qflags); aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib_va, 1, fib, &nointr); q->numpending++; *(q->headers.producer) = cpu_to_le32(Index + 1); spin_unlock_irqrestore(q->lock, qflags); if (!(nointr & aac_config.irq_mod)) aac_adapter_notify(dev, AdapNormCmdQueue); return 0; }
int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *callback_data) { struct aac_dev * dev = fibptr->dev; struct hw_fib * hw_fib = fibptr->hw_fib; struct aac_queue * q; unsigned long flags = 0; unsigned long qflags; if (!(hw_fib->header.XferState & cpu_to_le32(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 Fib is 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)) << 2); 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. */ 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 "aac_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: aac_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; }