diff options
Diffstat (limited to 'drivers/scsi/arcmsr/arcmsr_hba.c')
-rw-r--r-- | drivers/scsi/arcmsr/arcmsr_hba.c | 82 |
1 files changed, 32 insertions, 50 deletions
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index f0cfb0451757..9e45749d55ed 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -720,51 +720,39 @@ static void arcmsr_message_isr_bh_fn(struct work_struct *work) static int arcmsr_request_irq(struct pci_dev *pdev, struct AdapterControlBlock *acb) { - int i, j, r; - struct msix_entry entries[ARCMST_NUM_MSIX_VECTORS]; - - for (i = 0; i < ARCMST_NUM_MSIX_VECTORS; i++) - entries[i].entry = i; - r = pci_enable_msix_range(pdev, entries, 1, ARCMST_NUM_MSIX_VECTORS); - if (r < 0) - goto msi_int; - acb->msix_vector_count = r; - for (i = 0; i < r; i++) { - if (request_irq(entries[i].vector, - arcmsr_do_interrupt, 0, "arcmsr", acb)) { + unsigned long flags; + int nvec, i; + + nvec = pci_alloc_irq_vectors(pdev, 1, ARCMST_NUM_MSIX_VECTORS, + PCI_IRQ_MSIX); + if (nvec > 0) { + pr_info("arcmsr%d: msi-x enabled\n", acb->host->host_no); + flags = 0; + } else { + nvec = pci_alloc_irq_vectors(pdev, 1, 1, + PCI_IRQ_MSI | PCI_IRQ_LEGACY); + if (nvec < 1) + return FAILED; + + flags = IRQF_SHARED; + } + + acb->vector_count = nvec; + for (i = 0; i < nvec; i++) { + if (request_irq(pci_irq_vector(pdev, i), arcmsr_do_interrupt, + flags, "arcmsr", acb)) { pr_warn("arcmsr%d: request_irq =%d failed!\n", - acb->host->host_no, entries[i].vector); - for (j = 0 ; j < i ; j++) - free_irq(entries[j].vector, acb); - pci_disable_msix(pdev); - goto msi_int; + acb->host->host_no, pci_irq_vector(pdev, i)); + goto out_free_irq; } - acb->entries[i] = entries[i]; - } - acb->acb_flags |= ACB_F_MSIX_ENABLED; - pr_info("arcmsr%d: msi-x enabled\n", acb->host->host_no); - return SUCCESS; -msi_int: - if (pci_enable_msi_exact(pdev, 1) < 0) - goto legacy_int; - if (request_irq(pdev->irq, arcmsr_do_interrupt, - IRQF_SHARED, "arcmsr", acb)) { - pr_warn("arcmsr%d: request_irq =%d failed!\n", - acb->host->host_no, pdev->irq); - pci_disable_msi(pdev); - goto legacy_int; - } - acb->acb_flags |= ACB_F_MSI_ENABLED; - pr_info("arcmsr%d: msi enabled\n", acb->host->host_no); - return SUCCESS; -legacy_int: - if (request_irq(pdev->irq, arcmsr_do_interrupt, - IRQF_SHARED, "arcmsr", acb)) { - pr_warn("arcmsr%d: request_irq = %d failed!\n", - acb->host->host_no, pdev->irq); - return FAILED; } + return SUCCESS; +out_free_irq: + while (--i >= 0) + free_irq(pci_irq_vector(pdev, i), acb); + pci_free_irq_vectors(pdev); + return FAILED; } static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) @@ -886,15 +874,9 @@ static void arcmsr_free_irq(struct pci_dev *pdev, { int i; - if (acb->acb_flags & ACB_F_MSI_ENABLED) { - free_irq(pdev->irq, acb); - pci_disable_msi(pdev); - } else if (acb->acb_flags & ACB_F_MSIX_ENABLED) { - for (i = 0; i < acb->msix_vector_count; i++) - free_irq(acb->entries[i].vector, acb); - pci_disable_msix(pdev); - } else - free_irq(pdev->irq, acb); + for (i = 0; i < acb->vector_count; i++) + free_irq(pci_irq_vector(pdev, i), acb); + pci_free_irq_vectors(pdev); } static int arcmsr_suspend(struct pci_dev *pdev, pm_message_t state) |