diff options
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_base.c | 281 |
1 files changed, 135 insertions, 146 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 890637fdd61e..5be9ce45bde8 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c | |||
@@ -4414,6 +4414,107 @@ fail_alloc_cmds: | |||
4414 | return 1; | 4414 | return 1; |
4415 | } | 4415 | } |
4416 | 4416 | ||
4417 | /* | ||
4418 | * megasas_setup_irqs_msix - register legacy interrupts. | ||
4419 | * @instance: Adapter soft state | ||
4420 | * | ||
4421 | * Do not enable interrupt, only setup ISRs. | ||
4422 | * | ||
4423 | * Return 0 on success. | ||
4424 | */ | ||
4425 | static int | ||
4426 | megasas_setup_irqs_ioapic(struct megasas_instance *instance) | ||
4427 | { | ||
4428 | struct pci_dev *pdev; | ||
4429 | |||
4430 | pdev = instance->pdev; | ||
4431 | instance->irq_context[0].instance = instance; | ||
4432 | instance->irq_context[0].MSIxIndex = 0; | ||
4433 | if (request_irq(pdev->irq, instance->instancet->service_isr, | ||
4434 | IRQF_SHARED, "megasas", &instance->irq_context[0])) { | ||
4435 | dev_err(&instance->pdev->dev, | ||
4436 | "Failed to register IRQ from %s %d\n", | ||
4437 | __func__, __LINE__); | ||
4438 | return -1; | ||
4439 | } | ||
4440 | return 0; | ||
4441 | } | ||
4442 | |||
4443 | /** | ||
4444 | * megasas_setup_irqs_msix - register MSI-x interrupts. | ||
4445 | * @instance: Adapter soft state | ||
4446 | * @is_probe: Driver probe check | ||
4447 | * | ||
4448 | * Do not enable interrupt, only setup ISRs. | ||
4449 | * | ||
4450 | * Return 0 on success. | ||
4451 | */ | ||
4452 | static int | ||
4453 | megasas_setup_irqs_msix(struct megasas_instance *instance, u8 is_probe) | ||
4454 | { | ||
4455 | int i, j, cpu; | ||
4456 | struct pci_dev *pdev; | ||
4457 | |||
4458 | pdev = instance->pdev; | ||
4459 | |||
4460 | /* Try MSI-x */ | ||
4461 | cpu = cpumask_first(cpu_online_mask); | ||
4462 | for (i = 0; i < instance->msix_vectors; i++) { | ||
4463 | instance->irq_context[i].instance = instance; | ||
4464 | instance->irq_context[i].MSIxIndex = i; | ||
4465 | if (request_irq(instance->msixentry[i].vector, | ||
4466 | instance->instancet->service_isr, 0, "megasas", | ||
4467 | &instance->irq_context[i])) { | ||
4468 | dev_err(&instance->pdev->dev, | ||
4469 | "Failed to register IRQ for vector %d.\n", i); | ||
4470 | for (j = 0; j < i; j++) { | ||
4471 | if (smp_affinity_enable) | ||
4472 | irq_set_affinity_hint( | ||
4473 | instance->msixentry[j].vector, NULL); | ||
4474 | free_irq(instance->msixentry[j].vector, | ||
4475 | &instance->irq_context[j]); | ||
4476 | } | ||
4477 | /* Retry irq register for IO_APIC*/ | ||
4478 | instance->msix_vectors = 0; | ||
4479 | if (is_probe) | ||
4480 | return megasas_setup_irqs_ioapic(instance); | ||
4481 | else | ||
4482 | return -1; | ||
4483 | } | ||
4484 | if (smp_affinity_enable) { | ||
4485 | if (irq_set_affinity_hint(instance->msixentry[i].vector, | ||
4486 | get_cpu_mask(cpu))) | ||
4487 | dev_err(&instance->pdev->dev, | ||
4488 | "Failed to set affinity hint" | ||
4489 | " for cpu %d\n", cpu); | ||
4490 | cpu = cpumask_next(cpu, cpu_online_mask); | ||
4491 | } | ||
4492 | } | ||
4493 | return 0; | ||
4494 | } | ||
4495 | |||
4496 | /* | ||
4497 | * megasas_destroy_irqs- unregister interrupts. | ||
4498 | * @instance: Adapter soft state | ||
4499 | * return: void | ||
4500 | */ | ||
4501 | static void | ||
4502 | megasas_destroy_irqs(struct megasas_instance *instance) { | ||
4503 | |||
4504 | int i; | ||
4505 | |||
4506 | if (instance->msix_vectors) | ||
4507 | for (i = 0; i < instance->msix_vectors; i++) { | ||
4508 | if (smp_affinity_enable) | ||
4509 | irq_set_affinity_hint( | ||
4510 | instance->msixentry[i].vector, NULL); | ||
4511 | free_irq(instance->msixentry[i].vector, | ||
4512 | &instance->irq_context[i]); | ||
4513 | } | ||
4514 | else | ||
4515 | free_irq(instance->pdev->irq, &instance->irq_context[0]); | ||
4516 | } | ||
4517 | |||
4417 | /** | 4518 | /** |
4418 | * megasas_init_fw - Initializes the FW | 4519 | * megasas_init_fw - Initializes the FW |
4419 | * @instance: Adapter soft state | 4520 | * @instance: Adapter soft state |
@@ -4552,11 +4653,16 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
4552 | else | 4653 | else |
4553 | instance->msix_vectors = 0; | 4654 | instance->msix_vectors = 0; |
4554 | 4655 | ||
4555 | dev_info(&instance->pdev->dev, "[scsi%d]: FW supports" | 4656 | dev_info(&instance->pdev->dev, |
4556 | "<%d> MSIX vector,Online CPUs: <%d>," | 4657 | "firmware supports msix\t: (%d)", fw_msix_count); |
4557 | "Current MSIX <%d>\n", instance->host->host_no, | 4658 | dev_info(&instance->pdev->dev, |
4558 | fw_msix_count, (unsigned int)num_online_cpus(), | 4659 | "current msix/online cpus\t: (%d/%d)\n", |
4559 | instance->msix_vectors); | 4660 | instance->msix_vectors, (unsigned int)num_online_cpus()); |
4661 | |||
4662 | if (instance->msix_vectors ? | ||
4663 | megasas_setup_irqs_msix(instance, 1) : | ||
4664 | megasas_setup_irqs_ioapic(instance)) | ||
4665 | goto fail_setup_irqs; | ||
4560 | } | 4666 | } |
4561 | 4667 | ||
4562 | instance->ctrl_info = kzalloc(sizeof(struct megasas_ctrl_info), | 4668 | instance->ctrl_info = kzalloc(sizeof(struct megasas_ctrl_info), |
@@ -4573,6 +4679,7 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
4573 | /* Get operational params, sge flags, send init cmd to controller */ | 4679 | /* Get operational params, sge flags, send init cmd to controller */ |
4574 | if (instance->instancet->init_adapter(instance)) | 4680 | if (instance->instancet->init_adapter(instance)) |
4575 | goto fail_init_adapter; | 4681 | goto fail_init_adapter; |
4682 | instance->instancet->enable_intr(instance); | ||
4576 | 4683 | ||
4577 | printk(KERN_ERR "megasas: INIT adapter done\n"); | 4684 | printk(KERN_ERR "megasas: INIT adapter done\n"); |
4578 | 4685 | ||
@@ -4584,7 +4691,7 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
4584 | (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list))); | 4691 | (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list))); |
4585 | if (megasas_get_pd_list(instance) < 0) { | 4692 | if (megasas_get_pd_list(instance) < 0) { |
4586 | printk(KERN_ERR "megasas: failed to get PD list\n"); | 4693 | printk(KERN_ERR "megasas: failed to get PD list\n"); |
4587 | goto fail_init_adapter; | 4694 | goto fail_get_pd_list; |
4588 | } | 4695 | } |
4589 | 4696 | ||
4590 | memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); | 4697 | memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); |
@@ -4733,7 +4840,14 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
4733 | 4840 | ||
4734 | return 0; | 4841 | return 0; |
4735 | 4842 | ||
4843 | fail_get_pd_list: | ||
4844 | instance->instancet->disable_intr(instance); | ||
4736 | fail_init_adapter: | 4845 | fail_init_adapter: |
4846 | megasas_destroy_irqs(instance); | ||
4847 | fail_setup_irqs: | ||
4848 | if (instance->msix_vectors) | ||
4849 | pci_disable_msix(instance->pdev); | ||
4850 | instance->msix_vectors = 0; | ||
4737 | fail_ready_state: | 4851 | fail_ready_state: |
4738 | kfree(instance->ctrl_info); | 4852 | kfree(instance->ctrl_info); |
4739 | instance->ctrl_info = NULL; | 4853 | instance->ctrl_info = NULL; |
@@ -5106,7 +5220,7 @@ fail_set_dma_mask: | |||
5106 | static int megasas_probe_one(struct pci_dev *pdev, | 5220 | static int megasas_probe_one(struct pci_dev *pdev, |
5107 | const struct pci_device_id *id) | 5221 | const struct pci_device_id *id) |
5108 | { | 5222 | { |
5109 | int rval, pos, i, j, cpu; | 5223 | int rval, pos; |
5110 | struct Scsi_Host *host; | 5224 | struct Scsi_Host *host; |
5111 | struct megasas_instance *instance; | 5225 | struct megasas_instance *instance; |
5112 | u16 control = 0; | 5226 | u16 control = 0; |
@@ -5315,55 +5429,6 @@ static int megasas_probe_one(struct pci_dev *pdev, | |||
5315 | } | 5429 | } |
5316 | } | 5430 | } |
5317 | 5431 | ||
5318 | retry_irq_register: | ||
5319 | /* | ||
5320 | * Register IRQ | ||
5321 | */ | ||
5322 | if (instance->msix_vectors) { | ||
5323 | cpu = cpumask_first(cpu_online_mask); | ||
5324 | for (i = 0; i < instance->msix_vectors; i++) { | ||
5325 | instance->irq_context[i].instance = instance; | ||
5326 | instance->irq_context[i].MSIxIndex = i; | ||
5327 | if (request_irq(instance->msixentry[i].vector, | ||
5328 | instance->instancet->service_isr, 0, | ||
5329 | "megasas", | ||
5330 | &instance->irq_context[i])) { | ||
5331 | printk(KERN_DEBUG "megasas: Failed to " | ||
5332 | "register IRQ for vector %d.\n", i); | ||
5333 | for (j = 0; j < i; j++) { | ||
5334 | if (smp_affinity_enable) | ||
5335 | irq_set_affinity_hint( | ||
5336 | instance->msixentry[j].vector, NULL); | ||
5337 | free_irq( | ||
5338 | instance->msixentry[j].vector, | ||
5339 | &instance->irq_context[j]); | ||
5340 | } | ||
5341 | /* Retry irq register for IO_APIC */ | ||
5342 | instance->msix_vectors = 0; | ||
5343 | goto retry_irq_register; | ||
5344 | } | ||
5345 | if (smp_affinity_enable) { | ||
5346 | if (irq_set_affinity_hint(instance->msixentry[i].vector, | ||
5347 | get_cpu_mask(cpu))) | ||
5348 | dev_err(&instance->pdev->dev, | ||
5349 | "Error setting affinity hint " | ||
5350 | "for cpu %d\n", cpu); | ||
5351 | cpu = cpumask_next(cpu, cpu_online_mask); | ||
5352 | } | ||
5353 | } | ||
5354 | } else { | ||
5355 | instance->irq_context[0].instance = instance; | ||
5356 | instance->irq_context[0].MSIxIndex = 0; | ||
5357 | if (request_irq(pdev->irq, instance->instancet->service_isr, | ||
5358 | IRQF_SHARED, "megasas", | ||
5359 | &instance->irq_context[0])) { | ||
5360 | printk(KERN_DEBUG "megasas: Failed to register IRQ\n"); | ||
5361 | goto fail_irq; | ||
5362 | } | ||
5363 | } | ||
5364 | |||
5365 | instance->instancet->enable_intr(instance); | ||
5366 | |||
5367 | /* | 5432 | /* |
5368 | * Store instance in PCI softstate | 5433 | * Store instance in PCI softstate |
5369 | */ | 5434 | */ |
@@ -5410,17 +5475,8 @@ retry_irq_register: | |||
5410 | megasas_mgmt_info.max_index--; | 5475 | megasas_mgmt_info.max_index--; |
5411 | 5476 | ||
5412 | instance->instancet->disable_intr(instance); | 5477 | instance->instancet->disable_intr(instance); |
5413 | if (instance->msix_vectors) | 5478 | megasas_destroy_irqs(instance); |
5414 | for (i = 0; i < instance->msix_vectors; i++) { | 5479 | |
5415 | if (smp_affinity_enable) | ||
5416 | irq_set_affinity_hint( | ||
5417 | instance->msixentry[i].vector, NULL); | ||
5418 | free_irq(instance->msixentry[i].vector, | ||
5419 | &instance->irq_context[i]); | ||
5420 | } | ||
5421 | else | ||
5422 | free_irq(instance->pdev->irq, &instance->irq_context[0]); | ||
5423 | fail_irq: | ||
5424 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || | 5480 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || |
5425 | (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) || | 5481 | (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) || |
5426 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | 5482 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || |
@@ -5428,9 +5484,9 @@ fail_irq: | |||
5428 | megasas_release_fusion(instance); | 5484 | megasas_release_fusion(instance); |
5429 | else | 5485 | else |
5430 | megasas_release_mfi(instance); | 5486 | megasas_release_mfi(instance); |
5431 | fail_init_mfi: | ||
5432 | if (instance->msix_vectors) | 5487 | if (instance->msix_vectors) |
5433 | pci_disable_msix(instance->pdev); | 5488 | pci_disable_msix(instance->pdev); |
5489 | fail_init_mfi: | ||
5434 | fail_alloc_dma_buf: | 5490 | fail_alloc_dma_buf: |
5435 | if (instance->evt_detail) | 5491 | if (instance->evt_detail) |
5436 | pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), | 5492 | pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), |
@@ -5558,7 +5614,6 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) | |||
5558 | { | 5614 | { |
5559 | struct Scsi_Host *host; | 5615 | struct Scsi_Host *host; |
5560 | struct megasas_instance *instance; | 5616 | struct megasas_instance *instance; |
5561 | int i; | ||
5562 | 5617 | ||
5563 | instance = pci_get_drvdata(pdev); | 5618 | instance = pci_get_drvdata(pdev); |
5564 | host = instance->host; | 5619 | host = instance->host; |
@@ -5583,16 +5638,8 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) | |||
5583 | pci_set_drvdata(instance->pdev, instance); | 5638 | pci_set_drvdata(instance->pdev, instance); |
5584 | instance->instancet->disable_intr(instance); | 5639 | instance->instancet->disable_intr(instance); |
5585 | 5640 | ||
5586 | if (instance->msix_vectors) | 5641 | megasas_destroy_irqs(instance); |
5587 | for (i = 0; i < instance->msix_vectors; i++) { | 5642 | |
5588 | if (smp_affinity_enable) | ||
5589 | irq_set_affinity_hint( | ||
5590 | instance->msixentry[i].vector, NULL); | ||
5591 | free_irq(instance->msixentry[i].vector, | ||
5592 | &instance->irq_context[i]); | ||
5593 | } | ||
5594 | else | ||
5595 | free_irq(instance->pdev->irq, &instance->irq_context[0]); | ||
5596 | if (instance->msix_vectors) | 5643 | if (instance->msix_vectors) |
5597 | pci_disable_msix(instance->pdev); | 5644 | pci_disable_msix(instance->pdev); |
5598 | 5645 | ||
@@ -5611,7 +5658,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) | |||
5611 | static int | 5658 | static int |
5612 | megasas_resume(struct pci_dev *pdev) | 5659 | megasas_resume(struct pci_dev *pdev) |
5613 | { | 5660 | { |
5614 | int rval, i, j, cpu; | 5661 | int rval; |
5615 | struct Scsi_Host *host; | 5662 | struct Scsi_Host *host; |
5616 | struct megasas_instance *instance; | 5663 | struct megasas_instance *instance; |
5617 | 5664 | ||
@@ -5681,50 +5728,10 @@ megasas_resume(struct pci_dev *pdev) | |||
5681 | tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet, | 5728 | tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet, |
5682 | (unsigned long)instance); | 5729 | (unsigned long)instance); |
5683 | 5730 | ||
5684 | /* | 5731 | if (instance->msix_vectors ? |
5685 | * Register IRQ | 5732 | megasas_setup_irqs_msix(instance, 0) : |
5686 | */ | 5733 | megasas_setup_irqs_ioapic(instance)) |
5687 | if (instance->msix_vectors) { | 5734 | goto fail_init_mfi; |
5688 | cpu = cpumask_first(cpu_online_mask); | ||
5689 | for (i = 0 ; i < instance->msix_vectors; i++) { | ||
5690 | instance->irq_context[i].instance = instance; | ||
5691 | instance->irq_context[i].MSIxIndex = i; | ||
5692 | if (request_irq(instance->msixentry[i].vector, | ||
5693 | instance->instancet->service_isr, 0, | ||
5694 | "megasas", | ||
5695 | &instance->irq_context[i])) { | ||
5696 | printk(KERN_DEBUG "megasas: Failed to " | ||
5697 | "register IRQ for vector %d.\n", i); | ||
5698 | for (j = 0; j < i; j++) { | ||
5699 | if (smp_affinity_enable) | ||
5700 | irq_set_affinity_hint( | ||
5701 | instance->msixentry[j].vector, NULL); | ||
5702 | free_irq( | ||
5703 | instance->msixentry[j].vector, | ||
5704 | &instance->irq_context[j]); | ||
5705 | } | ||
5706 | goto fail_irq; | ||
5707 | } | ||
5708 | |||
5709 | if (smp_affinity_enable) { | ||
5710 | if (irq_set_affinity_hint(instance->msixentry[i].vector, | ||
5711 | get_cpu_mask(cpu))) | ||
5712 | dev_err(&instance->pdev->dev, "Error " | ||
5713 | "setting affinity hint for cpu " | ||
5714 | "%d\n", cpu); | ||
5715 | cpu = cpumask_next(cpu, cpu_online_mask); | ||
5716 | } | ||
5717 | } | ||
5718 | } else { | ||
5719 | instance->irq_context[0].instance = instance; | ||
5720 | instance->irq_context[0].MSIxIndex = 0; | ||
5721 | if (request_irq(pdev->irq, instance->instancet->service_isr, | ||
5722 | IRQF_SHARED, "megasas", | ||
5723 | &instance->irq_context[0])) { | ||
5724 | printk(KERN_DEBUG "megasas: Failed to register IRQ\n"); | ||
5725 | goto fail_irq; | ||
5726 | } | ||
5727 | } | ||
5728 | 5735 | ||
5729 | /* Re-launch SR-IOV heartbeat timer */ | 5736 | /* Re-launch SR-IOV heartbeat timer */ |
5730 | if (instance->requestorId) { | 5737 | if (instance->requestorId) { |
@@ -5748,7 +5755,6 @@ megasas_resume(struct pci_dev *pdev) | |||
5748 | 5755 | ||
5749 | return 0; | 5756 | return 0; |
5750 | 5757 | ||
5751 | fail_irq: | ||
5752 | fail_init_mfi: | 5758 | fail_init_mfi: |
5753 | if (instance->evt_detail) | 5759 | if (instance->evt_detail) |
5754 | pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), | 5760 | pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), |
@@ -5829,16 +5835,8 @@ static void megasas_detach_one(struct pci_dev *pdev) | |||
5829 | 5835 | ||
5830 | instance->instancet->disable_intr(instance); | 5836 | instance->instancet->disable_intr(instance); |
5831 | 5837 | ||
5832 | if (instance->msix_vectors) | 5838 | megasas_destroy_irqs(instance); |
5833 | for (i = 0; i < instance->msix_vectors; i++) { | 5839 | |
5834 | if (smp_affinity_enable) | ||
5835 | irq_set_affinity_hint( | ||
5836 | instance->msixentry[i].vector, NULL); | ||
5837 | free_irq(instance->msixentry[i].vector, | ||
5838 | &instance->irq_context[i]); | ||
5839 | } | ||
5840 | else | ||
5841 | free_irq(instance->pdev->irq, &instance->irq_context[0]); | ||
5842 | if (instance->msix_vectors) | 5840 | if (instance->msix_vectors) |
5843 | pci_disable_msix(instance->pdev); | 5841 | pci_disable_msix(instance->pdev); |
5844 | 5842 | ||
@@ -5912,23 +5910,14 @@ static void megasas_detach_one(struct pci_dev *pdev) | |||
5912 | */ | 5910 | */ |
5913 | static void megasas_shutdown(struct pci_dev *pdev) | 5911 | static void megasas_shutdown(struct pci_dev *pdev) |
5914 | { | 5912 | { |
5915 | int i; | ||
5916 | struct megasas_instance *instance = pci_get_drvdata(pdev); | 5913 | struct megasas_instance *instance = pci_get_drvdata(pdev); |
5917 | 5914 | ||
5918 | instance->unload = 1; | 5915 | instance->unload = 1; |
5919 | megasas_flush_cache(instance); | 5916 | megasas_flush_cache(instance); |
5920 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); | 5917 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); |
5921 | instance->instancet->disable_intr(instance); | 5918 | instance->instancet->disable_intr(instance); |
5922 | if (instance->msix_vectors) | 5919 | megasas_destroy_irqs(instance); |
5923 | for (i = 0; i < instance->msix_vectors; i++) { | 5920 | |
5924 | if (smp_affinity_enable) | ||
5925 | irq_set_affinity_hint( | ||
5926 | instance->msixentry[i].vector, NULL); | ||
5927 | free_irq(instance->msixentry[i].vector, | ||
5928 | &instance->irq_context[i]); | ||
5929 | } | ||
5930 | else | ||
5931 | free_irq(instance->pdev->irq, &instance->irq_context[0]); | ||
5932 | if (instance->msix_vectors) | 5921 | if (instance->msix_vectors) |
5933 | pci_disable_msix(instance->pdev); | 5922 | pci_disable_msix(instance->pdev); |
5934 | } | 5923 | } |