Commit 45ffac19 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Martin K. Petersen

scsi: lpfc: use pci_irq_alloc_vectors and pci_irq_free_vectors

This avoids having to store the msix_entries array and simpliefies the
shutdown and cleanup path a lot.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJames Smart <james.smart@broadcom.com>
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 8ea73db4
......@@ -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 */
......
......@@ -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 @@ lpfc_sli_enable_msix(struct lpfc_hba *phba)
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 @@ lpfc_sli4_set_affinity(struct lpfc_hba *phba, int vectors)
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 @@ lpfc_sli4_set_affinity(struct lpfc_hba *phba, int vectors)
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 @@ lpfc_sli4_set_affinity(struct lpfc_hba *phba, int vectors)
* @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;
}
/**
......
......@@ -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 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment