|
@@ -517,6 +517,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
|
|
if (sp->cmn.edtovResolution) /* E_D_TOV ticks are in nanoseconds */
|
|
|
phba->fc_edtov = (phba->fc_edtov + 999999) / 1000000;
|
|
|
|
|
|
+ phba->fc_edtovResol = sp->cmn.edtovResolution;
|
|
|
phba->fc_ratov = (be32_to_cpu(sp->cmn.w2.r_a_tov) + 999) / 1000;
|
|
|
|
|
|
if (phba->fc_topology == TOPOLOGY_LOOP) {
|
|
@@ -3927,6 +3928,64 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * lpfc_els_rsp_echo_acc - Issue echo acc response
|
|
|
+ * @vport: pointer to a virtual N_Port data structure.
|
|
|
+ * @data: pointer to echo data to return in the accept.
|
|
|
+ * @oldiocb: pointer to the original lpfc command iocb data structure.
|
|
|
+ * @ndlp: pointer to a node-list data structure.
|
|
|
+ *
|
|
|
+ * Return code
|
|
|
+ * 0 - Successfully issued acc echo response
|
|
|
+ * 1 - Failed to issue acc echo response
|
|
|
+ **/
|
|
|
+static int
|
|
|
+lpfc_els_rsp_echo_acc(struct lpfc_vport *vport, uint8_t *data,
|
|
|
+ struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
|
|
|
+{
|
|
|
+ struct lpfc_hba *phba = vport->phba;
|
|
|
+ struct lpfc_iocbq *elsiocb;
|
|
|
+ struct lpfc_sli *psli;
|
|
|
+ uint8_t *pcmd;
|
|
|
+ uint16_t cmdsize;
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ psli = &phba->sli;
|
|
|
+ cmdsize = oldiocb->iocb.unsli3.rcvsli3.acc_len;
|
|
|
+
|
|
|
+ elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
|
|
|
+ ndlp->nlp_DID, ELS_CMD_ACC);
|
|
|
+ if (!elsiocb)
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ elsiocb->iocb.ulpContext = oldiocb->iocb.ulpContext; /* Xri */
|
|
|
+ /* Xmit ECHO ACC response tag <ulpIoTag> */
|
|
|
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
|
|
|
+ "2876 Xmit ECHO ACC response tag x%x xri x%x\n",
|
|
|
+ elsiocb->iotag, elsiocb->iocb.ulpContext);
|
|
|
+ pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
|
|
|
+ *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
|
|
|
+ pcmd += sizeof(uint32_t);
|
|
|
+ memcpy(pcmd, data, cmdsize - sizeof(uint32_t));
|
|
|
+
|
|
|
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
|
|
|
+ "Issue ACC ECHO: did:x%x flg:x%x",
|
|
|
+ ndlp->nlp_DID, ndlp->nlp_flag, 0);
|
|
|
+
|
|
|
+ phba->fc_stat.elsXmitACC++;
|
|
|
+ elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
|
|
|
+ lpfc_nlp_put(ndlp);
|
|
|
+ elsiocb->context1 = NULL; /* Don't need ndlp for cmpl,
|
|
|
+ * it could be freed */
|
|
|
+
|
|
|
+ rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
|
|
|
+ if (rc == IOCB_ERROR) {
|
|
|
+ lpfc_els_free_iocb(phba, elsiocb);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* lpfc_els_disc_adisc - Issue remaining adisc iocbs to npr nodes of a vport
|
|
|
* @vport: pointer to a host virtual N_Port data structure.
|
|
@@ -4685,6 +4744,30 @@ lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * lpfc_els_rcv_echo - Process an unsolicited echo iocb
|
|
|
+ * @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.
|
|
|
+ *
|
|
|
+ * Return code
|
|
|
+ * 0 - Successfully processed echo iocb (currently always return 0)
|
|
|
+ **/
|
|
|
+static int
|
|
|
+lpfc_els_rcv_echo(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
|
|
+ struct lpfc_nodelist *ndlp)
|
|
|
+{
|
|
|
+ uint8_t *pcmd;
|
|
|
+
|
|
|
+ pcmd = (uint8_t *) (((struct lpfc_dmabuf *) cmdiocb->context2)->virt);
|
|
|
+
|
|
|
+ /* skip over first word of echo command to find echo data */
|
|
|
+ pcmd += sizeof(uint32_t);
|
|
|
+
|
|
|
+ lpfc_els_rsp_echo_acc(vport, pcmd, cmdiocb, ndlp);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* lpfc_els_rcv_lirr - Process an unsolicited lirr iocb
|
|
|
* @vport: pointer to a host virtual N_Port data structure.
|
|
@@ -4736,6 +4819,89 @@ lpfc_els_rcv_rrq(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
|
|
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * lpfc_els_rsp_rls_acc - Completion callbk func for MBX_READ_LNK_STAT mbox cmd
|
|
|
+ * @phba: pointer to lpfc hba data structure.
|
|
|
+ * @pmb: pointer to the driver internal queue element for mailbox command.
|
|
|
+ *
|
|
|
+ * This routine is the completion callback function for the MBX_READ_LNK_STAT
|
|
|
+ * mailbox command. This callback function is to actually send the Accept
|
|
|
+ * (ACC) response to a Read Port Status (RPS) unsolicited IOCB event. It
|
|
|
+ * collects the link statistics from the completion of the MBX_READ_LNK_STAT
|
|
|
+ * mailbox command, constructs the RPS response with the link statistics
|
|
|
+ * collected, and then invokes the lpfc_sli_issue_iocb() routine to send ACC
|
|
|
+ * response to the RPS.
|
|
|
+ *
|
|
|
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
|
|
|
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
|
|
|
+ * will be stored into the context1 field of the IOCB for the completion
|
|
|
+ * callback function to the RPS Accept Response ELS IOCB command.
|
|
|
+ *
|
|
|
+ **/
|
|
|
+static void
|
|
|
+lpfc_els_rsp_rls_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
|
|
+{
|
|
|
+ MAILBOX_t *mb;
|
|
|
+ IOCB_t *icmd;
|
|
|
+ struct RLS_RSP *rls_rsp;
|
|
|
+ uint8_t *pcmd;
|
|
|
+ struct lpfc_iocbq *elsiocb;
|
|
|
+ struct lpfc_nodelist *ndlp;
|
|
|
+ uint16_t xri;
|
|
|
+ uint32_t cmdsize;
|
|
|
+
|
|
|
+ mb = &pmb->u.mb;
|
|
|
+
|
|
|
+ ndlp = (struct lpfc_nodelist *) pmb->context2;
|
|
|
+ xri = (uint16_t) ((unsigned long)(pmb->context1));
|
|
|
+ pmb->context1 = NULL;
|
|
|
+ pmb->context2 = NULL;
|
|
|
+
|
|
|
+ if (mb->mbxStatus) {
|
|
|
+ mempool_free(pmb, phba->mbox_mem_pool);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ cmdsize = sizeof(struct RLS_RSP) + sizeof(uint32_t);
|
|
|
+ mempool_free(pmb, phba->mbox_mem_pool);
|
|
|
+ elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize,
|
|
|
+ lpfc_max_els_tries, ndlp,
|
|
|
+ ndlp->nlp_DID, ELS_CMD_ACC);
|
|
|
+
|
|
|
+ /* Decrement the ndlp reference count from previous mbox command */
|
|
|
+ lpfc_nlp_put(ndlp);
|
|
|
+
|
|
|
+ if (!elsiocb)
|
|
|
+ return;
|
|
|
+
|
|
|
+ icmd = &elsiocb->iocb;
|
|
|
+ icmd->ulpContext = xri;
|
|
|
+
|
|
|
+ pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
|
|
|
+ *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
|
|
|
+ pcmd += sizeof(uint32_t); /* Skip past command */
|
|
|
+ rls_rsp = (struct RLS_RSP *)pcmd;
|
|
|
+
|
|
|
+ rls_rsp->linkFailureCnt = cpu_to_be32(mb->un.varRdLnk.linkFailureCnt);
|
|
|
+ rls_rsp->lossSyncCnt = cpu_to_be32(mb->un.varRdLnk.lossSyncCnt);
|
|
|
+ rls_rsp->lossSignalCnt = cpu_to_be32(mb->un.varRdLnk.lossSignalCnt);
|
|
|
+ rls_rsp->primSeqErrCnt = cpu_to_be32(mb->un.varRdLnk.primSeqErrCnt);
|
|
|
+ rls_rsp->invalidXmitWord = cpu_to_be32(mb->un.varRdLnk.invalidXmitWord);
|
|
|
+ rls_rsp->crcCnt = cpu_to_be32(mb->un.varRdLnk.crcCnt);
|
|
|
+
|
|
|
+ /* Xmit ELS RLS ACC response tag <ulpIoTag> */
|
|
|
+ lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_ELS,
|
|
|
+ "2874 Xmit ELS RLS ACC response tag x%x xri x%x, "
|
|
|
+ "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
|
|
|
+ elsiocb->iotag, elsiocb->iocb.ulpContext,
|
|
|
+ ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
|
|
|
+ ndlp->nlp_rpi);
|
|
|
+ elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
|
|
|
+ phba->fc_stat.elsXmitACC++;
|
|
|
+ if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == IOCB_ERROR)
|
|
|
+ lpfc_els_free_iocb(phba, elsiocb);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* lpfc_els_rsp_rps_acc - Completion callbk func for MBX_READ_LNK_STAT mbox cmd
|
|
|
* @phba: pointer to lpfc hba data structure.
|
|
@@ -4829,7 +4995,155 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * lpfc_els_rcv_rps - Process an unsolicited rps iocb
|
|
|
+ * lpfc_els_rcv_rls - Process an unsolicited rls iocb
|
|
|
+ * @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.
|
|
|
+ *
|
|
|
+ * This routine processes Read Port Status (RPL) IOCB received as an
|
|
|
+ * ELS unsolicited event. It first checks the remote port state. If the
|
|
|
+ * remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE
|
|
|
+ * state, it invokes the lpfc_els_rsl_reject() routine to send the reject
|
|
|
+ * response. Otherwise, it issue the MBX_READ_LNK_STAT mailbox command
|
|
|
+ * for reading the HBA link statistics. It is for the callback function,
|
|
|
+ * lpfc_els_rsp_rls_acc(), set to the MBX_READ_LNK_STAT mailbox command
|
|
|
+ * to actually sending out RPL Accept (ACC) response.
|
|
|
+ *
|
|
|
+ * Return codes
|
|
|
+ * 0 - Successfully processed rls iocb (currently always return 0)
|
|
|
+ **/
|
|
|
+static int
|
|
|
+lpfc_els_rcv_rls(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
|
|
+ struct lpfc_nodelist *ndlp)
|
|
|
+{
|
|
|
+ struct lpfc_hba *phba = vport->phba;
|
|
|
+ LPFC_MBOXQ_t *mbox;
|
|
|
+ struct lpfc_dmabuf *pcmd;
|
|
|
+ struct ls_rjt stat;
|
|
|
+
|
|
|
+ if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
|
|
|
+ (ndlp->nlp_state != NLP_STE_MAPPED_NODE))
|
|
|
+ /* reject the unsolicited RPS request and done with it */
|
|
|
+ goto reject_out;
|
|
|
+
|
|
|
+ pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
|
|
|
+
|
|
|
+ mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC);
|
|
|
+ if (mbox) {
|
|
|
+ lpfc_read_lnk_stat(phba, mbox);
|
|
|
+ mbox->context1 =
|
|
|
+ (void *)((unsigned long) cmdiocb->iocb.ulpContext);
|
|
|
+ mbox->context2 = lpfc_nlp_get(ndlp);
|
|
|
+ mbox->vport = vport;
|
|
|
+ mbox->mbox_cmpl = lpfc_els_rsp_rls_acc;
|
|
|
+ if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT)
|
|
|
+ != MBX_NOT_FINISHED)
|
|
|
+ /* Mbox completion will send ELS Response */
|
|
|
+ return 0;
|
|
|
+ /* Decrement reference count used for the failed mbox
|
|
|
+ * command.
|
|
|
+ */
|
|
|
+ lpfc_nlp_put(ndlp);
|
|
|
+ mempool_free(mbox, phba->mbox_mem_pool);
|
|
|
+ }
|
|
|
+reject_out:
|
|
|
+ /* issue rejection response */
|
|
|
+ stat.un.b.lsRjtRsvd0 = 0;
|
|
|
+ stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
|
|
+ stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
|
|
|
+ stat.un.b.vendorUnique = 0;
|
|
|
+ lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * lpfc_els_rcv_rtv - Process an unsolicited rtv iocb
|
|
|
+ * @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.
|
|
|
+ *
|
|
|
+ * This routine processes Read Timout Value (RTV) IOCB received as an
|
|
|
+ * ELS unsolicited event. It first checks the remote port state. If the
|
|
|
+ * remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE
|
|
|
+ * state, it invokes the lpfc_els_rsl_reject() routine to send the reject
|
|
|
+ * response. Otherwise, it sends the Accept(ACC) response to a Read Timeout
|
|
|
+ * Value (RTV) unsolicited IOCB event.
|
|
|
+ *
|
|
|
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
|
|
|
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
|
|
|
+ * will be stored into the context1 field of the IOCB for the completion
|
|
|
+ * callback function to the RPS Accept Response ELS IOCB command.
|
|
|
+ *
|
|
|
+ * Return codes
|
|
|
+ * 0 - Successfully processed rtv iocb (currently always return 0)
|
|
|
+ **/
|
|
|
+static int
|
|
|
+lpfc_els_rcv_rtv(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
|
|
+ struct lpfc_nodelist *ndlp)
|
|
|
+{
|
|
|
+ struct lpfc_hba *phba = vport->phba;
|
|
|
+ struct ls_rjt stat;
|
|
|
+ struct RTV_RSP *rtv_rsp;
|
|
|
+ uint8_t *pcmd;
|
|
|
+ struct lpfc_iocbq *elsiocb;
|
|
|
+ uint32_t cmdsize;
|
|
|
+
|
|
|
+
|
|
|
+ if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
|
|
|
+ (ndlp->nlp_state != NLP_STE_MAPPED_NODE))
|
|
|
+ /* reject the unsolicited RPS request and done with it */
|
|
|
+ goto reject_out;
|
|
|
+
|
|
|
+ cmdsize = sizeof(struct RTV_RSP) + sizeof(uint32_t);
|
|
|
+ elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize,
|
|
|
+ lpfc_max_els_tries, ndlp,
|
|
|
+ ndlp->nlp_DID, ELS_CMD_ACC);
|
|
|
+
|
|
|
+ if (!elsiocb)
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
|
|
|
+ *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
|
|
|
+ pcmd += sizeof(uint32_t); /* Skip past command */
|
|
|
+
|
|
|
+ /* use the command's xri in the response */
|
|
|
+ elsiocb->iocb.ulpContext = cmdiocb->iocb.ulpContext;
|
|
|
+
|
|
|
+ rtv_rsp = (struct RTV_RSP *)pcmd;
|
|
|
+
|
|
|
+ /* populate RTV payload */
|
|
|
+ rtv_rsp->ratov = cpu_to_be32(phba->fc_ratov * 1000); /* report msecs */
|
|
|
+ rtv_rsp->edtov = cpu_to_be32(phba->fc_edtov);
|
|
|
+ bf_set(qtov_edtovres, rtv_rsp, phba->fc_edtovResol ? 1 : 0);
|
|
|
+ bf_set(qtov_rttov, rtv_rsp, 0); /* Field is for FC ONLY */
|
|
|
+ rtv_rsp->qtov = cpu_to_be32(rtv_rsp->qtov);
|
|
|
+
|
|
|
+ /* Xmit ELS RLS ACC response tag <ulpIoTag> */
|
|
|
+ lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_ELS,
|
|
|
+ "2875 Xmit ELS RTV ACC response tag x%x xri x%x, "
|
|
|
+ "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x, "
|
|
|
+ "Data: x%x x%x x%x\n",
|
|
|
+ elsiocb->iotag, elsiocb->iocb.ulpContext,
|
|
|
+ ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
|
|
|
+ ndlp->nlp_rpi,
|
|
|
+ rtv_rsp->ratov, rtv_rsp->edtov, rtv_rsp->qtov);
|
|
|
+ elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
|
|
|
+ phba->fc_stat.elsXmitACC++;
|
|
|
+ if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == IOCB_ERROR)
|
|
|
+ lpfc_els_free_iocb(phba, elsiocb);
|
|
|
+ return 0;
|
|
|
+
|
|
|
+reject_out:
|
|
|
+ /* issue rejection response */
|
|
|
+ stat.un.b.lsRjtRsvd0 = 0;
|
|
|
+ stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
|
|
+ stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
|
|
|
+ stat.un.b.vendorUnique = 0;
|
|
|
+ lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/* lpfc_els_rcv_rps - Process an unsolicited rps iocb
|
|
|
* @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.
|
|
@@ -5019,7 +5333,6 @@ lpfc_els_rcv_rpl(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
|
|
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
|
|
|
lp = (uint32_t *) pcmd->virt;
|
|
|
rpl = (RPL *) (lp + 1);
|
|
|
-
|
|
|
maxsize = be32_to_cpu(rpl->maxsize);
|
|
|
|
|
|
/* We support only one port */
|
|
@@ -5838,6 +6151,16 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|
|
if (newnode)
|
|
|
lpfc_nlp_put(ndlp);
|
|
|
break;
|
|
|
+ case ELS_CMD_RLS:
|
|
|
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
|
|
+ "RCV RLS: did:x%x/ste:x%x flg:x%x",
|
|
|
+ did, vport->port_state, ndlp->nlp_flag);
|
|
|
+
|
|
|
+ phba->fc_stat.elsRcvRLS++;
|
|
|
+ lpfc_els_rcv_rls(vport, elsiocb, ndlp);
|
|
|
+ if (newnode)
|
|
|
+ lpfc_nlp_put(ndlp);
|
|
|
+ break;
|
|
|
case ELS_CMD_RPS:
|
|
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
|
|
"RCV RPS: did:x%x/ste:x%x flg:x%x",
|
|
@@ -5868,6 +6191,15 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|
|
if (newnode)
|
|
|
lpfc_nlp_put(ndlp);
|
|
|
break;
|
|
|
+ case ELS_CMD_RTV:
|
|
|
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
|
|
+ "RCV RTV: did:x%x/ste:x%x flg:x%x",
|
|
|
+ did, vport->port_state, ndlp->nlp_flag);
|
|
|
+ phba->fc_stat.elsRcvRTV++;
|
|
|
+ lpfc_els_rcv_rtv(vport, elsiocb, ndlp);
|
|
|
+ if (newnode)
|
|
|
+ lpfc_nlp_put(ndlp);
|
|
|
+ break;
|
|
|
case ELS_CMD_RRQ:
|
|
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
|
|
"RCV RRQ: did:x%x/ste:x%x flg:x%x",
|
|
@@ -5878,6 +6210,16 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|
|
if (newnode)
|
|
|
lpfc_nlp_put(ndlp);
|
|
|
break;
|
|
|
+ case ELS_CMD_ECHO:
|
|
|
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
|
|
+ "RCV ECHO: did:x%x/ste:x%x flg:x%x",
|
|
|
+ did, vport->port_state, ndlp->nlp_flag);
|
|
|
+
|
|
|
+ phba->fc_stat.elsRcvECHO++;
|
|
|
+ lpfc_els_rcv_echo(vport, elsiocb, ndlp);
|
|
|
+ if (newnode)
|
|
|
+ lpfc_nlp_put(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",
|