scsi: lpfc: use pci_irq_alloc_vectors and pci_irq_free_vectors
authorChristoph Hellwig <hch@lst.de>
Sun, 12 Feb 2017 21:52:26 +0000 (13:52 -0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 22 Feb 2017 23:41:42 +0000 (18:41 -0500)
This avoids having to store the msix_entries array and simpliefies the
shutdown and cleanup path a lot.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: James Smart <james.smart@broadcom.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_sli4.h

index 6593b073c52483c52b8dcd31adf5248566d2f80f..64022d79117b78f6cf0287fa09ca9f7aa28af170 100644 (file)
@@ -878,8 +878,6 @@ struct lpfc_hba {
        enum intr_type_t intr_type;
        uint32_t intr_mode;
 #define LPFC_INTR_ERROR        0xFFFFFFFF
-       struct msix_entry msix_entries[LPFC_MSIX_VECTORS];
-
        struct list_head port_list;
        struct lpfc_vport *pport;       /* physical lpfc_vport pointer */
        uint16_t max_vpi;               /* Maximum virtual nports */
index 64717c171b15576a94726e76059f434483c3df1d..8cffad192f17342778ef32bd8b10c579075feb0c 100644 (file)
@@ -5509,17 +5509,6 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
                goto out_free_fcf_rr_bmask;
        }
 
-       phba->sli4_hba.msix_entries = kzalloc((sizeof(struct msix_entry) *
-                                 (fof_vectors +
-                                  phba->cfg_fcp_io_channel)), GFP_KERNEL);
-       if (!phba->sli4_hba.msix_entries) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "2573 Failed allocate memory for msi-x "
-                               "interrupt vector entries\n");
-               rc = -ENOMEM;
-               goto out_free_fcp_eq_hdl;
-       }
-
        phba->sli4_hba.cpu_map = kzalloc((sizeof(struct lpfc_vector_map_info) *
                                         phba->sli4_hba.num_present_cpu),
                                         GFP_KERNEL);
@@ -5528,7 +5517,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
                                "3327 Failed allocate memory for msi-x "
                                "interrupt vector mapping\n");
                rc = -ENOMEM;
-               goto out_free_msix;
+               goto out_free_fcp_eq_hdl;
        }
        if (lpfc_used_cpu == NULL) {
                lpfc_used_cpu = kzalloc((sizeof(uint16_t) * lpfc_present_cpu),
@@ -5539,7 +5528,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
                                        "interrupt vector mapping\n");
                        kfree(phba->sli4_hba.cpu_map);
                        rc = -ENOMEM;
-                       goto out_free_msix;
+                       goto out_free_fcp_eq_hdl;
                }
                for (i = 0; i < lpfc_present_cpu; i++)
                        lpfc_used_cpu[i] = LPFC_VECTOR_MAP_EMPTY;
@@ -5574,8 +5563,6 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
 
        return 0;
 
-out_free_msix:
-       kfree(phba->sli4_hba.msix_entries);
 out_free_fcp_eq_hdl:
        kfree(phba->sli4_hba.fcp_eq_hdl);
 out_free_fcf_rr_bmask:
@@ -5611,9 +5598,6 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba)
        phba->sli4_hba.num_online_cpu = 0;
        phba->sli4_hba.curr_disp_cpu = 0;
 
-       /* Free memory allocated for msi-x interrupt vector entries */
-       kfree(phba->sli4_hba.msix_entries);
-
        /* Free memory allocated for fast-path work queue handles */
        kfree(phba->sli4_hba.fcp_eq_hdl);
 
@@ -8484,16 +8468,7 @@ lpfc_sli4_pci_mem_unset(struct lpfc_hba *phba)
  * @phba: pointer to lpfc hba data structure.
  *
  * This routine is invoked to enable the MSI-X interrupt vectors to device
