scsi: lpfc: Reregister FPIN types if ELS_RDF is received from fabric controller
FC-LS-5 specifies that a received RDF implies a possible change to fabric supported diagnostic functions. Endpoints are to re-perform the RDF exchange with the fabric to enable possible new features or adapt to changes in values. This patch adds the logic to RDF receive to re-perform the RDF exchange with the switch. Link: https://lore.kernel.org/r/20210514195559.119853-11-jsmart2021@gmail.com Co-developed-by: Justin Tee <justin.tee@broadcom.com> Signed-off-by: Justin Tee <justin.tee@broadcom.com> Signed-off-by: James Smart <jsmart2021@gmail.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Родитель
3e49af9393
Коммит
8eced80707
|
@ -266,6 +266,7 @@ struct lpfc_stats {
|
|||
uint32_t elsRcvECHO;
|
||||
uint32_t elsRcvLCB;
|
||||
uint32_t elsRcvRDP;
|
||||
uint32_t elsRcvRDF;
|
||||
uint32_t elsXmitFLOGI;
|
||||
uint32_t elsXmitFDISC;
|
||||
uint32_t elsXmitPLOGI;
|
||||
|
|
|
@ -3670,6 +3670,43 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_els_rcv_rdf - Receive RDF ELS request from the fabric.
|
||||
* @vport: pointer to a host virtual N_Port data structure.
|
||||
* @cmdiocb: pointer to lpfc command iocb data structure.
|
||||
* @ndlp: pointer to a node-list data structure.
|
||||
*
|
||||
* A received RDF implies a possible change to fabric supported diagnostic
|
||||
* functions. This routine sends LS_ACC and then has the Nx_Port issue a new
|
||||
* RDF request to reregister for supported diagnostic functions.
|
||||
*
|
||||
* Return code
|
||||
* 0 - Success
|
||||
* -EIO - Failed to process received RDF
|
||||
**/
|
||||
static int
|
||||
lpfc_els_rcv_rdf(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||
struct lpfc_nodelist *ndlp)
|
||||
{
|
||||
/* Send LS_ACC */
|
||||
if (lpfc_els_rsp_acc(vport, ELS_CMD_RDF, cmdiocb, ndlp, NULL)) {
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
|
||||
"1623 Failed to RDF_ACC from x%x for x%x\n",
|
||||
ndlp->nlp_DID, vport->fc_myDID);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Issue new RDF for reregistering */
|
||||
if (lpfc_issue_els_rdf(vport, 0)) {
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
|
||||
"2623 Failed to re register RDF for x%x\n",
|
||||
vport->fc_myDID);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_cancel_retry_delay_tmo - Cancel the timer with delayed iocb-cmd retry
|
||||
* @vport: pointer to a host virtual N_Port data structure.
|
||||
|
@ -4803,6 +4840,7 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
|
|||
uint16_t cmdsize;
|
||||
int rc;
|
||||
ELS_PKT *els_pkt_ptr;
|
||||
struct fc_els_rdf_resp *rdf_resp;
|
||||
|
||||
oldcmd = &oldiocb->iocb;
|
||||
|
||||
|
@ -4914,6 +4952,29 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
|
|||
"Issue ACC PRLO: did:x%x flg:x%x",
|
||||
ndlp->nlp_DID, ndlp->nlp_flag, 0);
|
||||
break;
|
||||
case ELS_CMD_RDF:
|
||||
cmdsize = sizeof(*rdf_resp);
|
||||
elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry,
|
||||
ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
|
||||
if (!elsiocb)
|
||||
return 1;
|
||||
|
||||
icmd = &elsiocb->iocb;
|
||||
icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */
|
||||
icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id;
|
||||
pcmd = (((struct lpfc_dmabuf *)elsiocb->context2)->virt);
|
||||
rdf_resp = (struct fc_els_rdf_resp *)pcmd;
|
||||
memset(rdf_resp, 0, sizeof(*rdf_resp));
|
||||
rdf_resp->acc_hdr.la_cmd = ELS_LS_ACC;
|
||||
|
||||
/* FC-LS-5 specifies desc_list_len shall be set to 12 */
|
||||
rdf_resp->desc_list_len = cpu_to_be32(12);
|
||||
|
||||
/* FC-LS-5 specifies LS REQ Information descriptor */
|
||||
rdf_resp->lsri.desc_tag = cpu_to_be32(1);
|
||||
rdf_resp->lsri.desc_len = cpu_to_be32(sizeof(u32));
|
||||
rdf_resp->lsri.rqst_w0.cmd = ELS_RDF;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
@ -9027,6 +9088,20 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|||
|
||||
/* There are no replies, so no rjt codes */
|
||||
break;
|
||||
case ELS_CMD_RDF:
|
||||
phba->fc_stat.elsRcvRDF++;
|
||||
/* Accept RDF only from fabric controller */
|
||||
if (did != Fabric_Cntl_DID) {
|
||||
lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
|
||||
"1115 Received RDF from invalid DID "
|
||||
"x%x\n", did);
|
||||
rjt_err = LSRJT_PROTOCOL_ERR;
|
||||
rjt_exp = LSEXP_NOTHING_MORE;
|
||||
goto lsrjt;
|
||||
}
|
||||
|
||||
lpfc_els_rcv_rdf(vport, elsiocb, ndlp);
|
||||
break;
|
||||
default:
|
||||
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||
"RCV ELS cmd: cmd:x%x did:x%x/ste:x%x",
|
||||
|
|
Загрузка…
Ссылка в новой задаче