scsi: lpfc: Implement GID_PT on Nameserver query to support faster failover
The switches seem to respond faster to GID_PT vs GID_FT NameServer queries. Add support for GID_PT to be used over GID_FT to enable faster storage failover detection. Includes addition of new module parameter to select between GID_PT and GID_FT (GID_FT is default). Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com> Signed-off-by: James Smart <jsmart2021@gmail.com> Reviewed-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
此提交包含在:
@@ -831,6 +831,198 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
struct lpfc_iocbq *rspiocb)
|
||||
{
|
||||
struct lpfc_vport *vport = cmdiocb->vport;
|
||||
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
||||
IOCB_t *irsp;
|
||||
struct lpfc_dmabuf *outp;
|
||||
struct lpfc_dmabuf *inp;
|
||||
struct lpfc_sli_ct_request *CTrsp;
|
||||
struct lpfc_sli_ct_request *CTreq;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
int rc;
|
||||
|
||||
/* First save ndlp, before we overwrite it */
|
||||
ndlp = cmdiocb->context_un.ndlp;
|
||||
|
||||
/* we pass cmdiocb to state machine which needs rspiocb as well */
|
||||
cmdiocb->context_un.rsp_iocb = rspiocb;
|
||||
inp = (struct lpfc_dmabuf *)cmdiocb->context1;
|
||||
outp = (struct lpfc_dmabuf *)cmdiocb->context2;
|
||||
irsp = &rspiocb->iocb;
|
||||
|
||||
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
|
||||
"GID_PT cmpl: status:x%x/x%x rtry:%d",
|
||||
irsp->ulpStatus, irsp->un.ulpWord[4],
|
||||
vport->fc_ns_retry);
|
||||
|
||||
/* Don't bother processing response if vport is being torn down. */
|
||||
if (vport->load_flag & FC_UNLOADING) {
|
||||
if (vport->fc_flag & FC_RSCN_MODE)
|
||||
lpfc_els_flush_rscn(vport);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (lpfc_els_chk_latt(vport)) {
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
|
||||
"4108 Link event during NS query\n");
|
||||
if (vport->fc_flag & FC_RSCN_MODE)
|
||||
lpfc_els_flush_rscn(vport);
|
||||
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
|
||||
goto out;
|
||||
}
|
||||
if (lpfc_error_lost_link(irsp)) {
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
|
||||
"4101 NS query failed due to link event\n");
|
||||
if (vport->fc_flag & FC_RSCN_MODE)
|
||||
lpfc_els_flush_rscn(vport);
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_irq(shost->host_lock);
|
||||
if (vport->fc_flag & FC_RSCN_DEFERRED) {
|
||||
vport->fc_flag &= ~FC_RSCN_DEFERRED;
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
|
||||
/* This is a GID_PT completing so the gidft_inp counter was
|
||||
* incremented before the GID_PT was issued to the wire.
|
||||
*/
|
||||
vport->gidft_inp--;
|
||||
|
||||
/*
|
||||
* Skip processing the NS response
|
||||
* Re-issue the NS cmd
|
||||
*/
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
|
||||
"4102 Process Deferred RSCN Data: x%x x%x\n",
|
||||
vport->fc_flag, vport->fc_rscn_id_cnt);
|
||||
lpfc_els_handle_rscn(vport);
|
||||
|
||||
goto out;
|
||||
}
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
|
||||
if (irsp->ulpStatus) {
|
||||
/* Check for retry */
|
||||
if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
|
||||
if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
|
||||
(irsp->un.ulpWord[4] & IOERR_PARAM_MASK) !=
|
||||
IOERR_NO_RESOURCES)
|
||||
vport->fc_ns_retry++;
|
||||
|
||||
/* CT command is being retried */
|
||||
vport->gidft_inp--;
|
||||
rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_PT,
|
||||
vport->fc_ns_retry, GID_PT_N_PORT);
|
||||
if (rc == 0)
|
||||
goto out;
|
||||
}
|
||||
if (vport->fc_flag & FC_RSCN_MODE)
|
||||
lpfc_els_flush_rscn(vport);
|
||||
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
|
||||
"4103 GID_FT Query error: 0x%x 0x%x\n",
|
||||
irsp->ulpStatus, vport->fc_ns_retry);
|
||||
} else {
|
||||
/* Good status, continue checking */
|
||||
CTreq = (struct lpfc_sli_ct_request *)inp->virt;
|
||||
CTrsp = (struct lpfc_sli_ct_request *)outp->virt;
|
||||
if (CTrsp->CommandResponse.bits.CmdRsp ==
|
||||
cpu_to_be16(SLI_CT_RESPONSE_FS_ACC)) {
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
|
||||
"4105 NameServer Rsp Data: x%x x%x\n",
|
||||
vport->fc_flag,
|
||||
CTreq->un.gid.Fc4Type);
|
||||
|
||||
lpfc_ns_rsp(vport,
|
||||
outp,
|
||||
CTreq->un.gid.Fc4Type,
|
||||
(uint32_t)(irsp->un.genreq64.bdl.bdeSize));
|
||||
} else if (CTrsp->CommandResponse.bits.CmdRsp ==
|
||||
be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
|
||||
/* NameServer Rsp Error */
|
||||
if ((CTrsp->ReasonCode == SLI_CT_UNABLE_TO_PERFORM_REQ)
|
||||
&& (CTrsp->Explanation == SLI_CT_NO_FC4_TYPES)) {
|
||||
lpfc_printf_vlog(
|
||||
vport, KERN_INFO, LOG_DISCOVERY,
|
||||
"4106 No NameServer Entries "
|
||||
"Data: x%x x%x x%x x%x\n",
|
||||
CTrsp->CommandResponse.bits.CmdRsp,
|
||||
(uint32_t)CTrsp->ReasonCode,
|
||||
(uint32_t)CTrsp->Explanation,
|
||||
vport->fc_flag);
|
||||
|
||||
lpfc_debugfs_disc_trc(
|
||||
vport, LPFC_DISC_TRC_CT,
|
||||
"GID_PT no entry cmd:x%x rsn:x%x exp:x%x",
|
||||
(uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
|
||||
(uint32_t)CTrsp->ReasonCode,
|
||||
(uint32_t)CTrsp->Explanation);
|
||||
} else {
|
||||
lpfc_printf_vlog(
|
||||
vport, KERN_INFO, LOG_DISCOVERY,
|
||||
"4107 NameServer Rsp Error "
|
||||
"Data: x%x x%x x%x x%x\n",
|
||||
CTrsp->CommandResponse.bits.CmdRsp,
|
||||
(uint32_t)CTrsp->ReasonCode,
|
||||
(uint32_t)CTrsp->Explanation,
|
||||
vport->fc_flag);
|
||||
|
||||
lpfc_debugfs_disc_trc(
|
||||
vport, LPFC_DISC_TRC_CT,
|
||||
"GID_PT rsp err1 cmd:x%x rsn:x%x exp:x%x",
|
||||
(uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
|
||||
(uint32_t)CTrsp->ReasonCode,
|
||||
(uint32_t)CTrsp->Explanation);
|
||||
}
|
||||
} else {
|
||||
/* NameServer Rsp Error */
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
|
||||
"4109 NameServer Rsp Error "
|
||||
"Data: x%x x%x x%x x%x\n",
|
||||
CTrsp->CommandResponse.bits.CmdRsp,
|
||||
(uint32_t)CTrsp->ReasonCode,
|
||||
(uint32_t)CTrsp->Explanation,
|
||||
vport->fc_flag);
|
||||
|
||||
lpfc_debugfs_disc_trc(
|
||||
vport, LPFC_DISC_TRC_CT,
|
||||
"GID_PT rsp err2 cmd:x%x rsn:x%x exp:x%x",
|
||||
(uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
|
||||
(uint32_t)CTrsp->ReasonCode,
|
||||
(uint32_t)CTrsp->Explanation);
|
||||
}
|
||||
vport->gidft_inp--;
|
||||
}
|
||||
/* Link up / RSCN discovery */
|
||||
if ((vport->num_disc_nodes == 0) &&
|
||||
(vport->gidft_inp == 0)) {
|
||||
/*
|
||||
* The driver has cycled through all Nports in the RSCN payload.
|
||||
* Complete the handling by cleaning up and marking the
|
||||
* current driver state.
|
||||
*/
|
||||
if (vport->port_state >= LPFC_DISC_AUTH) {
|
||||
if (vport->fc_flag & FC_RSCN_MODE) {
|
||||
lpfc_els_flush_rscn(vport);
|
||||
spin_lock_irq(shost->host_lock);
|
||||
vport->fc_flag |= FC_RSCN_MODE; /* RSCN still */
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
} else {
|
||||
lpfc_els_flush_rscn(vport);
|
||||
}
|
||||
}
|
||||
|
||||
lpfc_disc_start(vport);
|
||||
}
|
||||
out:
|
||||
cmdiocb->context_un.ndlp = ndlp; /* Now restore ndlp for free */
|
||||
lpfc_ct_free_iocb(phba, cmdiocb);
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||
struct lpfc_iocbq *rspiocb)
|
||||
@@ -1365,6 +1557,8 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
|
||||
bpl->tus.f.bdeFlags = 0;
|
||||
if (cmdcode == SLI_CTNS_GID_FT)
|
||||
bpl->tus.f.bdeSize = GID_REQUEST_SZ;
|
||||
else if (cmdcode == SLI_CTNS_GID_PT)
|
||||
bpl->tus.f.bdeSize = GID_REQUEST_SZ;
|
||||
else if (cmdcode == SLI_CTNS_GFF_ID)
|
||||
bpl->tus.f.bdeSize = GFF_REQUEST_SZ;
|
||||
else if (cmdcode == SLI_CTNS_GFT_ID)
|
||||
@@ -1405,6 +1599,18 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
|
||||
rsp_size = FC_MAX_NS_RSP;
|
||||
break;
|
||||
|
||||
case SLI_CTNS_GID_PT:
|
||||
CtReq->CommandResponse.bits.CmdRsp =
|
||||
cpu_to_be16(SLI_CTNS_GID_PT);
|
||||
CtReq->un.gid.PortType = context;
|
||||
|
||||
if (vport->port_state < LPFC_NS_QRY)
|
||||
vport->port_state = LPFC_NS_QRY;
|
||||
lpfc_set_disctmo(vport);
|
||||
cmpl = lpfc_cmpl_ct_cmd_gid_pt;
|
||||
rsp_size = FC_MAX_NS_RSP;
|
||||
break;
|
||||
|
||||
case SLI_CTNS_GFF_ID:
|
||||
CtReq->CommandResponse.bits.CmdRsp =
|
||||
cpu_to_be16(SLI_CTNS_GFF_ID);
|
||||
|
新增問題並參考
封鎖使用者