- * with SLI-3 interface specs. The kernel function pci_enable_msix_exact()
- * is called to enable the MSI-X vectors. Note that pci_enable_msix_exact(),
- * once invoked, enables either all or nothing, depending on the current
- * availability of PCI vector resources. The device driver is responsible
- * for calling the individual request_irq() to register each MSI-X vector
- * with a interrupt handler, which is done in this function. Note that
- * later when device is unloading, the driver should always call free_irq()
- * on all MSI-X vectors it has done request_irq() on before calling
- * pci_disable_msix(). Failure to do so results in a BUG_ON() and a device
- * will be left with MSI-X enabled and leaks its vectors.
+ * with SLI-3 interface specs.
  *
  * Return codes
  *   0 - successful
@@ -8502,33 +8477,24 @@ lpfc_sli4_pci_mem_unset(struct lpfc_hba *phba)
 static int
 lpfc_sli_enable_msix(struct lpfc_hba *phba)
 {
-       int rc, i;
+       int rc;
        LPFC_MBOXQ_t *pmb;
 
        /* Set up MSI-X multi-message vectors */
-       for (i = 0; i < LPFC_MSIX_VECTORS; i++)
-               phba->msix_entries[i].entry = i;
-
-       /* Configure MSI-X capability structure */
-       rc = pci_enable_msix_exact(phba->pcidev, phba->msix_entries,
-                                  LPFC_MSIX_VECTORS);
-       if (rc) {
+       rc = pci_alloc_irq_vectors(phba->pcidev,
+                       LPFC_MSIX_VECTORS, LPFC_MSIX_VECTORS, PCI_IRQ_MSIX);
+       if (rc < 0) {
                lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
                                "0420 PCI enable MSI-X failed (%d)\n", rc);
                goto vec_fail_out;
        }
-       for (i = 0; i < LPFC_MSIX_VECTORS; i++)
-               lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-                               "0477 MSI-X entry[%d]: vector=x%x "
-                               "message=%d\n", i,
-                               phba->msix_entries[i].vector,
-                               phba->msix_entries[i].entry);
+
        /*
         * Assign MSI-X vectors to interrupt handlers
         */
 
        /* vector-0 is associated to slow-path handler */
