diff options
author | Mahesh Rajashekhara <Mahesh.Rajashekhara@pmcs.com> | 2015-03-26 10:41:25 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Odin.com> | 2015-04-09 19:48:15 -0400 |
commit | 495c021767bd78c998a46cf8cdd7a4ebf3a9cfd1 (patch) | |
tree | df008c08442b599115bfc0b32aff99a83cd7ddc6 /drivers/scsi/aacraid/comminit.c | |
parent | b836439faf04b16c80ffd9a0699a2354ebde13e1 (diff) |
aacraid: MSI-x support
Signed-off-by: Mahesh Rajashekhara <Mahesh.Rajashekhara@pmcs.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Murthy Bhat <Murthy.Bhat@pmcs.com>
Signed-off-by: James Bottomley <JBottomley@Odin.com>
Diffstat (limited to 'drivers/scsi/aacraid/comminit.c')
-rw-r--r-- | drivers/scsi/aacraid/comminit.c | 95 |
1 files changed, 92 insertions, 3 deletions
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 177b094c7792..fdd95247f034 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 | ||
46 | static void aac_define_int_mode(struct aac_dev *dev); | ||
47 | |||
46 | struct aac_common aac_config = { | 48 | struct aac_common aac_config = { |
47 | .irq_mod = 1 | 49 | .irq_mod = 1 |
48 | }; | 50 | }; |
@@ -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 | ||
@@ -228,6 +231,11 @@ 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 | if ((dev->pdev->device == PMC_DEVICE_S7 || | ||
235 | dev->pdev->device == PMC_DEVICE_S8 || | ||
236 | dev->pdev->device == PMC_DEVICE_S9) && | ||
237 | dev->msi_enabled) | ||
238 | aac_src_access_devreg(dev, AAC_ENABLE_INTX); | ||
231 | return status; | 239 | return status; |
232 | } | 240 | } |
233 | 241 | ||
@@ -388,6 +396,8 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) | |||
388 | } | 396 | } |
389 | } | 397 | } |
390 | } | 398 | } |
399 | dev->max_msix = 0; | ||
400 | dev->msi_enabled = 0; | ||
391 | if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS, | 401 | if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS, |
392 | 0, 0, 0, 0, 0, 0, | 402 | 0, 0, 0, 0, 0, 0, |
393 | status+0, status+1, status+2, status+3, status+4)) | 403 | status+0, status+1, status+2, status+3, status+4)) |
@@ -461,6 +471,11 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) | |||
461 | if (host->can_queue > AAC_NUM_IO_FIB) | 471 | if (host->can_queue > AAC_NUM_IO_FIB) |
462 | host->can_queue = AAC_NUM_IO_FIB; | 472 | host->can_queue = AAC_NUM_IO_FIB; |
463 | 473 | ||
474 | if (dev->pdev->device == PMC_DEVICE_S6 || | ||
475 | dev->pdev->device == PMC_DEVICE_S7 || | ||
476 | dev->pdev->device == PMC_DEVICE_S8 || | ||
477 | dev->pdev->device == PMC_DEVICE_S9) | ||
478 | aac_define_int_mode(dev); | ||
464 | /* | 479 | /* |
465 | * Ok now init the communication subsystem | 480 | * Ok now init the communication subsystem |
466 | */ | 481 | */ |
@@ -489,4 +504,78 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) | |||
489 | return dev; | 504 | return dev; |
490 | } | 505 | } |
491 | 506 | ||
492 | 507 | static void aac_define_int_mode(struct aac_dev *dev) | |
508 | { | ||
509 | |||
510 | int i, msi_count; | ||
511 | |||
512 | /* max. vectors from GET_COMM_PREFERRED_SETTINGS */ | ||
513 | if (dev->max_msix == 0 || | ||
514 | dev->pdev->device == PMC_DEVICE_S6 || | ||
515 | dev->sync_mode) { | ||
516 | dev->max_msix = 1; | ||
517 | dev->vector_cap = | ||
518 | dev->scsi_host_ptr->can_queue + | ||
519 | AAC_NUM_MGT_FIB; | ||
520 | return; | ||
521 | } | ||
522 | |||
523 | msi_count = min(dev->max_msix, | ||
524 | (unsigned int)num_online_cpus()); | ||
525 | |||
526 | dev->max_msix = msi_count; | ||
527 | |||
528 | if (msi_count > AAC_MAX_MSIX) | ||
529 | msi_count = AAC_MAX_MSIX; | ||
530 | |||
531 | for (i = 0; i < msi_count; i++) | ||
532 | dev->msixentry[i].entry = i; | ||
533 | |||
534 | if (msi_count > 1 && | ||
535 | pci_find_capability(dev->pdev, PCI_CAP_ID_MSIX)) { | ||
536 | i = pci_enable_msix(dev->pdev, | ||
537 | dev->msixentry, | ||
538 | msi_count); | ||
539 | /* Check how many MSIX vectors are allocated */ | ||
540 | if (i >= 0) { | ||
541 | dev->msi_enabled = 1; | ||
542 | if (i) { | ||
543 | msi_count = i; | ||
544 | if (pci_enable_msix(dev->pdev, | ||
545 | dev->msixentry, | ||
546 | msi_count)) { | ||
547 | dev->msi_enabled = 0; | ||
548 | printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n", | ||
549 | dev->name, dev->id, i); | ||
550 | } | ||
551 | } | ||
552 | } else { | ||
553 | dev->msi_enabled = 0; | ||
554 | printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n", | ||
555 | dev->name, dev->id, i); | ||
556 | } | ||
557 | } | ||
558 | |||
559 | if (!dev->msi_enabled) { | ||
560 | msi_count = 1; | ||
561 | i = pci_enable_msi(dev->pdev); | ||
562 | |||
563 | if (!i) { | ||
564 | dev->msi_enabled = 1; | ||
565 | dev->msi = 1; | ||
566 | } else { | ||
567 | printk(KERN_ERR "%s%d: MSI not supported!! Will try INTx 0x%x.\n", | ||
568 | dev->name, dev->id, i); | ||
569 | } | ||
570 | } | ||
571 | |||
572 | if (!dev->msi_enabled) | ||
573 | dev->max_msix = msi_count = 1; | ||
574 | else { | ||
575 | if (dev->max_msix > msi_count) | ||
576 | dev->max_msix = msi_count; | ||
577 | } | ||
578 | dev->vector_cap = | ||
579 | (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) / | ||
580 | msi_count; | ||
581 | } | ||