diff options
Diffstat (limited to 'drivers/scsi/aacraid/comminit.c')
| -rw-r--r-- | drivers/scsi/aacraid/comminit.c | 106 |
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 | ||
| 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 | }; |
| @@ -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 | ||
| 180 | static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, int qsize) | 183 | static 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 | 511 | static 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 | } | ||