-       rc = request_irq(phba->msix_entries[0].vector,
+       rc = request_irq(pci_irq_vector(phba->pcidev, 0),
                         &lpfc_sli_sp_intr_handler, 0,
                         LPFC_SP_DRIVER_HANDLER_NAME, phba);
        if (rc) {
@@ -8539,7 +8505,7 @@ lpfc_sli_enable_msix(struct lpfc_hba *phba)
        }
 
        /* vector-1 is associated to fast-path handler */
-       rc = request_irq(phba->msix_entries[1].vector,
+       rc = request_irq(pci_irq_vector(phba->pcidev, 1),
                         &lpfc_sli_fp_intr_handler, 0,
                         LPFC_FP_DRIVER_HANDLER_NAME, phba);
 
@@ -8584,41 +8550,20 @@ mbx_fail_out:
 
 mem_fail_out:
        /* free the irq already requested */
-       free_irq(phba->msix_entries[1].vector, phba);
+       free_irq(pci_irq_vector(phba->pcidev, 1), phba);
 
 irq_fail_out:
        /* free the irq already requested */
-       free_irq(phba->msix_entries[0].vector, phba);
+       free_irq(pci_irq_vector(phba->pcidev, 0), phba);
 
 msi_fail_out:
        /* Unconfigure MSI-X capability structure */
-       pci_disable_msix(phba->pcidev);
+       pci_free_irq_vectors(phba->pcidev);
 
 vec_fail_out:
        return rc;
 }
 
-/**
- * lpfc_sli_disable_msix - Disable MSI-X interrupt mode on SLI-3 device.
- * @phba: pointer to lpfc hba data structure.
- *
- * This routine is invoked to release the MSI-X vectors and then disable the
- * MSI-X interrupt mode to device with SLI-3 interface spec.
- **/
-static void
-lpfc_sli_disable_msix(struct lpfc_hba *phba)
-{
-       int i;
-
-       /* Free up MSI-X multi-message vectors */
-       for (i = 0; i < LPFC_MSIX_VECTORS; i++)
-               free_irq(phba->msix_entries[i].vector, phba);
-       /* Disable MSI-X */
-       pci_disable_msix(phba->pcidev);
-
-       return;
-}
-
 /**
  * lpfc_sli_enable_msi - Enable MSI interrupt mode on SLI-3 device.
  * @phba: pointer to lpfc hba data structure.
@@ -8658,24 +8603,6 @@ lpfc_sli_enable_msi(struct lpfc_hba *phba)
        return rc;
 }
 
-/**
- * lpfc_sli_disable_msi - Disable MSI interrupt mode to SLI-3 device.
- * @phba: pointer to lpfc hba data structure.
- *
- * This routine is invoked to disable the MSI interrupt mode to device with
- * SLI-3 interface spec. The driver calls free_irq() on MSI vector it has
- * done request_irq() on before calling pci_disable_msi(). Failure to do so
- * results in a BUG_ON() and a device will be left with MSI enabled and leaks
- * its vector.
- */
-static void
-lpfc_sli_disable_msi(struct lpfc_hba *phba)
-{
-       free_irq(phba->pcidev->irq, phba);
-       pci_disable_msi(phba->pcidev);
-       return;
-}
-
 /**
  * lpfc_sli_enable_intr - Enable device interrupt to SLI-3 device.
  * @phba: pointer to lpfc hba data structure.
@@ -8747,19 +8674,20 @@ lpfc_sli_enable_intr(struct lpfc_hba *phba, uint32_t cfg_mode)
 static void
 lpfc_sli_disable_intr(struct lpfc_hba *phba)
 {
-       /* Disable the currently initialized interrupt mode */
+       int nr_irqs, i;
+
        if (phba->intr_type == MSIX)
-               lpfc_sli_disable_msix(phba);
-       else if (phba->intr_type == MSI)
-               lpfc_sli_disable_msi(phba);
-       else if (phba->intr_type == INTx)
-               free_irq(phba->pcidev->irq, phba);
+               nr_irqs = LPFC_MSIX_VECTORS;
+       else
+               nr_irqs = 1;
+
+       for (i = 0; i < nr_irqs; i++)
+               free_irq(pci_irq_vector(phba->pcidev, i), phba);
+       pci_free_irq_vectors(phba->pcidev);
 
        /* Reset interrupt management states */
        phba->intr_type = NONE;
        phba->sli.slistat.sli_intr = 0;
-
-       return;
 }
 
 /**
@@ -8915,7 +8843,7 @@ found:
                        lpfc_used_cpu[cpu] = phys_id;
 
                /* Associate vector with selected CPU */
-               cpup->irq = phba->sli4_hba.msix_entries[idx].vector;
+               cpup->irq = pci_irq_vector(phba->pcidev, idx);
 
                /* Associate IO channel with selected CPU */
                cpup->channel_id = idx;
@@ -8925,14 +8853,14 @@ found:
                        first_cpu = cpu;
 
                /* Now affinitize to the selected CPU */
-               i = irq_set_affinity_hint(phba->sli4_hba.msix_entries[idx].
-                                         vector, get_cpu_mask(cpu));
+               i = irq_set_affinity_hint(pci_irq_vector(phba->pcidev, idx),
+                                         get_cpu_mask(cpu));
 
                lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
                                "3330 Set Affinity: CPU %d channel %d "
                                "irq %d (%x)\n",
                                cpu, cpup->channel_id,
-                               phba->sli4_hba.msix_entries[idx].vector, i);
+                               pci_irq_vector(phba->pcidev, idx), i);
 
                /* Spread vector mapping across multple physical CPU nodes */
                phys_id++;
@@ -9047,14 +8975,7 @@ out:
  * @phba: pointer to lpfc hba data structure.
  *
  * This routine is invoked to enable the MSI-X interrupt vectors to device
