aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aacraid/comminit.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/aacraid/comminit.c')
-rw-r--r--drivers/scsi/aacraid/comminit.c106
1 files changed, 100 insertions, 6 deletions
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 177b094c7792..45db84ad322f 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -43,6 +43,8 @@
43 43
44#include "aacraid.h" 44#include "aacraid.h"
45 45
46static void aac_define_int_mode(struct aac_dev *dev);
47
46struct aac_common aac_config = { 48struct aac_common aac_config = {
47 .irq_mod = 1 49 .irq_mod = 1
48}; 50};
@@ -51,7 +53,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
51{ 53{
52 unsigned char *base; 54 unsigned char *base;
53 unsigned long size, align; 55 unsigned long size, align;
54 const unsigned long fibsize = 4096; 56 const unsigned long fibsize = dev->max_fib_size;
55 const unsigned long printfbufsiz = 256; 57 const unsigned long printfbufsiz = 256;
56 unsigned long host_rrq_size = 0; 58 unsigned long host_rrq_size = 0;
57 struct aac_init *init; 59 struct aac_init *init;
@@ -91,7 +93,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
91 init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION); 93 init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION);
92 if (dev->max_fib_size != sizeof(struct hw_fib)) 94 if (dev->max_fib_size != sizeof(struct hw_fib))
93 init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4); 95 init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4);
94 init->MiniPortRevision = cpu_to_le32(Sa_MINIPORT_REVISION); 96 init->Sa_MSIXVectors = cpu_to_le32(Sa_MINIPORT_REVISION);
95 init->fsrev = cpu_to_le32(dev->fsrev); 97 init->fsrev = cpu_to_le32(dev->fsrev);
96 98
97 /* 99 /*
@@ -140,7 +142,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
140 INITFLAGS_NEW_COMM_TYPE2_SUPPORTED | INITFLAGS_FAST_JBOD_SUPPORTED); 142 INITFLAGS_NEW_COMM_TYPE2_SUPPORTED | INITFLAGS_FAST_JBOD_SUPPORTED);
141 init->HostRRQ_AddrHigh = cpu_to_le32((u32)((u64)dev->host_rrq_pa >> 32)); 143 init->HostRRQ_AddrHigh = cpu_to_le32((u32)((u64)dev->host_rrq_pa >> 32));
142 init->HostRRQ_AddrLow = cpu_to_le32((u32)(dev->host_rrq_pa & 0xffffffff)); 144 init->HostRRQ_AddrLow = cpu_to_le32((u32)(dev->host_rrq_pa & 0xffffffff));
143 init->MiniPortRevision = cpu_to_le32(0L); /* number of MSI-X */ 145 /* number of MSI-X */
146 init->Sa_MSIXVectors = cpu_to_le32(dev->max_msix);
144 dprintk((KERN_WARNING"aacraid: New Comm Interface type2 enabled\n")); 147 dprintk((KERN_WARNING"aacraid: New Comm Interface type2 enabled\n"));
145 } 148 }
146 149
@@ -179,7 +182,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
179 182
180static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, int qsize) 183static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, int qsize)
181{ 184{
182 q->numpending = 0; 185 atomic_set(&q->numpending, 0);
183 q->dev = dev; 186 q->dev = dev;
184 init_waitqueue_head(&q->cmdready); 187 init_waitqueue_head(&q->cmdready);
185 INIT_LIST_HEAD(&q->cmdq); 188 INIT_LIST_HEAD(&q->cmdq);
@@ -228,6 +231,12 @@ int aac_send_shutdown(struct aac_dev * dev)
228 /* FIB should be freed only after getting the response from the F/W */ 231 /* FIB should be freed only after getting the response from the F/W */
229 if (status != -ERESTARTSYS) 232 if (status != -ERESTARTSYS)
230 aac_fib_free(fibctx); 233 aac_fib_free(fibctx);
234 dev->adapter_shutdown = 1;
235 if ((dev->pdev->device == PMC_DEVICE_S7 ||
236 dev->pdev->device == PMC_DEVICE_S8 ||
237 dev->pdev->device == PMC_DEVICE_S9) &&
238 dev->msi_enabled)
239 aac_src_access_devreg(dev, AAC_ENABLE_INTX);
231 return status; 240 return status;
232} 241}
233 242
@@ -350,8 +359,10 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
350 dev->raw_io_interface = dev->raw_io_64 = 0; 359 dev->raw_io_interface = dev->raw_io_64 = 0;
351 360
352 if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES, 361 if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES,
353 0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) && 362 0, 0, 0, 0, 0, 0,
363 status+0, status+1, status+2, status+3, NULL)) &&
354 (status[0] == 0x00000001)) { 364 (status[0] == 0x00000001)) {
365 dev->doorbell_mask = status[3];
355 if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64)) 366 if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64))
356 dev->raw_io_64 = 1; 367 dev->raw_io_64 = 1;
357 dev->sync_mode = aac_sync_mode; 368 dev->sync_mode = aac_sync_mode;
@@ -388,6 +399,9 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
388 } 399 }
389 } 400 }
390 } 401 }
402 dev->max_msix = 0;
403 dev->msi_enabled = 0;
404 dev->adapter_shutdown = 0;
391 if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS, 405 if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS,
392 0, 0, 0, 0, 0, 0, 406 0, 0, 0, 0, 0, 0,
393 status+0, status+1, status+2, status+3, status+4)) 407 status+0, status+1, status+2, status+3, status+4))
@@ -461,6 +475,11 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
461 if (host->can_queue > AAC_NUM_IO_FIB) 475 if (host->can_queue > AAC_NUM_IO_FIB)
462 host->can_queue = AAC_NUM_IO_FIB; 476 host->can_queue = AAC_NUM_IO_FIB;
463 477
478 if (dev->pdev->device == PMC_DEVICE_S6 ||
479 dev->pdev->device == PMC_DEVICE_S7 ||
480 dev->pdev->device == PMC_DEVICE_S8 ||
481 dev->pdev->device == PMC_DEVICE_S9)
482 aac_define_int_mode(dev);
464 /* 483 /*
465 * Ok now init the communication subsystem 484 * Ok now init the communication subsystem
466 */ 485 */
@@ -489,4 +508,79 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
489 return dev; 508 return dev;
490} 509}
491 510
492 511static void aac_define_int_mode(struct aac_dev *dev)
512{
513
514 int i, msi_count;
515
516 msi_count = i = 0;
517 /* max. vectors from GET_COMM_PREFERRED_SETTINGS */
518 if (dev->max_msix == 0 ||
519 dev->pdev->device == PMC_DEVICE_S6 ||
520 dev->sync_mode) {
521 dev->max_msix = 1;
522 dev->vector_cap =
523 dev->scsi_host_ptr->can_queue +
524 AAC_NUM_MGT_FIB;
525 return;
526 }
527
528 msi_count = min(dev->max_msix,
529 (unsigned int)num_online_cpus());
530
531 dev->max_msix = msi_count;
532
533 if (msi_count > AAC_MAX_MSIX)
534 msi_count = AAC_MAX_MSIX;
535
536 for (i = 0; i < msi_count; i++)
537 dev->msixentry[i].entry = i;
538
539 if (msi_count > 1 &&
540 pci_find_capability(dev->pdev, PCI_CAP_ID_MSIX)) {
541 i = pci_enable_msix(dev->pdev,
542 dev->msixentry,
543 msi_count);
544 /* Check how many MSIX vectors are allocated */
545 if (i >= 0) {
546 dev->msi_enabled = 1;
547 if (i) {
548 msi_count = i;
549 if (pci_enable_msix(dev->pdev,
550 dev->msixentry,
551 msi_count)) {
552 dev->msi_enabled = 0;
553 printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n",
554 dev->name, dev->id, i);
555 }
556 }
557 } else {
558 dev->msi_enabled = 0;
559 printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n",
560 dev->name, dev->id, i);
561 }
562 }
563
564 if (!dev->msi_enabled) {
565 msi_count = 1;
566 i = pci_enable_msi(dev->pdev);
567
568 if (!i) {
569 dev->msi_enabled = 1;
570 dev->msi = 1;
571 } else {
572 printk(KERN_ERR "%s%d: MSI not supported!! Will try INTx 0x%x.\n",
573 dev->name, dev->id, i);
574 }
575 }
576
577 if (!dev->msi_enabled)
578 dev->max_msix = msi_count = 1;
579 else {
580 if (dev->max_msix > msi_count)
581 dev->max_msix = msi_count;
582 }
583 dev->vector_cap =
584 (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) /
585 msi_count;
586}