diff options
author | Mark Haverkamp <markh@osdl.org> | 2005-10-24 10:52:22 -0700 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-10-28 11:41:53 -0500 |
commit | 8e0c5ebde82b08f6d996e11983890fc4cc085fab (patch) | |
tree | 3ba38ff8e7b9203b47d038c215d9c7d623c250ba /drivers/scsi/aacraid/commsup.c | |
parent | 38a9a621aba953ddb8051547e98c10ec3c741312 (diff) |
[SCSI] aacraid: Newer adapter communication iterface support
Received from Mark Salyzyn.
This patch adds the 'new comm' interface, which modern AAC based
adapters that are less than a year old support in the name of much
improved performance. These modern adapters support both the legacy and
the 'new comm' interfaces.
Signed-off-by: Mark Haverkamp <markh@osdl.org>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/aacraid/commsup.c')
-rw-r--r-- | drivers/scsi/aacraid/commsup.c | 88 |
1 files changed, 58 insertions, 30 deletions
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index e4d543a474a..ee906725593 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -212,7 +212,7 @@ void fib_init(struct fib *fibptr) hw_fib->header.StructType = FIB_MAGIC; hw_fib->header.Size = cpu_to_le16(fibptr->dev->max_fib_size); hw_fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable); - hw_fib->header.SenderFibAddress = cpu_to_le32(fibptr->hw_fib_pa); + hw_fib->header.SenderFibAddress = 0; /* Filled in later if needed */ hw_fib->header.ReceiverFibAddress = cpu_to_le32(fibptr->hw_fib_pa); hw_fib->header.SenderSize = cpu_to_le16(fibptr->dev->max_fib_size); } @@ -380,9 +380,7 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f 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; 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; @@ -417,7 +415,7 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority * 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.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 @@ -456,10 +454,10 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority FIB_COUNTER_INCREMENT(aac_config.FibsSent); - 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 " 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)); @@ -469,14 +467,37 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority if(wait) spin_lock_irqsave(&fibptr->event_lock, flags); spin_lock_irqsave(q->lock, qflags); - 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); - if (!(nointr & aac_config.irq_mod)) - aac_adapter_notify(dev, AdapNormCmdQueue); + 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. */ @@ -492,7 +513,6 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority * hardware failure has occurred. */ unsigned long count = 36000000L; /* 3 minutes */ - unsigned long qflags; while (down_trylock(&fibptr->event_wait)) { if (--count == 0) { spin_lock_irqsave(q->lock, qflags); @@ -621,12 +641,16 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size) 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; } /* @@ -637,21 +661,25 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size) * send the completed cdb to the adapter. */ if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) { - 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); + 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); } - 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 { |