- * with SLI-4 interface spec. The kernel function pci_enable_msix_range()
- * is called to enable the MSI-X vectors. The device driver is responsible
- * for calling the individual request_irq() to register each MSI-X vector
- * with a interrupt handler, which is done in this function. Note that
- * later when device is unloading, the driver should always call free_irq()
- * on all MSI-X vectors it has done request_irq() on before calling
- * pci_disable_msix(). Failure to do so results in a BUG_ON() and a device
- * will be left with MSI-X enabled and leaks its vectors.
+ * with SLI-4 interface spec.
  *
  * Return codes
  * 0 - successful
@@ -9066,17 +8987,11 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba)
        int vectors, rc, index;
 
        /* Set up MSI-X multi-message vectors */
-       for (index = 0; index < phba->cfg_fcp_io_channel; index++)
-               phba->sli4_hba.msix_entries[index].entry = index;
-
-       /* Configure MSI-X capability structure */
        vectors = phba->cfg_fcp_io_channel;
-       if (phba->cfg_fof) {
-               phba->sli4_hba.msix_entries[index].entry = index;
+       if (phba->cfg_fof)
                vectors++;
-       }
-       rc = pci_enable_msix_range(phba->pcidev, phba->sli4_hba.msix_entries,
-                                  2, vectors);
+
+       rc = pci_alloc_irq_vectors(phba->pcidev, 2, vectors, PCI_IRQ_MSIX);
        if (rc < 0) {
                lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
                                "0484 PCI enable MSI-X failed (%d)\n", rc);
@@ -9084,14 +8999,6 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba)
        }
        vectors = rc;
 
-       /* Log MSI-X vector assignment */
-       for (index = 0; index < vectors; index++)
-               lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-                               "0489 MSI-X entry[%d]: vector=x%x "
-                               "message=%d\n", index,
-                               phba->sli4_hba.msix_entries[index].vector,
-                               phba->sli4_hba.msix_entries[index].entry);
-
        /* Assign MSI-X vectors to interrupt handlers */
        for (index = 0; index < vectors; index++) {
                memset(&phba->sli4_hba.handler_name[index], 0, 16);
@@ -9103,14 +9010,12 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba)
                phba->sli4_hba.fcp_eq_hdl[index].phba = phba;
                atomic_set(&phba->sli4_hba.fcp_eq_hdl[index].fcp_eq_in_use, 1);
                if (phba->cfg_fof && (index == (vectors - 1)))
-                       rc = request_irq(
-                               phba->sli4_hba.msix_entries[index].vector,
+                       rc = request_irq(pci_irq_vector(phba->pcidev, index),
                                 &lpfc_sli4_fof_intr_handler, 0,
                                 (char *)&phba->sli4_hba.handler_name[index],
                                 &phba->sli4_hba.fcp_eq_hdl[index]);
                else
-                       rc = request_irq(
-                               phba->sli4_hba.msix_entries[index].vector,
+                       rc = request_irq(pci_irq_vector(phba->pcidev, index),
                                 &lpfc_sli4_hba_intr_handler, 0,
                                 (char *)&phba->sli4_hba.handler_name[index],
                                 &phba->sli4_hba.fcp_eq_hdl[index]);
@@ -9140,48 +9045,19 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba)
 cfg_fail_out:
        /* free the irq already requested */
        for (--index; index >= 0; index--) {
-               irq_set_affinity_hint(phba->sli4_hba.msix_entries[index].
-                                         vector, NULL);
-               free_irq(phba->sli4_hba.msix_entries[index].vector,
-                        &phba->sli4_hba.fcp_eq_hdl[index]);
+               int irq = pci_irq_vector(phba->pcidev, index);
+
+               irq_set_affinity_hint(irq, NULL);
+               free_irq(irq, &phba->sli4_hba.fcp_eq_hdl[index]);
        }
 
        /* Unconfigure MSI-X capability structure */
-       pci_disable_msix(phba->pcidev);
+       pci_free_irq_vectors(phba->pcidev);
 
 vec_fail_out:
        return rc;
 }
 
