summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2011-07-22 18:37:28 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-07-27 07:12:47 -0400
commit0a96e9754d6c4a2a31e50ee6c6e36ec13f80bc25 (patch)
tree177428ae74bb817eb299102cc5c90ea8f79b36f3 /drivers/scsi
parent5248a7498e5f6f3d6d276080466946f82f0ea56a (diff)
[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')
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c76
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c44
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c1
4 files changed, 49 insertions, 73 deletions
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index bffd86f204dd..80ca11c5158c 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -1466,80 +1466,10 @@ lpfc_sriov_hw_max_virtfn_show(struct device *dev,
1466 struct Scsi_Host *shost = class_to_shost(dev); 1466 struct Scsi_Host *shost = class_to_shost(dev);
1467 struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 1467 struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
1468 struct lpfc_hba *phba = vport->phba; 1468 struct lpfc_hba *phba = vport->phba;
1469 struct pci_dev *pdev = phba->pcidev; 1469 uint16_t max_nr_virtfn;
1470 union lpfc_sli4_cfg_shdr *shdr;
1471 uint32_t shdr_status, shdr_add_status;
1472 LPFC_MBOXQ_t *mboxq;
1473 struct lpfc_mbx_get_prof_cfg *get_prof_cfg;
1474 struct lpfc_rsrc_desc_pcie *desc;
1475 uint32_t max_nr_virtfn;
1476 uint32_t desc_count;
1477 int length, rc, i;
1478
1479 if ((phba->sli_rev < LPFC_SLI_REV4) ||
1480 (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
1481 LPFC_SLI_INTF_IF_TYPE_2))
1482 return -EPERM;
1483
1484 if (!pdev->is_physfn)
1485 return snprintf(buf, PAGE_SIZE, "%d\n", 0);
1486
1487 mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
1488 if (!mboxq)
1489 return -ENOMEM;
1490
1491 /* get the maximum number of virtfn support by physfn */
1492 length = (sizeof(struct lpfc_mbx_get_prof_cfg) -
1493 sizeof(struct lpfc_sli4_cfg_mhdr));
1494 lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
1495 LPFC_MBOX_OPCODE_GET_PROFILE_CONFIG,
1496 length, LPFC_SLI4_MBX_EMBED);
1497 shdr = (union lpfc_sli4_cfg_shdr *)
1498 &mboxq->u.mqe.un.sli4_config.header.cfg_shdr;
1499 bf_set(lpfc_mbox_hdr_pf_num, &shdr->request,
1500 phba->sli4_hba.iov.pf_number + 1);
1501
1502 get_prof_cfg = &mboxq->u.mqe.un.get_prof_cfg;
1503 bf_set(lpfc_mbx_get_prof_cfg_prof_tp, &get_prof_cfg->u.request,
1504 LPFC_CFG_TYPE_CURRENT_ACTIVE);
1505
1506 rc = lpfc_sli_issue_mbox_wait(phba, mboxq,
1507 lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG));
1508
1509 if (rc != MBX_TIMEOUT) {
1510 /* check return status */
1511 shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
1512 shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
1513 &shdr->response);
1514 if (shdr_status || shdr_add_status || rc)
1515 goto error_out;
1516
1517 } else
1518 goto error_out;
1519
1520 desc_count = get_prof_cfg->u.response.prof_cfg.rsrc_desc_count;
1521
1522 for (i = 0; i < LPFC_RSRC_DESC_MAX_NUM; i++) {
1523 desc = (struct lpfc_rsrc_desc_pcie *)
1524 &get_prof_cfg->u.response.prof_cfg.desc[i];
1525 if (LPFC_RSRC_DESC_TYPE_PCIE ==
1526 bf_get(lpfc_rsrc_desc_pcie_type, desc)) {
1527 max_nr_virtfn = bf_get(lpfc_rsrc_desc_pcie_nr_virtfn,
1528 desc);
1529 break;
1530 }
1531 }
1532
1533 if (i < LPFC_RSRC_DESC_MAX_NUM) {
1534 if (rc != MBX_TIMEOUT)
1535 mempool_free(mboxq, phba->mbox_mem_pool);
1536 return snprintf(buf, PAGE_SIZE, "%d\n", max_nr_virtfn);
1537 }
1538 1470
1539error_out: 1471 max_nr_virtfn = lpfc_sli_sriov_nr_virtfn_get(phba);
1540 if (rc != MBX_TIMEOUT) 1472 return snprintf(buf, PAGE_SIZE, "%d\n", max_nr_virtfn);
1541 mempool_free(mboxq, phba->mbox_mem_pool);
1542 return -EIO;
1543} 1473}
1544 1474
1545/** 1475/**
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index a4f00cc72f41..1e41af8dea74 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -440,3 +440,4 @@ struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t,
440int lpfc_wr_object(struct lpfc_hba *, struct list_head *, uint32_t, uint32_t *); 440int lpfc_wr_object(struct lpfc_hba *, struct list_head *, uint32_t, uint32_t *);
441/* functions to support SR-IOV */ 441/* functions to support SR-IOV */
442int lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *, int); 442int lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *, int);
443uint16_t lpfc_sli_sriov_nr_virtfn_get(struct lpfc_hba *);
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 9d3e8affccb8..027b797c9916 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)
4037} 4037}
4038 4038
4039/** 4039/**
4040 * lpfc_sli_sriov_nr_virtfn_get - Get the number of sr-iov virtual functions
4041 * @phba: pointer to lpfc hba data structure.
4042 *
4043 * This function enables the PCI SR-IOV virtual functions to a physical
4044 * function. It invokes the PCI SR-IOV api with the @nr_vfn provided to
4045 * enable the number of virtual functions to the physical function. As
4046 * not all devices support SR-IOV, the return code from the pci_enable_sriov()
4047 * API call does not considered as an error condition for most of the device.
4048 **/
4049uint16_t
4050lpfc_sli_sriov_nr_virtfn_get(struct lpfc_hba *phba)
4051{
4052 struct pci_dev *pdev = phba->pcidev;
4053 uint16_t nr_virtfn;
4054 int pos;
4055
4056 if (!pdev->is_physfn)
4057 return 0;
4058
4059 pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
4060 if (pos == 0)
4061 return 0;
4062
4063 pci_read_config_word(pdev, pos + PCI_SRIOV_TOTAL_VF, &nr_virtfn);
4064 return nr_virtfn;
4065}
4066
4067/**
4040 * lpfc_sli_probe_sriov_nr_virtfn - Enable a number of sr-iov virtual functions 4068 * lpfc_sli_probe_sriov_nr_virtfn - Enable a number of sr-iov virtual functions
4041 * @phba: pointer to lpfc hba data structure. 4069 * @phba: pointer to lpfc hba data structure.
4042 * @nr_vfn: number of virtual functions to be enabled. 4070 * @nr_vfn: number of virtual functions to be enabled.
@@ -4051,8 +4079,17 @@ int
4051lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *phba, int nr_vfn) 4079lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *phba, int nr_vfn)
4052{ 4080{
4053 struct pci_dev *pdev = phba->pcidev; 4081 struct pci_dev *pdev = phba->pcidev;
4082 uint16_t max_nr_vfn;
4054 int rc; 4083 int rc;
4055 4084
4085 max_nr_vfn = lpfc_sli_sriov_nr_virtfn_get(phba);
4086 if (nr_vfn > max_nr_vfn) {
4087 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
4088 "3057 Requested vfs (%d) greater than "
4089 "supported vfs (%d)", nr_vfn, max_nr_vfn);
4090 return -EINVAL;
4091 }
4092
4056 rc = pci_enable_sriov(pdev, nr_vfn); 4093 rc = pci_enable_sriov(pdev, nr_vfn);
4057 if (rc) { 4094 if (rc) {
4058 lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, 4095 lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
@@ -9487,6 +9524,13 @@ lpfc_io_slot_reset_s4(struct pci_dev *pdev)
9487 } 9524 }
9488 9525
9489 pci_restore_state(pdev); 9526 pci_restore_state(pdev);
9527
9528 /*
9529 * As the new kernel behavior of pci_restore_state() API call clears
9530 * device saved_state flag, need to save the restored state again.
9531 */
9532 pci_save_state(pdev);
9533
9490 if (pdev->is_busmaster) 9534 if (pdev->is_busmaster)
9491 pci_set_master(pdev); 9535 pci_set_master(pdev);
9492 9536
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 59d81624a855..5b28ea1d72c5 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -5839,6 +5839,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
5839 "Advanced Error Reporting (AER)\n"); 5839 "Advanced Error Reporting (AER)\n");
5840 phba->cfg_aer_support = 0; 5840 phba->cfg_aer_support = 0;
5841 } 5841 }
5842 rc = 0;
5842 } 5843 }
5843 5844
5844 if (!(phba->hba_flag & HBA_FCOE_MODE)) { 5845 if (!(phba->hba_flag & HBA_FCOE_MODE)) {