From: Alexander Gordeev <hidden> Date: 2013-10-02 17:33:24
This series is against "next" branch in Bjorn's repo:
git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
Currently pci_enable_msi_block() and pci_enable_msix() interfaces
return a error code in case of failure, 0 in case of success and a
positive value which indicates the number of MSI-X/MSI interrupts
that could have been allocated. The latter value should be passed
to a repeated call to the interfaces until a failure or success:
for (i = 0; i < FOO_DRIVER_MAXIMUM_NVEC; i++)
adapter->msix_entries[i].entry = i;
while (nvec >= FOO_DRIVER_MINIMUM_NVEC) {
rc = pci_enable_msix(adapter->pdev,
adapter->msix_entries, nvec);
if (rc > 0)
nvec = rc;
else
return rc;
}
return -ENOSPC;
This technique proved to be confusing and error-prone. Vast share
of device drivers simply fail to follow the described guidelines.
This update converts pci_enable_msix() and pci_enable_msi_block()
interfaces to canonical kernel functions and makes them return a
error code in case of failure or 0 in case of success.
As result, device drivers will cease to use the overcomplicated
repeated fallbacks technique and resort to a straightforward
pattern - determine the number of MSI/MSI-X interrupts required
before calling pci_enable_msi_block() and pci_enable_msix()
interfaces:
rc = pci_msix_table_size(adapter->pdev);
if (rc < 0)
return rc;
nvec = min(nvec, rc);
if (nvec < FOO_DRIVER_MINIMUM_NVEC) {
return -ENOSPC;
for (i = 0; i < nvec; i++)
adapter->msix_entries[i].entry = i;
rc = pci_enable_msix(adapter->pdev,
adapter->msix_entries, nvec);
return rc;
Device drivers will use their knowledge of underlying hardware
to determine the number of MSI/MSI-X interrupts required.
The simplest case would be requesting all available interrupts -
to obtain that value device drivers will use pci_get_msi_cap()
interface for MSI and pci_msix_table_size() for MSI-X.
More complex cases would entail matching device capabilities
to the system environment, i.e. limiting number of hardware
queues (and hence associated MSI/MSI-X interrupts) to the number
of online CPUs.
Device drivers using MSI/MSI-X could be divided in three groups:
- drivers that request a hardcoded number of interrupts;
- drivers that request a number of interrupts using one call to
pci_enable_msix() and then enable MSI/MSI-X using a follow-up
to pci_enable_msix();
- drivers that fully follow the guidelines and repeatedly call
pci_enable_msix() in a loop;
This series converts to the new technique second and third groups.
To simplify device drivers code review I tried to make as little
changes as possible - the scope of this series is an introduction
of the new technique rather than clean-up effort for all drivers
affected.
The testing was very limited - I ensured successful booting on
all affected architectures except MIPS and operation of few
devices with and without pci=nomsi kernel parameter.
There is a ongoing discussion about impact of this update on
PowerPC pSeries platform. I am going to incorporate the outcome
of this discussion into the next version. Yet, the rest of the
platforms and the vast majority of device drivers already can
start getting initial reviews.
Patches 5,6,8 - update of the generic MSI code
Patch 7 - update of architectures affected
Patches 9-77 - bugfixes and updates of device drivers affected
The tree could be found in "pci-next-msi-v1" branch in repo:
https://github.com/a-gordeev/linux.git
Alexander Gordeev (77):
PCI/MSI: Fix return value when populate_msi_sysfs() failed
PCI/MSI/PPC: Fix wrong RTAS error code reporting
PCI/MSI/s390: Fix single MSI only check
PCI/MSI/s390: Remove superfluous check of MSI type
PCI/MSI: Convert pci_msix_table_size() to a public interface
PCI/MSI: Factor out pci_get_msi_cap() interface
PCI/MSI: Re-design MSI/MSI-X interrupts enablement pattern
PCI/MSI: Get rid of pci_enable_msi_block_auto() interface
ahci: Update MSI/MSI-X interrupts enablement code
ahci: Check MRSM bit when multiple MSIs enabled
benet: Return -ENOSPC when not enough MSI-Xs available
benet: Update MSI/MSI-X interrupts enablement code
bna: Update MSI/MSI-X interrupts enablement code
bnx2x: Update MSI/MSI-X interrupts enablement code
bnx2: Update MSI/MSI-X interrupts enablement code
cciss: Update MSI/MSI-X interrupts enablement code
cciss: Update a misleading comment on interrupt usage
cciss: Fallback to single MSI mode in case MSI-X failed
csiostor: Do not call pci_disable_msix() if pci_enable_msix() failed
csiostor: Return -ENOSPC when not enough MSI-X vectors available
csiostor: Update MSI/MSI-X interrupts enablement code
cxgb3: Do not call pci_disable_msix() if pci_enable_msix() failed
cxgb3: Return -ENOSPC when not enough MSI-X vectors available
cxgb3: Update MSI/MSI-X interrupts enablement code
cxgb4: Return -ENOSPC when not enough MSI-X vectors available
cxgb4: Update MSI/MSI-X interrupts enablement code
cxgb4vf: Do not call pci_disable_msix() if pci_enable_msix() failed
cxgb4vf: Return -ENOSPC when not enough MSI-X vectors available
cxgb4vf: Update MSI/MSI-X interrupts enablement code
hpsa: Update a misleading comment on interrupt usage
hpsa: Update MSI/MSI-X interrupts enablement code
hpsa: Fallback to single MSI mode in case MSI-X failed
ioat: Disable MSI-X in case request of IRQ failed
ioat: Update MSI/MSI-X interrupts enablement code
ipr: Do not call pci_disable_msi/msix() if pci_enable_msi/msix()
failed
ipr: Enable MSI-X when IPR_USE_MSIX type is set, not IPR_USE_MSI
ipr: Update MSI/MSI-X interrupts enablement code
ixgbe: Update MSI/MSI-X interrupts enablement code
ixgbevf: Return -ENOSPC when not enough MSI-X vectors available
ixgbevf: Update MSI/MSI-X interrupts enablement code
lpfc: Do not call pci_disable_msix() if pci_enable_msix() failed
lpfc: Update MSI/MSI-X interrupts enablement code
lpfc: Return -ENOSPC when not enough MSI-X vectors available
lpfc: Make MSI-X initialization routine more readable
megaraid: Update MSI/MSI-X interrupts enablement code
mlx4: Update MSI/MSI-X interrupts enablement code
mlx5: Fix memory leak in case not enough MSI-X vectors available
mlx5: Return -ENOSPC when not enough MSI-X vectors available
mlx5: Fix minimum number of MSI-Xs
mlx5: Update MSI/MSI-X interrupts enablement code
mthca: Update MSI/MSI-X interrupts enablement code
niu: Update MSI/MSI-X interrupts enablement code
ntb: Fix missed call to pci_enable_msix()
ntb: Ensure number of MSIs on SNB is enough for the link interrupt
ntb: Update MSI/MSI-X interrupts enablement code
nvme: Update MSI/MSI-X interrupts enablement code
pmcraid: Update MSI/MSI-X interrupts enablement code
qib: Update MSI/MSI-X interrupts enablement code
qla2xxx: Update MSI/MSI-X interrupts enablement code
qlcnic: Return -ENOSPC when not enough MSI-X vectors available
qlogic: Return -EINVAL in case MSI-X is not supported
qlcnic: Remove redundant return operator
qlcnic: Update MSI/MSI-X interrupts enablement code
qlcnic: Make MSI-X initialization routine bit more readable
qlge: Remove a redundant assignment
qlge: Update MSI/MSI-X interrupts enablement code
rapidio: Update MSI/MSI-X interrupts enablement code
sfc: Update MSI/MSI-X interrupts enablement code
tg3: Update MSI/MSI-X interrupts enablement code
vmci: Update MSI/MSI-X interrupts enablement code
vmxnet3: Return -EINVAL if number of requested MSI-Xs is not enough
vmxnet3: Fixup a weird loop exit
vmxnet3: Return -ENOSPC when not enough MSI-X vectors available
vmxnet3: Limit number of rx queues to 1 if per-queue MSI-Xs failed
vmxnet3: Update MSI/MSI-X interrupts enablement code
vxge: Sanitize MSI-X allocation routine error codes
vxge: Update MSI/MSI-X interrupts enablement code
Documentation/PCI/MSI-HOWTO.txt | 123 +++++++++++---------
arch/mips/pci/msi-octeon.c | 2 +-
arch/powerpc/kernel/msi.c | 2 +-
arch/powerpc/platforms/pseries/msi.c | 4 +-
arch/s390/pci/pci.c | 2 +-
arch/x86/kernel/apic/io_apic.c | 2 +-
drivers/ata/ahci.c | 71 ++++++++---
drivers/ata/ahci.h | 1 +
drivers/block/cciss.c | 22 ++--
drivers/block/nvme-core.c | 48 ++++----
drivers/dma/ioat/dma.c | 11 ++-
drivers/infiniband/hw/mthca/mthca_main.c | 16 ++-
drivers/infiniband/hw/qib/qib_pcie.c | 4 -
drivers/misc/vmw_vmci/vmci_guest.c | 22 +++-
drivers/net/ethernet/broadcom/bnx2.c | 27 +++--
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 54 ++++-----
drivers/net/ethernet/broadcom/tg3.c | 24 ++--
drivers/net/ethernet/brocade/bna/bnad.c | 34 +++---
drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c | 32 +++---
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 62 ++++++----
.../net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 49 +++++---
drivers/net/ethernet/emulex/benet/be_main.c | 36 +++---
drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c | 62 +++++-----
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 18 +--
drivers/net/ethernet/mellanox/mlx4/main.c | 17 ++--
drivers/net/ethernet/mellanox/mlx5/core/main.c | 17 ++--
drivers/net/ethernet/neterion/vxge/vxge-main.c | 38 +++----
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 108 +++++++++--------
drivers/net/ethernet/qlogic/qlge/qlge_main.c | 40 +++----
drivers/net/ethernet/sfc/efx.c | 18 ++-
drivers/net/ethernet/sun/niu.c | 20 ++--
drivers/net/vmxnet3/vmxnet3_drv.c | 84 +++++++-------
drivers/ntb/ntb_hw.c | 37 ++----
drivers/ntb/ntb_hw.h | 2 -
drivers/pci/msi.c | 93 +++++----------
drivers/pci/pcie/portdrv_core.c | 2 +
drivers/rapidio/devices/tsi721.c | 27 +++--
drivers/scsi/csiostor/csio_isr.c | 20 ++--
drivers/scsi/hpsa.c | 35 +++---
drivers/scsi/ipr.c | 52 ++++-----
drivers/scsi/lpfc/lpfc_init.c | 40 ++++---
drivers/scsi/megaraid/megaraid_sas_base.c | 20 ++--
drivers/scsi/pmcraid.c | 23 ++--
drivers/scsi/qla2xxx/qla_isr.c | 18 ++-
include/linux/pci.h | 7 +-
45 files changed, 744 insertions(+), 702 deletions(-)
--
1.7.7.6
From: Alexander Gordeev <hidden> Date: 2013-10-02 16:34:40
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/net/ethernet/sun/niu.c | 20 +++++++++++---------
1 files changed, 11 insertions(+), 9 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 16:36:26
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/infiniband/hw/mthca/mthca_main.c | 16 +++++++++++-----
1 files changed, 11 insertions(+), 5 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 16:38:01
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/misc/vmw_vmci/vmci_guest.c | 22 +++++++++++++++-------
1 files changed, 15 insertions(+), 7 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 16:39:53
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/scsi/qla2xxx/qla_isr.c | 18 +++++++++++-------
1 files changed, 11 insertions(+), 7 deletions(-)
@@ -2836,16 +2836,20 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)for(i=0;i<ha->msix_count;i++)entries[i].entry=i;-ret=pci_enable_msix(ha->pdev,entries,ha->msix_count);-if(ret){+ret=pci_msix_table_size(ha->pdev);+if(ret<0){+gotomsix_failed;+}else{if(ret<MIN_MSIX_COUNT)gotomsix_failed;-ql_log(ql_log_warn,vha,0x00c6,-"MSI-X: Failed to enable support "-"-- %d/%d\n Retry with %d vectors.\n",-ha->msix_count,ret,ret);-ha->msix_count=ret;+if(ret<ha->msix_count){+ql_log(ql_log_warn,vha,0x00c6,+"MSI-X: Failed to enable support "+"-- %d/%d\n Retry with %d vectors.\n",+ha->msix_count,ret,ret);+ha->msix_count=ret;+}ret=pci_enable_msix(ha->pdev,entries,ha->msix_count);if(ret){msix_failed:
From: Alexander Gordeev <hidden> Date: 2013-10-02 16:41:18
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/scsi/megaraid/megaraid_sas_base.c | 20 +++++++++-----------
1 files changed, 9 insertions(+), 11 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 16:42:51
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/net/ethernet/broadcom/bnx2.c | 27 ++++++++++++++-------------
1 files changed, 14 insertions(+), 13 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 16:44:31
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Note, in case just one MSI-X vector was available the
error message "0484 PCI enable MSI-X failed 1" is
preserved to not break tools which might depend on it.
Also, not sure why in case of multiple MSI-Xs mode failed
the driver skips the single MSI-X mode and falls back to
single MSI mode.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/scsi/lpfc/lpfc_init.c | 18 +++++++++++-------
1 files changed, 11 insertions(+), 7 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 16:46:18
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/net/ethernet/mellanox/mlx4/main.c | 17 ++++++++---------
1 files changed, 8 insertions(+), 9 deletions(-)
@@ -1852,8 +1852,16 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)inti;if(msi_x){+err=pci_msix_table_size(dev->pdev);+if(err<0)+gotono_msi;++/* Try if at least 2 vectors are available */nreq=min_t(int,dev->caps.num_eqs-dev->caps.reserved_eqs,nreq);+nreq=min_t(int,nreq,err);+if(nreq<2)+gotono_msi;entries=kcalloc(nreq,sizeof*entries,GFP_KERNEL);if(!entries)
@@ -1862,17 +1870,8 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)for(i=0;i<nreq;++i)entries[i].entry=i;-retry:err=pci_enable_msix(dev->pdev,entries,nreq);if(err){-/* Try again if at least 2 vectors are available */-if(err>1){-mlx4_info(dev,"Requested %d vectors, "-"but only %d MSI-X vectors available, "-"trying again\n",nreq,err);-nreq=err;-gotoretry;-}kfree(entries);gotono_msi;}
From: Alexander Gordeev <hidden> Date: 2013-10-02 16:47:46
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/block/cciss.c | 17 +++++++----------
1 files changed, 7 insertions(+), 10 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 16:50:16
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/scsi/pmcraid.c | 23 +++++++++++------------
1 files changed, 11 insertions(+), 12 deletions(-)
@@ -4680,24 +4680,23 @@ pmcraid_register_interrupt_handler(struct pmcraid_instance *pinstance)if((pmcraid_enable_msix)&&(pci_find_capability(pdev,PCI_CAP_ID_MSIX))){-intnum_hrrq=PMCRAID_NUM_MSIX_VECTORS;structmsix_entryentries[PMCRAID_NUM_MSIX_VECTORS];+intnum_hrrq=ARRAY_SIZE(entries);inti;-for(i=0;i<PMCRAID_NUM_MSIX_VECTORS;i++)-entries[i].entry=i;--rc=pci_enable_msix(pdev,entries,num_hrrq);-if(rc<0)-gotopmcraid_isr_legacy;/* Check how many MSIX vectors are allocated and register*msi-xhandlersforeachofthemgivingappropriatebuffer*/-if(rc>0){-num_hrrq=rc;-if(pci_enable_msix(pdev,entries,num_hrrq))-gotopmcraid_isr_legacy;-}+rc=pci_msix_table_size(pdev);+if(rc<0)+gotopmcraid_isr_legacy;++num_hrrq=min(num_hrrq,rc);+for(i=0;i<num_hrrq;i++)+entries[i].entry=i;++if(pci_enable_msix(pdev,entries,num_hrrq))+gotopmcraid_isr_legacy;for(i=0;i<num_hrrq;i++){pinstance->hrrq_vector[i].hrrq_id=i;
From: Alexander Gordeev <hidden> Date: 2013-10-02 16:51:50
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/scsi/csiostor/csio_isr.c | 18 ++++++++++++------
1 files changed, 12 insertions(+), 6 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 16:54:07
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c | 29 ++++++++++++-----------
1 files changed, 15 insertions(+), 14 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 16:55:44
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/net/ethernet/mellanox/mlx5/core/main.c | 18 +++++++++---------
1 files changed, 9 insertions(+), 9 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 16:57:25
Do not trust the hardware and always check if MSI
Revert to Single Message mode was enforced. Fall
back to the single MSI mode in case it did. Not
doing so might screw up the interrupt handling.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/ata/ahci.c | 17 +++++++++++++++++
drivers/ata/ahci.h | 1 +
2 files changed, 18 insertions(+), 0 deletions(-)
@@ -1116,6 +1124,15 @@ int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,if(rc)gotointx;+/*+*FallbacktosingleMSImodeifthecontrollerenforcedMRSMmode+*/+if(ahci_get_mrsm(hpriv)){+pci_disable_msi(pdev);+printk(KERN_INFO"ahci: MRSM is on, fallback to single MSI\n");+gotosingle_msi;+}+returnnvec;single_msi:
From: Alexander Gordeev <hidden> Date: 2013-10-02 16:59:13
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 18 +++++++-----------
1 files changed, 7 insertions(+), 11 deletions(-)
@@ -1749,8 +1749,7 @@ void ixgbevf_reset(struct ixgbevf_adapter *adapter)staticintixgbevf_acquire_msix_vectors(structixgbevf_adapter*adapter,intvectors){-interr=0;-intvector_threshold;+interr,vector_threshold;/* We'll want at least 2 (vector_threshold):*1)TxQ[0]+RxQ[0]handler
@@ -1763,18 +1762,15 @@ static int ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter,*Rightnow,wesimplycareabouthowmanywe'llget;we'll*setthemuplaterwhilerequestingirq's.*/-while(vectors>=vector_threshold){-err=pci_enable_msix(adapter->pdev,adapter->msix_entries,-vectors);-if(!err||err<0)/* Success or a nasty failure. */-break;-else/* err == number of vectors we should try again with */-vectors=err;-}+err=pci_msix_table_size(adapter->pdev);+if(err<0)+returnerr;+vectors=min(vectors,err);if(vectors<vector_threshold)-err=-ENOSPC;+return-ENOSPC;+err=pci_enable_msix(adapter->pdev,adapter->msix_entries,vectors);if(err){dev_err(&adapter->pdev->dev,"Unable to allocate MSI-X interrupts\n");
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:00:35
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/rapidio/devices/tsi721.c | 27 +++++++++++++++++----------
1 files changed, 17 insertions(+), 10 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:02:14
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/net/ethernet/sfc/efx.c | 18 +++++++++++-------
1 files changed, 11 insertions(+), 7 deletions(-)
@@ -1261,21 +1261,24 @@ static int efx_probe_interrupts(struct efx_nic *efx)n_channels+=extra_channels;n_channels=min(n_channels,efx->max_channels);-for(i=0;i<n_channels;i++)-xentries[i].entry=i;-rc=pci_enable_msix(efx->pci_dev,xentries,n_channels);-if(rc>0){+rc=pci_msix_table_size(efx->pci_dev);+if(rc<0)+gotomsi;++if(rc<n_channels){netif_err(efx,drv,efx->net_dev,"WARNING: Insufficient MSI-X vectors"" available (%d < %u).\n",rc,n_channels);netif_err(efx,drv,efx->net_dev,"WARNING: Performance may be reduced.\n");-EFX_BUG_ON_PARANOID(rc>=n_channels);n_channels=rc;-rc=pci_enable_msix(efx->pci_dev,xentries,-n_channels);}+EFX_BUG_ON_PARANOID(n_channels>ARRAY_SIZE(xentries));+for(i=0;i<n_channels;i++)+xentries[i].entry=i;++rc=pci_enable_msix(efx->pci_dev,xentries,n_channels);if(rc==0){efx->n_channels=n_channels;if(n_channels>extra_channels)
@@ -1293,6 +1296,7 @@ static int efx_probe_interrupts(struct efx_nic *efx)efx_get_channel(efx,i)->irq=xentries[i].vector;}else{+msi:/* Fall back to single channel MSI */efx->interrupt_mode=EFX_INT_MODE_MSI;netif_err(efx,drv,efx->net_dev,
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:04:24
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/net/ethernet/broadcom/tg3.c | 24 +++++++++++++-----------
1 files changed, 13 insertions(+), 11 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:06:55
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/block/nvme-core.c | 48 +++++++++++++++++++++++---------------------
1 files changed, 25 insertions(+), 23 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:09:13
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/net/ethernet/neterion/vxge/vxge-main.c | 36 ++++++++++-------------
1 files changed, 16 insertions(+), 20 deletions(-)
@@ -2297,7 +2297,21 @@ static int vxge_alloc_msix(struct vxgedev *vdev)intmsix_intr_vect=0,temp;vdev->intr_cnt=0;-start:+ret=pci_msix_table_size(vdev->pdev);+if(ret<0)+gotoalloc_entries_failed;++if(ret<(vdev->no_of_vpath*2+1)){+if((max_config_vpath!=VXGE_USE_DEFAULT)||(ret<3)){+ret=-ENOSPC;+gotoalloc_entries_failed;+}+/* Try with less no of vector by reducing no of vpaths count */+temp=(ret-1)/2;+vxge_close_vpaths(vdev,temp);+vdev->no_of_vpath=temp;+}+/* Tx/Rx MSIX Vectors count */vdev->intr_cnt=vdev->no_of_vpath*2;
@@ -2347,25 +2361,7 @@ start:vdev->vxge_entries[j].in_use=0;ret=pci_enable_msix(vdev->pdev,vdev->entries,vdev->intr_cnt);-if(ret>0){-vxge_debug_init(VXGE_ERR,-"%s: MSI-X enable failed for %d vectors, ret: %d",-VXGE_DRIVER_NAME,vdev->intr_cnt,ret);-if((max_config_vpath!=VXGE_USE_DEFAULT)||(ret<3)){-ret=-ENOSPC;-gotoenable_msix_failed;-}--kfree(vdev->entries);-kfree(vdev->vxge_entries);-vdev->entries=NULL;-vdev->vxge_entries=NULL;-/* Try with less no of vector by reducing no of vpaths count */-temp=(ret-1)/2;-vxge_close_vpaths(vdev,temp);-vdev->no_of_vpath=temp;-gotostart;-}elseif(ret<0)+if(ret)gotoenable_msix_failed;return0;
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:11:04
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/scsi/hpsa.c | 28 +++++++++++++---------------
1 files changed, 13 insertions(+), 15 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:12:59
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/net/ethernet/brocade/bna/bnad.c | 34 ++++++++++++------------------
1 files changed, 14 insertions(+), 20 deletions(-)
@@ -2469,21 +2469,11 @@ bnad_enable_msix(struct bnad *bnad)if(bnad->msix_table)return;-bnad->msix_table=-kcalloc(bnad->msix_num,sizeof(structmsix_entry),GFP_KERNEL);--if(!bnad->msix_table)+ret=pci_msix_table_size(bnad->pcidev);+if(ret<0)gotointx_mode;-for(i=0;i<bnad->msix_num;i++)-bnad->msix_table[i].entry=i;--ret=pci_enable_msix(bnad->pcidev,bnad->msix_table,bnad->msix_num);-if(ret>0){-/* Not enough MSI-X vectors. */-pr_warn("BNA: %d MSI-X vectors allocated < %d requested\n",-ret,bnad->msix_num);-+if(ret<bnad->msix_num){spin_lock_irqsave(&bnad->bna_lock,flags);/* ret = #of vectors that we got */bnad_q_num_adjust(bnad,(ret-BNAD_MAILBOX_MSIX_VECTORS)/2,
@@ -2495,15 +2485,19 @@ bnad_enable_msix(struct bnad *bnad)if(bnad->msix_num>ret)gotointx_mode;+}-/* Try once more with adjusted numbers */-/* If this fails, fall back to INTx */-ret=pci_enable_msix(bnad->pcidev,bnad->msix_table,-bnad->msix_num);-if(ret)-gotointx_mode;+bnad->msix_table=+kcalloc(bnad->msix_num,sizeof(structmsix_entry),GFP_KERNEL);++if(!bnad->msix_table)+gotointx_mode;-}elseif(ret<0)+for(i=0;i<bnad->msix_num;i++)+bnad->msix_table[i].entry=i;++ret=pci_enable_msix(bnad->pcidev,bnad->msix_table,bnad->msix_num);+if(ret)gotointx_mode;pci_intx(bnad->pcidev,0);
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:15:19
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/net/ethernet/emulex/benet/be_main.c | 38 ++++++++++++++------------
1 files changed, 20 insertions(+), 18 deletions(-)
@@ -2366,29 +2366,23 @@ static int be_msix_enable(struct be_adapter *adapter)elsenum_vec=adapter->cfg_num_qs;-for(i=0;i<num_vec;i++)-adapter->msix_entries[i].entry=i;+status=pci_msix_table_size(adapter->pdev);+if(status<0)+gotofail;-status=pci_enable_msix(adapter->pdev,adapter->msix_entries,num_vec);-if(status==0){-gotodone;-}elseif(status>=MIN_MSIX_VECTORS){-num_vec=status;-status=pci_enable_msix(adapter->pdev,adapter->msix_entries,-num_vec);-if(!status)-gotodone;-}else(status>0){+num_vec=min(num_vec,status);+if(num_vec<MIN_MSIX_VECTORS){status=-ENOSPC;+gotofail;}-dev_warn(dev,"MSIx enable failed\n");+for(i=0;i<num_vec;i++)+adapter->msix_entries[i].entry=i;++status=pci_enable_msix(adapter->pdev,adapter->msix_entries,num_vec);+if(status)+gotofail;-/* INTx is not supported in VFs, so fail probe if enable_msix fails */-if(!be_physfn(adapter))-returnstatus;-return0;-done:if(be_roce_supported(adapter)&&num_vec>MIN_MSIX_VECTORS){adapter->num_msix_roce_vec=num_vec/2;dev_info(dev,"enabled %d MSI-x vector(s) for RoCE\n",
@@ -2400,6 +2394,14 @@ done:dev_info(dev,"enabled %d MSI-x vector(s) for NIC\n",adapter->num_msix_vec);return0;++fail:+dev_warn(dev,"MSIx enable failed\n");++/* INTx is not supported in VFs, so fail probe if enable_msix fails */+if(!be_physfn(adapter))+returnstatus;+return0;}staticinlineintbe_msix_vec_get(structbe_adapter*adapter,
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:18:10
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/scsi/ipr.c | 46 +++++++++++++++++++++++-----------------------
1 files changed, 23 insertions(+), 23 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:20:06
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/net/ethernet/qlogic/qlge/qlge_main.c | 39 +++++++++++--------------
1 files changed, 17 insertions(+), 22 deletions(-)
@@ -3258,45 +3258,40 @@ static void ql_enable_msix(struct ql_adapter *qdev)/* Get the MSIX vectors. */if(qlge_irq_type==MSIX_IRQ){+err=pci_msix_table_size(qdev->pdev);+if(err<0)+gotomsix_fail;++qdev->intr_count=min_t(u32,qdev->intr_count,err);+/* Try to alloc space for the msix struct,*ifitfailsthengotoMSI/legacy.*/qdev->msi_x_entry=kcalloc(qdev->intr_count,sizeof(structmsix_entry),GFP_KERNEL);-if(!qdev->msi_x_entry){-qlge_irq_type=MSI_IRQ;-gotomsi;-}+if(!qdev->msi_x_entry)+gotomsix_fail;for(i=0;i<qdev->intr_count;i++)qdev->msi_x_entry[i].entry=i;-/* Loop to get our vectors. We start with-*whatwewantandsettleforwhatweget.-*/-do{-err=pci_enable_msix(qdev->pdev,-qdev->msi_x_entry,qdev->intr_count);-if(err>0)-qdev->intr_count=err;-}while(err>0);--if(err<0){-kfree(qdev->msi_x_entry);-qdev->msi_x_entry=NULL;-netif_warn(qdev,ifup,qdev->ndev,-"MSI-X Enable failed, trying MSI.\n");-qlge_irq_type=MSI_IRQ;-}elseif(err==0){+if(!pci_enable_msix(qdev->pdev,+qdev->msi_x_entry,qdev->intr_count)){set_bit(QL_MSIX_ENABLED,&qdev->flags);netif_info(qdev,ifup,qdev->ndev,"MSI-X Enabled, got %d vectors.\n",qdev->intr_count);return;}++kfree(qdev->msi_x_entry);+qdev->msi_x_entry=NULL;+msix_fail:+netif_warn(qdev,ifup,qdev->ndev,+"MSI-X Enable failed, trying MSI.\n");+qlge_irq_type=MSI_IRQ;}-msi:qdev->intr_count=1;if(qlge_irq_type==MSI_IRQ){if(!pci_enable_msi(qdev->pdev)){
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:21:59
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/ata/ahci.c | 56 ++++++++++++++++++++++++++++++++-------------------
1 files changed, 35 insertions(+), 21 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:23:49
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/ntb/ntb_hw.c | 41 +++++++++++++----------------------------
drivers/ntb/ntb_hw.h | 2 --
2 files changed, 13 insertions(+), 30 deletions(-)
@@ -1032,23 +1032,26 @@ static int ntb_setup_msix(struct ntb_device *ndev)structmsix_entry*msix;intmsix_entries;intrc,i;-u16val;-if(!pdev->msix_cap){-rc=-EIO;+rc=pci_msix_table_size(pdev);+if(rc<0)gotoerr;-}-rc=pci_read_config_word(pdev,pdev->msix_cap+PCI_MSIX_FLAGS,&val);-if(rc)+/*+*OnSNB,thelinkinterruptisalwaystiedto4thvector.If+*wecan'tgetall4,thenwecan'tuseMSI-X.+*/+if((rc<SNB_MSIX_CNT)&&(ndev->hw_type!=BWD_HW)){+rc=-ENOSPC;gotoerr;--msix_entries=msix_table_size(val);-if(msix_entries>ndev->limits.msix_cnt){+}+if(rc>ndev->limits.msix_cnt){rc=-EINVAL;gotoerr;}+msix_entries=rc;+ndev->msix_entries=kmalloc(sizeof(structmsix_entry)*msix_entries,GFP_KERNEL);if(!ndev->msix_entries){
@@ -1060,26 +1063,8 @@ static int ntb_setup_msix(struct ntb_device *ndev)ndev->msix_entries[i].entry=i;rc=pci_enable_msix(pdev,ndev->msix_entries,msix_entries);-if(rc<0)+if(rc)gotoerr1;-if(rc>0){-/* On SNB, the link interrupt is always tied to 4th vector. If-*wecan'tgetall4,thenwecan'tuseMSI-X.-*/-if((rc<SNB_MSIX_CNT)&&(ndev->hw_type!=BWD_HW)){-rc=-EIO;-gotoerr1;-}--dev_warn(&pdev->dev,-"Only %d MSI-X vectors. Limiting the number of queues to that number.\n",-rc);-msix_entries=rc;--rc=pci_enable_msix(pdev,ndev->msix_entries,msix_entries);-if(rc)-gotoerr1;-}for(i=0;i<msix_entries;i++){msix=&ndev->msix_entries[i];
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:25:25
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 56 ++++++++++++---------
1 files changed, 32 insertions(+), 24 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:25:39
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
.../net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 49 ++++++++++++--------
1 files changed, 29 insertions(+), 20 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:26:43
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 62 +++++++++++++----------
1 files changed, 35 insertions(+), 27 deletions(-)
@@ -5699,9 +5699,6 @@ static int enable_msix(struct adapter *adap)unsignedintnchan=adap->params.nports;structmsix_entryentries[MAX_INGQ+1];-for(i=0;i<ARRAY_SIZE(entries);++i)-entries[i].entry=i;-want=s->max_ethqsets+EXTRA_VECS;if(is_offload(adap)){want+=s->rdmaqs+s->ofldqsets;
@@ -5710,34 +5707,45 @@ static int enable_msix(struct adapter *adap)}need=adap->params.nports+EXTRA_VECS+ofld_need;-while((err=pci_enable_msix(adap->pdev,entries,want))>=need)-want=err;+err=pci_msix_table_size(adap->pdev);+if(err<0)+returnerr;-if(!err){-/*-*Distributeavailablevectorstothevariousqueuegroups.-*EverygroupgetsitsminimumrequirementandNICgetstop-*priorityforleftovers.-*/-i=want-EXTRA_VECS-ofld_need;-if(i<s->max_ethqsets){-s->max_ethqsets=i;-if(i<s->ethqsets)-reduce_ethqs(adap,i);-}-if(is_offload(adap)){-i=want-EXTRA_VECS-s->max_ethqsets;-i-=ofld_need-nchan;-s->ofldqsets=(i/nchan)*nchan;/* round down */-}-for(i=0;i<want;++i)-adap->msix_info[i].vec=entries[i].vector;-}elseif(err>0){+want=min(want,err);+if(want<need){dev_info(adap->pdev_dev,"only %d MSI-X vectors left, not using MSI-X\n",err);-err=-ENOSPC;+return-ENOSPC;}-returnerr;++BUG_ON(want>ARRAY_SIZE(entries));+for(i=0;i<want;++i)+entries[i].entry=i;++err=pci_enable_msix(adap->pdev,entries,want);+if(err)+returnerr;++/*+*Distributeavailablevectorstothevariousqueuegroups.+*EverygroupgetsitsminimumrequirementandNICgetstop+*priorityforleftovers.+*/+i=want-EXTRA_VECS-ofld_need;+if(i<s->max_ethqsets){+s->max_ethqsets=i;+if(i<s->ethqsets)+reduce_ethqs(adap,i);+}+if(is_offload(adap)){+i=want-EXTRA_VECS-s->max_ethqsets;+i-=ofld_need-nchan;+s->ofldqsets=(i/nchan)*nchan;/* round down */+}+for(i=0;i<want;++i)+adap->msix_info[i].vec=entries[i].vector;++return0;}#undef EXTRA_VECS
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:26:54
Make pci_msix_table_size() to return a error code if the device
does not support MSI-X. This update is needed to facilitate a
forthcoming re-design MSI/MSI-X interrupts enabling pattern.
Device drivers will use this interface to obtain maximum number
of MSI-X interrupts the device supports and use that value in
the following call to pci_enable_msix() interface.
Signed-off-by: Alexander Gordeev <redacted>
---
Documentation/PCI/MSI-HOWTO.txt | 13 +++++++++++++
drivers/pci/msi.c | 5 ++++-
drivers/pci/pcie/portdrv_core.c | 2 ++
3 files changed, 19 insertions(+), 1 deletions(-)
@@ -255,6 +255,19 @@ MSI-X Table. This address is mapped by the PCI subsystem, and should not be accessed directly by the device driver. If the driver wishes to mask or unmask an interrupt, it should call disable_irq() / enable_irq().+4.3.4 pci_msix_table_size++int pci_msix_table_size(struct pci_dev *dev)++This function could be used to retrieve number of entries in the device+MSI-X table.++If this function returns a negative number, it indicates the device is+not capable of sending MSI-Xs.++If this function returns a positive number, it indicates the maximum+number of MSI-X interrupt vectors that could be allocated.+ 4.4 Handling devices implementing both MSI and MSI-X capabilities If a device implements both MSI and MSI-X capabilities, it can
@@ -80,6 +80,8 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask)u32reg32;nr_entries=pci_msix_table_size(dev);+if(nr_entries<0)+returnnr_entries;if(!nr_entries)return-EINVAL;if(nr_entries>PCIE_PORT_MAX_MSIX_ENTRIES)
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:28:08
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/net/vmxnet3/vmxnet3_drv.c | 68 ++++++++++++++++++-------------------
1 files changed, 33 insertions(+), 35 deletions(-)
@@ -2724,49 +2724,47 @@ vmxnet3_read_mac_addr(struct vmxnet3_adapter *adapter, u8 *mac)#ifdef CONFIG_PCI_MSI-/*-*EnableMSIxvectors.-*Returns:-*0onsuccessfulenablingofrequiredvectors,-*VMXNET3_LINUX_MIN_MSIX_VECTwhenonlyminimumnumberofvectorsrequired-*couldbeenabled.-*numberofvectorswhichcanbeenabledotherwise(thisnumberissmaller-*thanVMXNET3_LINUX_MIN_MSIX_VECT)-*/-staticintvmxnet3_acquire_msix_vectors(structvmxnet3_adapter*adapter,intvectors){-interr=-EINVAL,vector_threshold;+interr,vector_threshold;+vector_threshold=VMXNET3_LINUX_MIN_MSIX_VECT;+if(vectors<vector_threshold)+return-EINVAL;-while(vectors>=vector_threshold){-err=pci_enable_msix(adapter->pdev,adapter->intr.msix_entries,-vectors);-if(!err){-adapter->intr.num_intrs=vectors;-return0;-}elseif(err<0){-dev_err(&adapter->netdev->dev,-"Failed to enable MSI-X, error: %d\n",err);-returnerr;-}elseif(err<vector_threshold){-dev_info(&adapter->pdev->dev,-"Number of MSI-Xs which can be allocated "-"is lower than min threshold required.\n");-return-ENOSPC;-}else{-/* If fails to enable required number of MSI-x vectors-*tryenablingminimumnumberofvectorsrequired.-*/-dev_err(&adapter->netdev->dev,-"Failed to enable %d MSI-X, trying %d instead\n",-vectors,vector_threshold);-vectors=vector_threshold;-}+err=pci_msix_table_size(adapter->pdev);+if(err<0)+gotoerr_msix;+if(err<vector_threshold){+dev_info(&adapter->pdev->dev,+"Number of MSI-X interrupts which can be allocated "+"is lower than min threshold required.\n");+return-ENOSPC;+}+if(err<vectors){+/*+*IffailstoenablerequirednumberofMSI-xvectors+*tryenablingminimumnumberofvectorsrequired.+*/+dev_err(&adapter->netdev->dev,+"Failed to enable %d MSI-X, trying %d instead\n",+vectors,vector_threshold);+vectors=vector_threshold;}+err=pci_enable_msix(adapter->pdev,adapter->intr.msix_entries,+vectors);+if(err)+gotoerr_msix;++adapter->intr.num_intrs=vectors;+return0;++err_msix:+dev_err(&adapter->netdev->dev,+"Failed to enable MSI-X, error: %d\n",err);returnerr;}
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:28:19
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c | 62 +++++++++++++------------
1 files changed, 32 insertions(+), 30 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:29:47
As result of recent re-design of the MSI/MSI-X interrupts enabling
pattern this driver has to be updated to use the new technique to
obtain a optimal number of MSI/MSI-X interrupts required.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 54 ++++++++++-------------
1 files changed, 23 insertions(+), 31 deletions(-)
@@ -1564,7 +1564,7 @@ void bnx2x_free_irq(struct bnx2x *bp)intbnx2x_enable_msix(structbnx2x*bp){-intmsix_vec=0,i,rc;+intmsix_vec=0,nvec,i,rc;/* VFs don't have a default status block */if(IS_PF(bp)){
@@ -1590,60 +1590,52 @@ int bnx2x_enable_msix(struct bnx2x *bp)msix_vec++;}+rc=pci_msix_table_size(bp->pdev);+if(rc<0)+gotono_msix;++nvec=min(msix_vec,rc);+if(nvec<BNX2X_MIN_MSIX_VEC_CNT(bp))+nvec=1;+DP(BNX2X_MSG_SP,"about to request enable msix with %d vectors\n",msix_vec);-rc=pci_enable_msix(bp->pdev,&bp->msix_table[0],msix_vec);+rc=pci_enable_msix(bp->pdev,&bp->msix_table[0],nvec);+if(rc)+gotono_msix;/**reconfigurenumberoftx/rxqueuesaccordingtoavailable*MSI-Xvectors*/-if(rc>=BNX2X_MIN_MSIX_VEC_CNT(bp)){-/* how less vectors we will have? */-intdiff=msix_vec-rc;--BNX2X_DEV_INFO("Trying to use less MSI-X vectors: %d\n",rc);+if(nvec==1){+bp->flags|=USING_SINGLE_MSIX_FLAG;-rc=pci_enable_msix(bp->pdev,&bp->msix_table[0],rc);+bp->num_ethernet_queues=1;+bp->num_queues=bp->num_ethernet_queues+bp->num_cnic_queues;+}elseif(nvec<msix_vec){+/* how less vectors we will have? */+intdiff=msix_vec-nvec;-if(rc){-BNX2X_DEV_INFO("MSI-X is not attainable rc %d\n",rc);-gotono_msix;-}/**decreasenumberofqueuesbynumberofunallocatedentries*/bp->num_ethernet_queues-=diff;bp->num_queues=bp->num_ethernet_queues+bp->num_cnic_queues;+}+if(nvec!=msix_vec)BNX2X_DEV_INFO("New queue configuration set: %d\n",bp->num_queues);-}elseif(rc>0){-/* Get by with single vector */-rc=pci_enable_msix(bp->pdev,&bp->msix_table[0],1);-if(rc){-BNX2X_DEV_INFO("Single MSI-X is not attainable rc %d\n",-rc);-gotono_msix;-}--BNX2X_DEV_INFO("Using single MSI-X vector\n");-bp->flags|=USING_SINGLE_MSIX_FLAG;--BNX2X_DEV_INFO("set number of queues to 1\n");-bp->num_ethernet_queues=1;-bp->num_queues=bp->num_ethernet_queues+bp->num_cnic_queues;-}elseif(rc<0){-BNX2X_DEV_INFO("MSI-X is not attainable rc %d\n",rc);-gotono_msix;-}bp->flags|=USING_MSIX_FLAG;return0;no_msix:+BNX2X_DEV_INFO("MSI-X is not attainable rc %d\n",rc);+/* fall to INTx if not enough memory */if(rc==-ENOMEM)bp->flags|=DISABLE_MSI_FLAG;
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:30:05
This update is needed to facilitate a forthcoming re-design
MSI/MSI-X interrupts enabling pattern.
Device drivers will use this interface to obtain maximum number
of MSI interrupts the device supports and use that value in the
following call to pci_enable_msi_block() interface.
Signed-off-by: Alexander Gordeev <redacted>
---
Documentation/PCI/MSI-HOWTO.txt | 15 +++++++++++++++
drivers/pci/msi.c | 33 +++++++++++++++++++++------------
include/linux/pci.h | 6 ++++++
3 files changed, 42 insertions(+), 12 deletions(-)
@@ -169,6 +169,21 @@ on any interrupt for which it previously called request_irq(). Failure to do so results in a BUG_ON(), leaving the device with MSI enabled and thus leaking its vector.+4.2.5 pci_get_msi_cap++int pci_get_msi_cap(struct pci_dev *dev)++This function could be used to retrieve the number of MSI vectors the+device requested (via the Multiple Message Capable register). The MSI+specification only allows the returned value to be a power of two,+up to a maximum of 2^5 (32).++If this function returns a negative number, it indicates the device is+not capable of sending MSIs.++If this function returns a positive number, it indicates the maximum+number of MSI interrupt vectors that could be allocated.+ 4.3 Using MSI-X The MSI-X capability is much more flexible than the MSI capability.
@@ -812,6 +812,21 @@ static int pci_msi_check_device(struct pci_dev *dev, int nvec, int type)return0;}+intpci_get_msi_cap(structpci_dev*dev)+{+intret;+u16msgctl;++if(!dev->msi_cap)+return-EINVAL;++pci_read_config_word(dev,dev->msi_cap+PCI_MSI_FLAGS,&msgctl);+ret=1<<((msgctl&PCI_MSI_FLAGS_QMASK)>>1);++returnret;+}+EXPORT_SYMBOL(pci_get_msi_cap);+/***pci_enable_msi_block-configuredevice'sMSIcapabilitystructure*@dev:devicetoconfigure
@@ -828,13 +843,10 @@ static int pci_msi_check_device(struct pci_dev *dev, int nvec, int type)intpci_enable_msi_block(structpci_dev*dev,unsignedintnvec){intstatus,maxvec;-u16msgctl;-if(!dev->msi_cap)-return-EINVAL;--pci_read_config_word(dev,dev->msi_cap+PCI_MSI_FLAGS,&msgctl);-maxvec=1<<((msgctl&PCI_MSI_FLAGS_QMASK)>>1);+maxvec=pci_get_msi_cap(dev);+if(maxvec<0)+returnmaxvec;if(nvec>maxvec)returnmaxvec;
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:31:22
As result of recent re-design of MSI/MSI-X interrupts enabling
pattern pci_enable_msi_block_auto() interface became obsolete.
To enable maximum number of MSI interrupts for a device the
driver will first obtain that number from pci_get_msi_cap()
function and then call pci_enable_msi_block() interface.
Signed-off-by: Alexander Gordeev <redacted>
---
Documentation/PCI/MSI-HOWTO.txt | 30 ++----------------------------
drivers/pci/msi.c | 20 --------------------
include/linux/pci.h | 7 -------
3 files changed, 2 insertions(+), 55 deletions(-)
@@ -133,33 +133,7 @@ static int foo_driver_enable_msi(struct foo_adapter *adapter, int nvec) return rc; }-4.2.3 pci_enable_msi_block_auto--int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *count)--This variation on pci_enable_msi() call allows a device driver to request-the maximum possible number of MSIs. The MSI specification only allows-interrupts to be allocated in powers of two, up to a maximum of 2^5 (32).--If this function returns a positive number, it indicates that it has-succeeded and the returned value is the number of allocated interrupts. In-this case, the function enables MSI on this device and updates dev->irq to-be the lowest of the new interrupts assigned to it. The other interrupts-assigned to the device are in the range dev->irq to dev->irq + returned-value - 1.--If this function returns a negative number, it indicates an error and-the driver should not attempt to request any more MSI interrupts for-this device.--If the device driver needs to know the number of interrupts the device-supports it can pass the pointer count where that number is stored. The-device driver must decide what action to take if pci_enable_msi_block_auto()-succeeds, but returns a value less than the number of interrupts supported.-If the device driver does not need to know the number of interrupts-supported, it can set the pointer count to NULL.--4.2.4 pci_disable_msi+4.2.3 pci_disable_msi void pci_disable_msi(struct pci_dev *dev)
@@ -175,7 +149,7 @@ on any interrupt for which it previously called request_irq(). Failure to do so results in a BUG_ON(), leaving the device with MSI enabled and thus leaking its vector.-4.2.5 pci_get_msi_cap+4.2.4 pci_get_msi_cap int pci_get_msi_cap(struct pci_dev *dev)
@@ -533,7 +533,7 @@ csio_enable_msix(struct csio_hw *hw)csio_info(hw,"Not using MSI-X, remainder:%d\n",rv);kfree(entries);-return-ENOMEM;+return-ENOSPC;}/* Save off vectors */
@@ -4141,7 +4141,11 @@ static void hpsa_interrupt_mode(struct ctlr_info *h)}default_int_mode:#endif /* CONFIG_PCI_MSI */-/* if we get here we're going to use the default interrupt mode */+/*+*Ifwegetherewe'regoingtouseeitherthe+*defaultinterruptmodeorsingleMSImode+*/+h->intr[h->intr_mode]=h->pdev->irq;}
@@ -1066,7 +1066,7 @@ static int ntb_setup_msix(struct ntb_device *ndev)/* On SNB, the link interrupt is always tied to 4th vector. If*wecan'tgetall4,thenwecan'tuseMSI-X.*/-if(ndev->hw_type!=BWD_HW){+if((rc<SNB_MSIX_CNT)&&(ndev->hw_type!=BWD_HW)){rc=-EIO;gotoerr1;}
@@ -4103,7 +4103,10 @@ static void cciss_interrupt_mode(ctlr_info_t *h)}default_int_mode:#endif /* CONFIG_PCI_MSI */-/* if we get here we're going to use the default interrupt mode */+/*+*Ifwegetherewe'regoingtouseeitherthe+*defaultinterruptmodeorsingleMSImode+*/h->intr[h->intr_mode]=h->pdev->irq;return;}
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:50:10
arch_setup_msi_irqs() hook can only be called from the generic
MSI code which ensures correct MSI type parameter.
Signed-off-by: Alexander Gordeev <redacted>
---
arch/s390/pci/pci.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:53:16
Multiple MSIs have never been supported on s390 architecture,
but the platform code fails to report single MSI only.
Signed-off-by: Alexander Gordeev <redacted>
---
arch/s390/pci/pci.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:54:05
The minimum number of MSI-Xs is (MLX5_EQ_VEC_COMP_BASE + 1) in
one check and 2 in another check. Make the checks consistent and
assume the minimum number is (MLX5_EQ_VEC_COMP_BASE + 1).
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/net/ethernet/mellanox/mlx5/core/main.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
From: Alexander Gordeev <hidden> Date: 2013-10-02 17:55:23
Current MSI-X enablement code assumes MSI-Xs were successfully
allocated in case less than requested vectors were available.
That assumption is wrong, since MSI-Xs should be enabled with
a repeated call to pci_enable_msix(). This update fixes this.
Signed-off-by: Alexander Gordeev <redacted>
---
drivers/ntb/ntb_hw.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
@@ -1075,6 +1075,10 @@ static int ntb_setup_msix(struct ntb_device *ndev)"Only %d MSI-X vectors. Limiting the number of queues to that number.\n",rc);msix_entries=rc;++rc=pci_enable_msix(pdev,ndev->msix_entries,msix_entries);+if(rc)+gotoerr1;}for(i=0;i<msix_entries;i++){
@@ -2752,7 +2752,10 @@ vmxnet3_acquire_msix_vectors(struct vmxnet3_adapter *adapter,"Failed to enable MSI-X, error: %d\n",err);returnerr;}elseif(err<vector_threshold){-break;+dev_info(&adapter->pdev->dev,+"Number of MSI-Xs which can be allocated "+"is lower than min threshold required.\n");+return-ENOSPC;}else{/* If fails to enable required number of MSI-x vectors*tryenablingminimumnumberofvectorsrequired.
@@ -2764,9 +2767,6 @@ vmxnet3_acquire_msix_vectors(struct vmxnet3_adapter *adapter,}}-dev_info(&adapter->pdev->dev,-"Number of MSI-X interrupts which can be allocated "-"is lower than min threshold required.\n");returnerr;}
@@ -2814,12 +2814,14 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter)err=vmxnet3_acquire_msix_vectors(adapter,adapter->intr.num_intrs);-/* If we cannot allocate one MSIx vector per queue-*thenlimitthenumberofrxqueuesto1-*/-if(err==VMXNET3_LINUX_MIN_MSIX_VECT){-if(adapter->share_intr!=VMXNET3_INTR_BUDDYSHARE-||adapter->num_rx_queues!=1){+if(!err){+/* If we cannot allocate one MSIx vector per queue+*thenlimitthenumberofrxqueuesto1+*/+if((adapter->intr.num_intrs==+VMXNET3_LINUX_MIN_MSIX_VECT)&&+((adapter->share_intr!=VMXNET3_INTR_BUDDYSHARE)||+(adapter->num_rx_queues!=1))){adapter->share_intr=VMXNET3_INTR_TXSHARE;netdev_err(adapter->netdev,"Number of rx queues : 1\n");
@@ -2829,8 +2831,6 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter)}return;}-if(!err)-return;/* If we cannot allocate MSIx vectors use only one rx queue */dev_info(&adapter->pdev->dev,
From: Alexander Gordeev <hidden> Date: 2013-10-02 18:09:25
Currently pci_enable_msi_block() and pci_enable_msix() interfaces
return a error code in case of failure, 0 in case of success and a
positive value which indicates the number of MSI-X/MSI interrupts
that could have been allocated. The latter value should be passed
to a repeated call to the interfaces until a failure or success.
This technique proved to be confusing and error-prone. Vast share
of device drivers simply fail to follow the described guidelines.
This update converts pci_enable_msix() and pci_enable_msi_block()
interfaces to canonical kernel functions and makes them return a
error code in case of failure or 0 in case of success.
As result, device drivers will cease to use the overcomplicated
repeated fallbacks technique and resort to a straightforward
pattern - determine the number of MSI/MSI-X interrupts required
before calling pci_enable_msix() and pci_enable_msi_block()
interfaces.
Device drivers will use their knowledge of underlying hardware
to determine the number of MSI/MSI-X interrupts required.
The simplest case would be requesting all available interrupts -
to obtain that value device drivers will use pci_get_msi_cap()
interface for MSI and pci_msix_table_size() for MSI-X.
More complex cases would entail matching device capabilities
with the system environment, i.e. limiting number of hardware
queues (and hence associated MSI/MSI-X interrupts) to the number
of online CPUs.
Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Alexander Gordeev <redacted>
---
Documentation/PCI/MSI-HOWTO.txt | 71 ++++++++++++++++++---------------
arch/mips/pci/msi-octeon.c | 2 +-
arch/powerpc/kernel/msi.c | 2 +-
arch/powerpc/platforms/pseries/msi.c | 2 +-
arch/s390/pci/pci.c | 2 +-
arch/x86/kernel/apic/io_apic.c | 2 +-
drivers/pci/msi.c | 52 +++++++------------------
7 files changed, 58 insertions(+), 75 deletions(-)
@@ -111,21 +111,27 @@ the device are in the range dev->irq to dev->irq + count - 1. If this function returns a negative number, it indicates an error and the driver should not attempt to request any more MSI interrupts for-this device. If this function returns a positive number, it is-less than 'count' and indicates the number of interrupts that could have-been allocated. In neither case is the irq value updated or the device-switched into MSI mode.--The device driver must decide what action to take if-pci_enable_msi_block() returns a value less than the number requested.-For instance, the driver could still make use of fewer interrupts;-in this case the driver should call pci_enable_msi_block()-again. Note that it is not guaranteed to succeed, even when the-'count' has been reduced to the value returned from a previous call to-pci_enable_msi_block(). This is because there are multiple constraints-on the number of vectors that can be allocated; pci_enable_msi_block()-returns as soon as it finds any constraint that doesn't allow the-call to succeed.+this device.++Device drivers should normally call pci_get_msi_cap() function before+calling this function to determine maximum number of MSI interrupts+a device can send.++A sequence to achieve that might look like:++static int foo_driver_enable_msi(struct foo_adapter *adapter, int nvec)+{+ rc = pci_get_msi_cap(adapter->pdev);+ if (rc < 0)+ return rc;++ nvec = min(nvec, rc);+ if (nvec < FOO_DRIVER_MINIMUM_NVEC) {+ return -ENOSPC;++ rc = pci_enable_msi_block(adapter->pdev, nvec);+ return rc;+} 4.2.3 pci_enable_msi_block_auto
@@ -218,9 +224,7 @@ interrupts assigned to the MSI-X vectors so it can free them again later. If this function returns a negative number, it indicates an error and the driver should not attempt to allocate any more MSI-X interrupts for-this device. If it returns a positive number, it indicates the maximum-number of interrupt vectors that could have been allocated. See example-below.+this device. This function, in contrast with pci_enable_msi(), does not adjust dev->irq. The device will not generate interrupts for this interrupt
@@ -229,24 +233,27 @@ number once MSI-X is enabled. Device drivers should normally call this function once per device during the initialization phase.-It is ideal if drivers can cope with a variable number of MSI-X interrupts;-there are many reasons why the platform may not be able to provide the-exact number that a driver asks for.+Device drivers should normally call pci_msix_table_size() function before+calling this function to determine maximum number of MSI-X interrupts+a device can send.-A request loop to achieve that might look like:+A sequence to achieve that might look like: static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec) {- while (nvec >= FOO_DRIVER_MINIMUM_NVEC) {- rc = pci_enable_msix(adapter->pdev,- adapter->msix_entries, nvec);- if (rc > 0)- nvec = rc;- else- return rc;- }-- return -ENOSPC;+ rc = pci_msix_table_size(adapter->pdev);+ if (rc < 0)+ return rc;++ nvec = min(nvec, rc);+ if (nvec < FOO_DRIVER_MINIMUM_NVEC) {+ return -ENOSPC;++ for (i = 0; i < nvec; i++)+ adapter->msix_entries[i].entry = i;++ rc = pci_enable_msix(adapter->pdev, adapter->msix_entries, nvec);+ return rc; } 4.3.2 pci_disable_msix
@@ -193,7 +193,7 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)*overridearch_setup_msi_irqs()*/if(type==PCI_CAP_ID_MSI&&nvec>1)-return1;+return-EINVAL;list_for_each_entry(entry,&dev->msi_list,list){ret=arch_setup_msi_irq(dev,entry);
@@ -22,7 +22,7 @@ int arch_msi_check_device(struct pci_dev* dev, int nvec, int type)/* PowerPC doesn't support multiple MSI yet */if(type==PCI_CAP_ID_MSI&&nvec>1)-return1;+return-EINVAL;if(ppc_md.msi_check_device){pr_debug("msi: Using platform check routine.\n");
@@ -348,7 +348,7 @@ static int rtas_msi_check_device(struct pci_dev *pdev, int nvec, int type)quota=msi_quota_for_device(pdev,nvec);if(quota&"a<nvec)-returnquota;+return-ENOSPC;return0;}
@@ -3145,7 +3145,7 @@ int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)/* Multiple MSI vectors only supported with interrupt remapping */if(type==PCI_CAP_ID_MSI&&nvec>1)-return1;+return-EINVAL;node=dev_to_node(&dev->dev);irq_want=nr_irqs_gsi;
@@ -719,7 +719,7 @@ static int msix_capability_init(struct pci_dev *dev,ret=arch_setup_msi_irqs(dev,nvec,PCI_CAP_ID_MSIX);if(ret)-gotoout_avail;+gotoerror;/**SomedevicesrequireMSI-Xtobeenabledbeforewecantouchthe
@@ -733,7 +733,7 @@ static int msix_capability_init(struct pci_dev *dev,ret=populate_msi_sysfs(dev);if(ret)-gotoout_free;+gotoerror;/* Set MSI-X enabled bits and unmask the function */pci_intx_for_msi(dev,0);
@@ -744,24 +744,7 @@ static int msix_capability_init(struct pci_dev *dev,return0;-out_avail:-if(ret<0){-/*-*Ifwehadsomesuccess,reportthenumberofirqs-*wesucceededinsettingup.-*/-structmsi_desc*entry;-intavail=0;--list_for_each_entry(entry,&dev->msi_list,list){-if(entry->irq!=0)-avail++;-}-if(avail!=0)-ret=avail;-}--out_free:+error:free_msi_irqs(dev);returnret;
@@ -975,7 +951,7 @@ int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)if(nr_entries<0)returnnr_entries;if(nvec>nr_entries)-returnnr_entries;+return-EINVAL;/* Check for any invalid entries */for(i=0;i<nvec;i++){