-/**
- * lpfc_sli4_disable_msix - Disable MSI-X interrupt mode to SLI-4 device
- * @phba: pointer to lpfc hba data structure.
- *
- * This routine is invoked to release the MSI-X vectors and then disable the
- * MSI-X interrupt mode to device with SLI-4 interface spec.
- **/
-static void
-lpfc_sli4_disable_msix(struct lpfc_hba *phba)
-{
-       int index;
-
-       /* Free up MSI-X multi-message vectors */
-       for (index = 0; index < phba->cfg_fcp_io_channel; index++) {
-               irq_set_affinity_hint(phba->sli4_hba.msix_entries[index].
-                                         vector, NULL);
-               free_irq(phba->sli4_hba.msix_entries[index].vector,
-                        &phba->sli4_hba.fcp_eq_hdl[index]);
-       }
-       if (phba->cfg_fof) {
-               free_irq(phba->sli4_hba.msix_entries[index].vector,
-                        &phba->sli4_hba.fcp_eq_hdl[index]);
-       }
-       /* Disable MSI-X */
-       pci_disable_msix(phba->pcidev);
-
-       return;
-}
-
 /**
  * lpfc_sli4_enable_msi - Enable MSI interrupt mode to SLI-4 device
  * @phba: pointer to lpfc hba data structure.
@@ -9232,24 +9108,6 @@ lpfc_sli4_enable_msi(struct lpfc_hba *phba)
        return 0;
 }
 
-/**
- * lpfc_sli4_disable_msi - Disable MSI interrupt mode to SLI-4 device
- * @phba: pointer to lpfc hba data structure.
- *
- * This routine is invoked to disable the MSI interrupt mode to device with
- * SLI-4 interface spec. The driver calls free_irq() on MSI vector it has
- * done request_irq() on before calling pci_disable_msi(). Failure to do so
- * results in a BUG_ON() and a device will be left with MSI enabled and leaks
- * its vector.
- **/
-static void
-lpfc_sli4_disable_msi(struct lpfc_hba *phba)
-{
-       free_irq(phba->pcidev->irq, phba);
-       pci_disable_msi(phba->pcidev);
-       return;
-}
-
 /**
  * lpfc_sli4_enable_intr - Enable device interrupt to SLI-4 device
  * @phba: pointer to lpfc hba data structure.
@@ -9335,18 +9193,28 @@ static void
 lpfc_sli4_disable_intr(struct lpfc_hba *phba)
 {
        /* Disable the currently initialized interrupt mode */
-       if (phba->intr_type == MSIX)
-               lpfc_sli4_disable_msix(phba);
-       else if (phba->intr_type == MSI)
-               lpfc_sli4_disable_msi(phba);
-       else if (phba->intr_type == INTx)
+       if (phba->intr_type == MSIX) {
+               int index;
+
+               /* Free up MSI-X multi-message vectors */
+               for (index = 0; index < phba->cfg_fcp_io_channel; index++) {
+                       int irq = pci_irq_vector(phba->pcidev, index);
+
+                       irq_set_affinity_hint(irq, NULL);
+                       free_irq(irq, &phba->sli4_hba.fcp_eq_hdl[index]);
+               }
+
+               if (phba->cfg_fof)
+                       free_irq(pci_irq_vector(phba->pcidev, index), phba);
+       } else {
                free_irq(phba->pcidev->irq, phba);
+       }
+
+       pci_free_irq_vectors(phba->pcidev);
 
        /* Reset interrupt management states */
        phba->intr_type = NONE;
        phba->sli.slistat.sli_intr = 0;
-
-       return;
 }
 
 /**
index 0b88b5703e0f10b835e79981594cc6a606e401f4..dfbb25e5c5b68bf5a72b95827139a5d350b8d12a 100644 (file)
@@ -515,7 +515,6 @@ struct lpfc_sli4_hba {
        uint32_t ue_to_rp;
        struct lpfc_register sli_intf;
        struct lpfc_pc_sli4_params pc_sli4_params;
-       struct msix_entry *msix_entries;
        uint8_t handler_name[LPFC_SLI4_HANDLER_CNT][LPFC_SLI4_HANDLER_NAME_SZ];
        struct lpfc_fcp_eq_hdl *fcp_eq_hdl; /* FCP per-WQ handle */