diff options
author | James Smart <james.smart@emulex.com> | 2011-07-22 18:37:28 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-07-27 15:12:47 +0400 |
commit | 0a96e9754d6c4a2a31e50ee6c6e36ec13f80bc25 (patch) | |
tree | 177428ae74bb817eb299102cc5c90ea8f79b36f3 /drivers/scsi/lpfc/lpfc_init.c | |
parent | 5248a7498e5f6f3d6d276080466946f82f0ea56a (diff) | |
download | linux-3.10-0a96e9754d6c4a2a31e50ee6c6e36ec13f80bc25.tar.gz linux-3.10-0a96e9754d6c4a2a31e50ee6c6e36ec13f80bc25.tar.bz2 linux-3.10-0a96e9754d6c4a2a31e50ee6c6e36ec13f80bc25.zip |
[SCSI] lpfc 8.3.25: PCI and SR-IOV Fixes
PCI and SR-IOV Fixes
- Call pci_save_state after the pci_restore_state completes.
- After calling pci_enable_pcie_error_reporting() and checking the return
value for logging messages from rc, reset rc to 0 to it will not later be
interpreted for error.
- Read PCI config space SR-IOV capability to get the number of VFs supported.
- Check for the PF's supported number of VFs before invoking PCI enable sriov
API call and log error message that user requested number of VFs is beyond
the PF capability if such request is passed in.
- Added check for Physical function with Virtual Functions attached. If so,
first disable all the VFs before proceeding to device reset.
Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_init.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 9d3e8affccb..027b797c991 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -4037,6 +4037,34 @@ lpfc_reset_hba(struct lpfc_hba *phba) } /** + * lpfc_sli_sriov_nr_virtfn_get - Get the number of sr-iov virtual functions + * @phba: pointer to lpfc hba data structure. + * + * This function enables the PCI SR-IOV virtual functions to a physical + * function. It invokes the PCI SR-IOV api with the @nr_vfn provided to + * enable the number of virtual functions to the physical function. As + * not all devices support SR-IOV, the return code from the pci_enable_sriov() + * API call does not considered as an error condition for most of the device. + **/ +uint16_t +lpfc_sli_sriov_nr_virtfn_get(struct lpfc_hba *phba) +{ + struct pci_dev *pdev = phba->pcidev; + uint16_t nr_virtfn; + int pos; + + if (!pdev->is_physfn) + return 0; + + pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV); + if (pos == 0) + return 0; + + pci_read_config_word(pdev, pos + PCI_SRIOV_TOTAL_VF, &nr_virtfn); + return nr_virtfn; +} + +/** * lpfc_sli_probe_sriov_nr_virtfn - Enable a number of sr-iov virtual functions * @phba: pointer to lpfc hba data structure. * @nr_vfn: number of virtual functions to be enabled. @@ -4051,8 +4079,17 @@ int lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *phba, int nr_vfn) { struct pci_dev *pdev = phba->pcidev; + uint16_t max_nr_vfn; int rc; + max_nr_vfn = lpfc_sli_sriov_nr_virtfn_get(phba); + if (nr_vfn > max_nr_vfn) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3057 Requested vfs (%d) greater than " + "supported vfs (%d)", nr_vfn, max_nr_vfn); + return -EINVAL; + } + rc = pci_enable_sriov(pdev, nr_vfn); if (rc) { lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, @@ -9487,6 +9524,13 @@ lpfc_io_slot_reset_s4(struct pci_dev *pdev) } pci_restore_state(pdev); + + /* + * As the new kernel behavior of pci_restore_state() API call clears + * device saved_state flag, need to save the restored state again. + */ + pci_save_state(pdev); + if (pdev->is_busmaster) pci_set_master(pdev); |