diff options
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 98 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 5 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 43 |
5 files changed, 129 insertions, 20 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index f8f5b4a2d523..da9070cdad91 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -612,6 +612,7 @@ struct lpfc_vport { #define FC_CT_RSNN_NN 0x4 /* RSNN_NN accepted by switch */ #define FC_CT_RSPN_ID 0x8 /* RSPN_ID accepted by switch */ #define FC_CT_RFT_ID 0x10 /* RFT_ID accepted by switch */ +#define FC_CT_RPRT_DEFER 0x20 /* Defer issuing FDMI RPRT */ struct list_head fc_nodes; @@ -1059,6 +1060,7 @@ struct lpfc_hba { #define HBA_HBEAT_INP 0x4000000 /* mbox HBEAT is in progress */ #define HBA_HBEAT_TMO 0x8000000 /* HBEAT initiated after timeout */ #define HBA_FLOGI_OUTSTANDING 0x10000000 /* FLOGI is outstanding */ +#define HBA_RHBA_CMPL 0x20000000 /* RHBA FDMI command is successful */ struct completion *fw_dump_cmpl; /* cmpl event tracker for fw_dump */ uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/ diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 6f88fd0df8b0..b0775be31d5c 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -434,6 +434,7 @@ void lpfc_nvmet_buf_free(struct lpfc_hba *phba, void *virtp, dma_addr_t dma); void lpfc_in_buf_free(struct lpfc_hba *, struct lpfc_dmabuf *); void lpfc_rq_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp); +void lpfc_setup_fdmi_mask(struct lpfc_vport *vport); int lpfc_link_reset(struct lpfc_vport *vport); /* Function prototypes. */ diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 094199d1006a..9d36b20fb878 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -2168,6 +2168,41 @@ ns_cmd_exit: } /** + * lpfc_fdmi_rprt_defer - Check for any deferred FDMI RPRT commands + * @phba: Pointer to HBA context object. + * @mask: Initial port attributes mask + * + * This function checks to see if any vports have deferred their FDMI RPRT. + * A vports RPRT may be deferred if it is issued before the primary ports + * RHBA completes. + */ +static void +lpfc_fdmi_rprt_defer(struct lpfc_hba *phba, uint32_t mask) +{ + struct lpfc_vport **vports; + struct lpfc_vport *vport; + struct lpfc_nodelist *ndlp; + int i; + + phba->hba_flag |= HBA_RHBA_CMPL; + vports = lpfc_create_vport_work_array(phba); + if (vports) { + for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { + vport = vports[i]; + ndlp = lpfc_findnode_did(phba->pport, FDMI_DID); + if (!ndlp) + continue; + if (vport->ct_flags & FC_CT_RPRT_DEFER) { + vport->ct_flags &= ~FC_CT_RPRT_DEFER; + vport->fdmi_port_mask = mask; + lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPRT, 0); + } + } + } + lpfc_destroy_vport_work_array(phba, vports); +} + +/** * lpfc_cmpl_ct_disc_fdmi - Handle a discovery FDMI completion * @phba: Pointer to HBA context object. * @cmdiocb: Pointer to the command IOCBQ. @@ -2255,8 +2290,12 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, switch (cmd) { case SLI_MGMT_RHBA: if (vport->fdmi_hba_mask == LPFC_FDMI2_HBA_ATTR) { - /* Fallback to FDMI-1 */ + /* Fallback to FDMI-1 for HBA attributes */ vport->fdmi_hba_mask = LPFC_FDMI1_HBA_ATTR; + + /* If HBA attributes are FDMI1, so should + * port attributes be for consistency. + */ vport->fdmi_port_mask = LPFC_FDMI1_PORT_ATTR; /* Start over */ lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA, 0); @@ -2264,6 +2303,11 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, return; case SLI_MGMT_RPRT: + if (vport->port_type != LPFC_PHYSICAL_PORT) { + ndlp = lpfc_findnode_did(phba->pport, FDMI_DID); + if (!ndlp) + return; + } if (vport->fdmi_port_mask == LPFC_FDMI2_PORT_ATTR) { /* Fallback to FDMI-1 */ vport->fdmi_port_mask = LPFC_FDMI1_PORT_ATTR; @@ -2313,6 +2357,9 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, */ switch (cmd) { case SLI_MGMT_RHBA: + /* Check for any RPRTs deferred till after RHBA completes */ + lpfc_fdmi_rprt_defer(phba, vport->fdmi_port_mask); + lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPA, 0); break; @@ -2321,10 +2368,26 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, break; case SLI_MGMT_DPRT: - if (vport->port_type == LPFC_PHYSICAL_PORT) + if (vport->port_type == LPFC_PHYSICAL_PORT) { lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RHBA, 0); - else - lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPRT, 0); + } else { + ndlp = lpfc_findnode_did(phba->pport, FDMI_DID); + if (!ndlp) + return; + + /* Only issue a RPRT for the vport if the RHBA + * for the physical port completes successfully. + * We may have to defer the RPRT accordingly. + */ + if (phba->hba_flag & HBA_RHBA_CMPL) { + lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPRT, 0); + } else { + lpfc_printf_vlog(vport, KERN_INFO, + LOG_DISCOVERY, + "6078 RPRT deferred\n"); + vport->ct_flags |= FC_CT_RPRT_DEFER; + } + } break; case SLI_MGMT_RPA: if (vport->port_type == LPFC_PHYSICAL_PORT && @@ -2339,7 +2402,8 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, break; } - lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT, + lpfc_printf_log(phba, KERN_INFO, + LOG_DISCOVERY | LOG_CGN_MGMT, "6210 Issue Vendor MI FDMI %x\n", phba->sli4_hba.pc_sli4_params.mi_ver); @@ -2408,6 +2472,9 @@ lpfc_fdmi_change_check(struct lpfc_vport *vport) phba->link_flag &= ~LS_CT_VEN_RPA; lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA, 0); } else { + ndlp = lpfc_findnode_did(phba->pport, FDMI_DID); + if (!ndlp) + return; lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DPRT, 0); } @@ -2429,6 +2496,9 @@ lpfc_fdmi_change_check(struct lpfc_vport *vport) lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPA, LPFC_FDMI_PORT_ATTR_num_disc); } else { + ndlp = lpfc_findnode_did(phba->pport, FDMI_DID); + if (!ndlp) + return; lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPRT, LPFC_FDMI_PORT_ATTR_num_disc); } @@ -3501,8 +3571,10 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, /* FDMI request */ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, - "0218 FDMI Request Data: x%x x%x x%x\n", - vport->fc_flag, vport->port_state, cmdcode); + "0218 FDMI Request x%x mask x%x Data: x%x x%x x%x\n", + cmdcode, new_mask, vport->fdmi_port_mask, + vport->fc_flag, vport->port_state); + CtReq = (struct lpfc_sli_ct_request *)mp->virt; /* First populate the CT_IU preamble */ @@ -3571,6 +3643,12 @@ hba_out: break; case SLI_MGMT_RPRT: + if (vport->port_type != LPFC_PHYSICAL_PORT) { + ndlp = lpfc_findnode_did(phba->pport, FDMI_DID); + if (!ndlp) + return 0; + } + fallthrough; case SLI_MGMT_RPA: pab = (struct lpfc_fdmi_reg_portattr *)&CtReq->un.PortID; if (cmdcode == SLI_MGMT_RPRT) { @@ -3635,6 +3713,12 @@ port_out: rsp_size = FC_MAX_NS_RSP; fallthrough; case SLI_MGMT_DPRT: + if (vport->port_type != LPFC_PHYSICAL_PORT) { + ndlp = lpfc_findnode_did(phba->pport, FDMI_DID); + if (!ndlp) + return 0; + } + fallthrough; case SLI_MGMT_DPA: pe = (struct lpfc_fdmi_port_entry *)&CtReq->un.PortID; memcpy((uint8_t *)&pe->PortName, diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 3ab22ac49e49..fb36f26170e4 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1359,6 +1359,7 @@ lpfc_linkup_port(struct lpfc_vport *vport) vport->fc_flag |= FC_NDISC_ACTIVE; vport->fc_ns_retry = 0; spin_unlock_irq(shost->host_lock); + lpfc_setup_fdmi_mask(vport); lpfc_linkup_cleanup_nodes(vport); } @@ -1390,8 +1391,8 @@ lpfc_linkup(struct lpfc_hba *phba) phba->pport->rcv_flogi_cnt = 0; spin_unlock_irq(shost->host_lock); - /* reinitialize initial FLOGI flag */ - phba->hba_flag &= ~(HBA_FLOGI_ISSUED); + /* reinitialize initial HBA flag */ + phba->hba_flag &= ~(HBA_FLOGI_ISSUED | HBA_RHBA_CMPL); phba->defer_flogi_acc_flag = false; return 0; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 39267016f339..0dedb7cf621b 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -9003,6 +9003,36 @@ lpfc_hba_free(struct lpfc_hba *phba) } /** + * lpfc_setup_fdmi_mask - Setup initial FDMI mask for HBA and Port attributes + * @vport: pointer to lpfc vport data structure. + * + * This routine is will setup initial FDMI attribute masks for + * FDMI2 or SmartSAN depending on module parameters. The driver will attempt + * to get these attributes first before falling back, the attribute + * fallback hierarchy is SmartSAN -> FDMI2 -> FMDI1 + **/ +void +lpfc_setup_fdmi_mask(struct lpfc_vport *vport) +{ + struct lpfc_hba *phba = vport->phba; + + vport->load_flag |= FC_ALLOW_FDMI; + if (phba->cfg_enable_SmartSAN || + phba->cfg_fdmi_on == LPFC_FDMI_SUPPORT) { + /* Setup appropriate attribute masks */ + vport->fdmi_hba_mask = LPFC_FDMI2_HBA_ATTR; + if (phba->cfg_enable_SmartSAN) + vport->fdmi_port_mask = LPFC_FDMI2_SMART_ATTR; + else + vport->fdmi_port_mask = LPFC_FDMI2_PORT_ATTR; + } + + lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, + "6077 Setup FDMI mask: hba x%x port x%x\n", + vport->fdmi_hba_mask, vport->fdmi_port_mask); +} + +/** * lpfc_create_shost - Create hba physical port with associated scsi host. * @phba: pointer to lpfc hba data structure. * @@ -9045,21 +9075,12 @@ lpfc_create_shost(struct lpfc_hba *phba) /* Put reference to SCSI host to driver's device private data */ pci_set_drvdata(phba->pcidev, shost); + lpfc_setup_fdmi_mask(vport); + /* * At this point we are fully registered with PSA. In addition, * any initial discovery should be completed. */ - vport->load_flag |= FC_ALLOW_FDMI; - if (phba->cfg_enable_SmartSAN || - (phba->cfg_fdmi_on == LPFC_FDMI_SUPPORT)) { - - /* Setup appropriate attribute masks */ - vport->fdmi_hba_mask = LPFC_FDMI2_HBA_ATTR; - if (phba->cfg_enable_SmartSAN) - vport->fdmi_port_mask = LPFC_FDMI2_SMART_ATTR; - else - vport->fdmi_port_mask = LPFC_FDMI2_PORT_ATTR; - } return 0; } |