diff options
author | Mahesh Rajashekhara <Mahesh_Rajashekhara@pmc-sierra.com> | 2012-07-14 08:48:51 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-07-20 03:59:04 -0400 |
commit | 85d22bbf6787c240921539bba224eb221bfb8ee1 (patch) | |
tree | 364d004282e48cd45d83232e00fddc3cdbec057c /drivers/scsi/aacraid/src.c | |
parent | fa7250d6945d0f693bef6545682beb7f671f1694 (diff) |
[SCSI] aacraid: Series 7 Async. (performance) mode support
- Series 7 Async. (performance) mode support added
- New scatter/gather list format for Series 7
- Driver converts s/g list to a firmware suitable list for best performance on
Series 7, this can be disabled with driver parameter "aac_convert_sgl" for
testing purposes
- New container read/write command structure for Series 7
- Fast response support for the SCSI pass-through path added
- Async. status response buffer changes
Signed-off-by: Mahesh Rajashekhara <Mahesh_Rajashekhara@pmc-sierra.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/aacraid/src.c')
-rw-r--r-- | drivers/scsi/aacraid/src.c | 85 |
1 files changed, 47 insertions, 38 deletions
diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c index 0fb1f5507cd8..3b021ec63255 100644 --- a/drivers/scsi/aacraid/src.c +++ b/drivers/scsi/aacraid/src.c | |||
@@ -56,21 +56,10 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id) | |||
56 | if (bellbits & PmDoorBellResponseSent) { | 56 | if (bellbits & PmDoorBellResponseSent) { |
57 | bellbits = PmDoorBellResponseSent; | 57 | bellbits = PmDoorBellResponseSent; |
58 | /* handle async. status */ | 58 | /* handle async. status */ |
59 | src_writel(dev, MUnit.ODR_C, bellbits); | ||
60 | src_readl(dev, MUnit.ODR_C); | ||
59 | our_interrupt = 1; | 61 | our_interrupt = 1; |
60 | index = dev->host_rrq_idx; | 62 | index = dev->host_rrq_idx; |
61 | if (dev->host_rrq[index] == 0) { | ||
62 | u32 old_index = index; | ||
63 | /* adjust index */ | ||
64 | do { | ||
65 | index++; | ||
66 | if (index == dev->scsi_host_ptr->can_queue + | ||
67 | AAC_NUM_MGT_FIB) | ||
68 | index = 0; | ||
69 | if (dev->host_rrq[index] != 0) | ||
70 | break; | ||
71 | } while (index != old_index); | ||
72 | dev->host_rrq_idx = index; | ||
73 | } | ||
74 | for (;;) { | 63 | for (;;) { |
75 | isFastResponse = 0; | 64 | isFastResponse = 0; |
76 | /* remove toggle bit (31) */ | 65 | /* remove toggle bit (31) */ |
@@ -93,6 +82,8 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id) | |||
93 | } else { | 82 | } else { |
94 | bellbits_shifted = (bellbits >> SRC_ODR_SHIFT); | 83 | bellbits_shifted = (bellbits >> SRC_ODR_SHIFT); |
95 | if (bellbits_shifted & DoorBellAifPending) { | 84 | if (bellbits_shifted & DoorBellAifPending) { |
85 | src_writel(dev, MUnit.ODR_C, bellbits); | ||
86 | src_readl(dev, MUnit.ODR_C); | ||
96 | our_interrupt = 1; | 87 | our_interrupt = 1; |
97 | /* handle AIF */ | 88 | /* handle AIF */ |
98 | aac_intr_normal(dev, 0, 2, 0, NULL); | 89 | aac_intr_normal(dev, 0, 2, 0, NULL); |
@@ -100,6 +91,13 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id) | |||
100 | unsigned long sflags; | 91 | unsigned long sflags; |
101 | struct list_head *entry; | 92 | struct list_head *entry; |
102 | int send_it = 0; | 93 | int send_it = 0; |
94 | extern int aac_sync_mode; | ||
95 | |||
96 | if (!aac_sync_mode) { | ||
97 | src_writel(dev, MUnit.ODR_C, bellbits); | ||
98 | src_readl(dev, MUnit.ODR_C); | ||
99 | our_interrupt = 1; | ||
100 | } | ||
103 | 101 | ||
104 | if (dev->sync_fib) { | 102 | if (dev->sync_fib) { |
105 | our_interrupt = 1; | 103 | our_interrupt = 1; |
@@ -132,7 +130,6 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id) | |||
132 | } | 130 | } |
133 | 131 | ||
134 | if (our_interrupt) { | 132 | if (our_interrupt) { |
135 | src_writel(dev, MUnit.ODR_C, bellbits); | ||
136 | return IRQ_HANDLED; | 133 | return IRQ_HANDLED; |
137 | } | 134 | } |
138 | return IRQ_NONE; | 135 | return IRQ_NONE; |
@@ -336,6 +333,9 @@ static void aac_src_start_adapter(struct aac_dev *dev) | |||
336 | { | 333 | { |
337 | struct aac_init *init; | 334 | struct aac_init *init; |
338 | 335 | ||
336 | /* reset host_rrq_idx first */ | ||
337 | dev->host_rrq_idx = 0; | ||
338 | |||
339 | init = dev->init; | 339 | init = dev->init; |
340 | init->HostElapsedSeconds = cpu_to_le32(get_seconds()); | 340 | init->HostElapsedSeconds = cpu_to_le32(get_seconds()); |
341 | 341 | ||
@@ -397,31 +397,40 @@ static int aac_src_deliver_message(struct fib *fib) | |||
397 | q->numpending++; | 397 | q->numpending++; |
398 | spin_unlock_irqrestore(q->lock, qflags); | 398 | spin_unlock_irqrestore(q->lock, qflags); |
399 | 399 | ||
400 | /* Calculate the amount to the fibsize bits */ | 400 | if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) { |
401 | fibsize = (sizeof(struct aac_fib_xporthdr) + hdr_size + 127) / 128 - 1; | 401 | /* Calculate the amount to the fibsize bits */ |
402 | if (fibsize > (ALIGN32 - 1)) | 402 | fibsize = (hdr_size + 127) / 128 - 1; |
403 | return -EMSGSIZE; | 403 | if (fibsize > (ALIGN32 - 1)) |
404 | return -EMSGSIZE; | ||
405 | /* New FIB header, 32-bit */ | ||
406 | address = fib->hw_fib_pa; | ||
407 | fib->hw_fib_va->header.StructType = FIB_MAGIC2; | ||
408 | fib->hw_fib_va->header.SenderFibAddress = (u32)address; | ||
409 | fib->hw_fib_va->header.u.TimeStamp = 0; | ||
410 | BUG_ON((u32)(address >> 32) != 0L); | ||
411 | address |= fibsize; | ||
412 | } else { | ||
413 | /* Calculate the amount to the fibsize bits */ | ||
414 | fibsize = (sizeof(struct aac_fib_xporthdr) + hdr_size + 127) / 128 - 1; | ||
415 | if (fibsize > (ALIGN32 - 1)) | ||
416 | return -EMSGSIZE; | ||
417 | |||
418 | /* Fill XPORT header */ | ||
419 | pFibX = (void *)fib->hw_fib_va - sizeof(struct aac_fib_xporthdr); | ||
420 | pFibX->Handle = cpu_to_le32(fib->hw_fib_va->header.Handle); | ||
421 | pFibX->HostAddress = cpu_to_le64(fib->hw_fib_pa); | ||
422 | pFibX->Size = cpu_to_le32(hdr_size); | ||
404 | 423 | ||
405 | /* Fill XPORT header */ | 424 | /* |
406 | pFibX = (void *)fib->hw_fib_va - sizeof(struct aac_fib_xporthdr); | 425 | * The xport header has been 32-byte aligned for us so that fibsize |
407 | /* | 426 | * can be masked out of this address by hardware. -- BenC |
408 | * This was stored by aac_fib_send() and it is the index into | 427 | */ |
409 | * dev->fibs. Not sure why we add 1 to it, but I suspect that it's | 428 | address = fib->hw_fib_pa - sizeof(struct aac_fib_xporthdr); |
410 | * because it can't be zero when we pass it to the hardware. Note that | 429 | if (address & (ALIGN32 - 1)) |
411 | * it was stored in native endian, hence the lack of swapping. -- BenC | 430 | return -EINVAL; |
412 | */ | 431 | address |= fibsize; |
413 | pFibX->Handle = cpu_to_le32(fib->hw_fib_va->header.SenderData + 1); | 432 | } |
414 | pFibX->HostAddress = cpu_to_le64(fib->hw_fib_pa); | ||
415 | pFibX->Size = cpu_to_le32(hdr_size); | ||
416 | 433 | ||
417 | /* | ||
418 | * The xport header has been 32-byte aligned for us so that fibsize | ||
419 | * can be masked out of this address by hardware. -- BenC | ||
420 | */ | ||
421 | address = fib->hw_fib_pa - sizeof(struct aac_fib_xporthdr); | ||
422 | if (address & (ALIGN32 - 1)) | ||
423 | return -EINVAL; | ||
424 | address |= fibsize; | ||
425 | src_writel(dev, MUnit.IQ_H, (address >> 32) & 0xffffffff); | 434 | src_writel(dev, MUnit.IQ_H, (address >> 32) & 0xffffffff); |
426 | src_writel(dev, MUnit.IQ_L, address & 0xffffffff); | 435 | src_writel(dev, MUnit.IQ_L, address & 0xffffffff); |
427 | 436 | ||
@@ -764,7 +773,7 @@ int aac_srcv_init(struct aac_dev *dev) | |||
764 | 773 | ||
765 | if (aac_init_adapter(dev) == NULL) | 774 | if (aac_init_adapter(dev) == NULL) |
766 | goto error_iounmap; | 775 | goto error_iounmap; |
767 | if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1) | 776 | if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE2) |
768 | goto error_iounmap; | 777 | goto error_iounmap; |
769 | dev->msi = aac_msi && !pci_enable_msi(dev->pdev); | 778 | dev->msi = aac_msi && !pci_enable_msi(dev->pdev); |
770 | if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, | 779 | if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, |