diff options
author | Mark Haverkamp <markh@osdl.org> | 2005-10-24 13:52:22 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-10-28 12:41:53 -0400 |
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 e4d543a474ae..ee9067255930 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c | |||
@@ -212,7 +212,7 @@ void fib_init(struct fib *fibptr) | |||
212 | hw_fib->header.StructType = FIB_MAGIC; | 212 | hw_fib->header.StructType = FIB_MAGIC; |
213 | hw_fib->header.Size = cpu_to_le16(fibptr->dev->max_fib_size); | 213 | hw_fib->header.Size = cpu_to_le16(fibptr->dev->max_fib_size); |
214 | hw_fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable); | 214 | hw_fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable); |
215 | hw_fib->header.SenderFibAddress = cpu_to_le32(fibptr->hw_fib_pa); | 215 | hw_fib->header.SenderFibAddress = 0; /* Filled in later if needed */ |
216 | hw_fib->header.ReceiverFibAddress = cpu_to_le32(fibptr->hw_fib_pa); | 216 | hw_fib->header.ReceiverFibAddress = cpu_to_le32(fibptr->hw_fib_pa); |
217 | hw_fib->header.SenderSize = cpu_to_le16(fibptr->dev->max_fib_size); | 217 | hw_fib->header.SenderSize = cpu_to_le16(fibptr->dev->max_fib_size); |
218 | } | 218 | } |
@@ -380,9 +380,7 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f | |||
380 | 380 | ||
381 | int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority, int wait, int reply, fib_callback callback, void * callback_data) | 381 | int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority, int wait, int reply, fib_callback callback, void * callback_data) |
382 | { | 382 | { |
383 | u32 index; | ||
384 | struct aac_dev * dev = fibptr->dev; | 383 | struct aac_dev * dev = fibptr->dev; |
385 | unsigned long nointr = 0; | ||
386 | struct hw_fib * hw_fib = fibptr->hw_fib; | 384 | struct hw_fib * hw_fib = fibptr->hw_fib; |
387 | struct aac_queue * q; | 385 | struct aac_queue * q; |
388 | unsigned long flags = 0; | 386 | unsigned long flags = 0; |
@@ -417,7 +415,7 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority | |||
417 | * Map the fib into 32bits by using the fib number | 415 | * Map the fib into 32bits by using the fib number |
418 | */ | 416 | */ |
419 | 417 | ||
420 | hw_fib->header.SenderFibAddress = cpu_to_le32(((u32)(fibptr-dev->fibs)) << 1); | 418 | hw_fib->header.SenderFibAddress = cpu_to_le32(((u32)(fibptr - dev->fibs)) << 2); |
421 | hw_fib->header.SenderData = (u32)(fibptr - dev->fibs); | 419 | hw_fib->header.SenderData = (u32)(fibptr - dev->fibs); |
422 | /* | 420 | /* |
423 | * Set FIB state to indicate where it came from and if we want a | 421 | * 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 | |||
456 | 454 | ||
457 | FIB_COUNTER_INCREMENT(aac_config.FibsSent); | 455 | FIB_COUNTER_INCREMENT(aac_config.FibsSent); |
458 | 456 | ||
459 | dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index)); | ||
460 | dprintk((KERN_DEBUG "Fib contents:.\n")); | 457 | dprintk((KERN_DEBUG "Fib contents:.\n")); |
461 | dprintk((KERN_DEBUG " Command = %d.\n", hw_fib->header.Command)); | 458 | dprintk((KERN_DEBUG " Command = %d.\n", le32_to_cpu(hw_fib->header.Command))); |
462 | dprintk((KERN_DEBUG " XferState = %x.\n", hw_fib->header.XferState)); | 459 | dprintk((KERN_DEBUG " SubCommand = %d.\n", le32_to_cpu(((struct aac_query_mount *)fib_data(fibptr))->command))); |
460 | dprintk((KERN_DEBUG " XferState = %x.\n", le32_to_cpu(hw_fib->header.XferState))); | ||
463 | dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib)); | 461 | dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib)); |
464 | dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa)); | 462 | dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa)); |
465 | dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); | 463 | 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 | |||
469 | if(wait) | 467 | if(wait) |
470 | spin_lock_irqsave(&fibptr->event_lock, flags); | 468 | spin_lock_irqsave(&fibptr->event_lock, flags); |
471 | spin_lock_irqsave(q->lock, qflags); | 469 | spin_lock_irqsave(q->lock, qflags); |
472 | aac_queue_get( dev, &index, AdapNormCmdQueue, hw_fib, 1, fibptr, &nointr); | 470 | if (dev->new_comm_interface) { |
473 | 471 | unsigned long count = 10000000L; /* 50 seconds */ | |
474 | list_add_tail(&fibptr->queue, &q->pendingq); | 472 | list_add_tail(&fibptr->queue, &q->pendingq); |
475 | q->numpending++; | 473 | q->numpending++; |
476 | *(q->headers.producer) = cpu_to_le32(index + 1); | 474 | spin_unlock_irqrestore(q->lock, qflags); |
477 | spin_unlock_irqrestore(q->lock, qflags); | 475 | while (aac_adapter_send(fibptr) != 0) { |
478 | if (!(nointr & aac_config.irq_mod)) | 476 | if (--count == 0) { |
479 | aac_adapter_notify(dev, AdapNormCmdQueue); | 477 | if (wait) |
478 | spin_unlock_irqrestore(&fibptr->event_lock, flags); | ||
479 | spin_lock_irqsave(q->lock, qflags); | ||
480 | q->numpending--; | ||
481 | list_del(&fibptr->queue); | ||
482 | spin_unlock_irqrestore(q->lock, qflags); | ||
483 | return -ETIMEDOUT; | ||
484 | } | ||
485 | udelay(5); | ||
486 | } | ||
487 | } else { | ||
488 | u32 index; | ||
489 | unsigned long nointr = 0; | ||
490 | aac_queue_get( dev, &index, AdapNormCmdQueue, hw_fib, 1, fibptr, &nointr); | ||
491 | |||
492 | list_add_tail(&fibptr->queue, &q->pendingq); | ||
493 | q->numpending++; | ||
494 | *(q->headers.producer) = cpu_to_le32(index + 1); | ||
495 | spin_unlock_irqrestore(q->lock, qflags); | ||
496 | dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index)); | ||
497 | if (!(nointr & aac_config.irq_mod)) | ||
498 | aac_adapter_notify(dev, AdapNormCmdQueue); | ||
499 | } | ||
500 | |||
480 | /* | 501 | /* |
481 | * If the caller wanted us to wait for response wait now. | 502 | * If the caller wanted us to wait for response wait now. |
482 | */ | 503 | */ |
@@ -492,7 +513,6 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority | |||
492 | * hardware failure has occurred. | 513 | * hardware failure has occurred. |
493 | */ | 514 | */ |
494 | unsigned long count = 36000000L; /* 3 minutes */ | 515 | unsigned long count = 36000000L; /* 3 minutes */ |
495 | unsigned long qflags; | ||
496 | while (down_trylock(&fibptr->event_wait)) { | 516 | while (down_trylock(&fibptr->event_wait)) { |
497 | if (--count == 0) { | 517 | if (--count == 0) { |
498 | spin_lock_irqsave(q->lock, qflags); | 518 | spin_lock_irqsave(q->lock, qflags); |
@@ -621,12 +641,16 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size) | |||
621 | unsigned long qflags; | 641 | unsigned long qflags; |
622 | 642 | ||
623 | if (hw_fib->header.XferState == 0) { | 643 | if (hw_fib->header.XferState == 0) { |
644 | if (dev->new_comm_interface) | ||
645 | kfree (hw_fib); | ||
624 | return 0; | 646 | return 0; |
625 | } | 647 | } |
626 | /* | 648 | /* |
627 | * If we plan to do anything check the structure type first. | 649 | * If we plan to do anything check the structure type first. |
628 | */ | 650 | */ |
629 | if ( hw_fib->header.StructType != FIB_MAGIC ) { | 651 | if ( hw_fib->header.StructType != FIB_MAGIC ) { |
652 | if (dev->new_comm_interface) | ||
653 | kfree (hw_fib); | ||
630 | return -EINVAL; | 654 | return -EINVAL; |
631 | } | 655 | } |
632 | /* | 656 | /* |
@@ -637,21 +661,25 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size) | |||
637 | * send the completed cdb to the adapter. | 661 | * send the completed cdb to the adapter. |
638 | */ | 662 | */ |
639 | if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) { | 663 | if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) { |
640 | u32 index; | 664 | if (dev->new_comm_interface) { |
641 | hw_fib->header.XferState |= cpu_to_le32(HostProcessed); | 665 | kfree (hw_fib); |
642 | if (size) { | 666 | } else { |
643 | size += sizeof(struct aac_fibhdr); | 667 | u32 index; |
644 | if (size > le16_to_cpu(hw_fib->header.SenderSize)) | 668 | hw_fib->header.XferState |= cpu_to_le32(HostProcessed); |
645 | return -EMSGSIZE; | 669 | if (size) { |
646 | hw_fib->header.Size = cpu_to_le16(size); | 670 | size += sizeof(struct aac_fibhdr); |
671 | if (size > le16_to_cpu(hw_fib->header.SenderSize)) | ||
672 | return -EMSGSIZE; | ||
673 | hw_fib->header.Size = cpu_to_le16(size); | ||
674 | } | ||
675 | q = &dev->queues->queue[AdapNormRespQueue]; | ||
676 | spin_lock_irqsave(q->lock, qflags); | ||
677 | aac_queue_get(dev, &index, AdapNormRespQueue, hw_fib, 1, NULL, &nointr); | ||
678 | *(q->headers.producer) = cpu_to_le32(index + 1); | ||
679 | spin_unlock_irqrestore(q->lock, qflags); | ||
680 | if (!(nointr & (int)aac_config.irq_mod)) | ||
681 | aac_adapter_notify(dev, AdapNormRespQueue); | ||
647 | } | 682 | } |
648 | q = &dev->queues->queue[AdapNormRespQueue]; | ||
649 | spin_lock_irqsave(q->lock, qflags); | ||
650 | aac_queue_get(dev, &index, AdapNormRespQueue, hw_fib, 1, NULL, &nointr); | ||
651 | *(q->headers.producer) = cpu_to_le32(index + 1); | ||
652 | spin_unlock_irqrestore(q->lock, qflags); | ||
653 | if (!(nointr & (int)aac_config.irq_mod)) | ||
654 | aac_adapter_notify(dev, AdapNormRespQueue); | ||
655 | } | 683 | } |
656 | else | 684 | else |
657 | { | 685 | { |