Commit d6de08cc authored by James Smart's avatar James Smart Committed by Martin K. Petersen

lpfc: Fix the FLOGI discovery logic to comply with T11 standards

Fix the FLOGI discovery logic to comply with T11 standards

We weren't properly setting fabric parameters, such as R_A_TOV and E_D_TOV,
when we registered the vfi object in default configs and pt2pt configs.
Revise to now pass service params with the values to the firmware and
ensure they are reset on link bounce. Required reworking the call sequence
in the discovery threads.
Signed-off-by: default avatarDick Kennedy <dick.kennedy@avagotech.com>
Signed-off-by: default avatarJames Smart <james.smart@avagotech.com>
Reviewed-by: default avatarHannes Reinicke <hare@suse.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent f5cb5304
...@@ -72,6 +72,7 @@ void lpfc_cancel_all_vport_retry_delay_timer(struct lpfc_hba *); ...@@ -72,6 +72,7 @@ void lpfc_cancel_all_vport_retry_delay_timer(struct lpfc_hba *);
void lpfc_retry_pport_discovery(struct lpfc_hba *); void lpfc_retry_pport_discovery(struct lpfc_hba *);
void lpfc_release_rpi(struct lpfc_hba *, struct lpfc_vport *, uint16_t); void lpfc_release_rpi(struct lpfc_hba *, struct lpfc_vport *, uint16_t);
void lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
......
This diff is collapsed.
...@@ -1083,7 +1083,7 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -1083,7 +1083,7 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
} }
static void void
lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{ {
struct lpfc_vport *vport = pmb->vport; struct lpfc_vport *vport = pmb->vport;
...@@ -1113,8 +1113,10 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -1113,8 +1113,10 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
/* Start discovery by sending a FLOGI. port_state is identically /* Start discovery by sending a FLOGI. port_state is identically
* LPFC_FLOGI while waiting for FLOGI cmpl * LPFC_FLOGI while waiting for FLOGI cmpl
*/ */
if (vport->port_state != LPFC_FLOGI || vport->fc_flag & FC_PT2PT_PLOGI) if (vport->port_state != LPFC_FLOGI)
lpfc_initial_flogi(vport); lpfc_initial_flogi(vport);
else if (vport->fc_flag & FC_PT2PT)
lpfc_disc_start(vport);
return; return;
out: out:
...@@ -2963,8 +2965,10 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) ...@@ -2963,8 +2965,10 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
out_free_mem: out_free_mem:
mempool_free(mboxq, phba->mbox_mem_pool); mempool_free(mboxq, phba->mbox_mem_pool);
lpfc_mbuf_free(phba, dmabuf->virt, dmabuf->phys); if (dmabuf) {
kfree(dmabuf); lpfc_mbuf_free(phba, dmabuf->virt, dmabuf->phys);
kfree(dmabuf);
}
return; return;
} }
......
...@@ -280,38 +280,12 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -280,38 +280,12 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
uint32_t *lp; uint32_t *lp;
IOCB_t *icmd; IOCB_t *icmd;
struct serv_parm *sp; struct serv_parm *sp;
uint32_t ed_tov;
LPFC_MBOXQ_t *mbox; LPFC_MBOXQ_t *mbox;
struct ls_rjt stat; struct ls_rjt stat;
int rc; int rc;
memset(&stat, 0, sizeof (struct ls_rjt)); memset(&stat, 0, sizeof (struct ls_rjt));
if (vport->port_state <= LPFC_FDISC) {
/* Before responding to PLOGI, check for pt2pt mode.
* If we are pt2pt, with an outstanding FLOGI, abort
* the FLOGI and resend it first.
*/
if (vport->fc_flag & FC_PT2PT) {
lpfc_els_abort_flogi(phba);
if (!(vport->fc_flag & FC_PT2PT_PLOGI)) {
/* If the other side is supposed to initiate
* the PLOGI anyway, just ACC it now and
* move on with discovery.
*/
phba->fc_edtov = FF_DEF_EDTOV;
phba->fc_ratov = FF_DEF_RATOV;
/* Start discovery - this should just do
CLEAR_LA */
lpfc_disc_start(vport);
} else
lpfc_initial_flogi(vport);
} else {
stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
ndlp, NULL);
return 0;
}
}
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
lp = (uint32_t *) pcmd->virt; lp = (uint32_t *) pcmd->virt;
sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
...@@ -404,30 +378,46 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -404,30 +378,46 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
/* Check for Nport to NPort pt2pt protocol */ /* Check for Nport to NPort pt2pt protocol */
if ((vport->fc_flag & FC_PT2PT) && if ((vport->fc_flag & FC_PT2PT) &&
!(vport->fc_flag & FC_PT2PT_PLOGI)) { !(vport->fc_flag & FC_PT2PT_PLOGI)) {
/* rcv'ed PLOGI decides what our NPortId will be */ /* rcv'ed PLOGI decides what our NPortId will be */
vport->fc_myDID = icmd->un.rcvels.parmRo; vport->fc_myDID = icmd->un.rcvels.parmRo;
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (mbox == NULL) ed_tov = be32_to_cpu(sp->cmn.e_d_tov);
goto out; if (sp->cmn.edtovResolution) {
lpfc_config_link(phba, mbox); /* E_D_TOV ticks are in nanoseconds */
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; ed_tov = (phba->fc_edtov + 999999) / 1000000;
mbox->vport = vport;
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
mempool_free(mbox, phba->mbox_mem_pool);
goto out;
} }
/* /*
* For SLI4, the VFI/VPI are registered AFTER the * For pt-to-pt, use the larger EDTOV
* Nport with the higher WWPN sends us a PLOGI with * RATOV = 2 * EDTOV
* our assigned NPortId.
*/ */
if (ed_tov > phba->fc_edtov)
phba->fc_edtov = ed_tov;
phba->fc_ratov = (2 * phba->fc_edtov) / 1000;
memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));
/* Issue config_link / reg_vfi to account for updated TOV's */
if (phba->sli_rev == LPFC_SLI_REV4) if (phba->sli_rev == LPFC_SLI_REV4)
lpfc_issue_reg_vfi(vport); lpfc_issue_reg_vfi(vport);
else {
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (mbox == NULL)
goto out;
lpfc_config_link(phba, mbox);
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
mbox->vport = vport;
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
mempool_free(mbox, phba->mbox_mem_pool);
goto out;
}
}
lpfc_can_disctmo(vport); lpfc_can_disctmo(vport);
} }
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox) if (!mbox)
goto out; goto out;
...@@ -1038,7 +1028,9 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, ...@@ -1038,7 +1028,9 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
uint32_t *lp; uint32_t *lp;
IOCB_t *irsp; IOCB_t *irsp;
struct serv_parm *sp; struct serv_parm *sp;
uint32_t ed_tov;
LPFC_MBOXQ_t *mbox; LPFC_MBOXQ_t *mbox;
int rc;
cmdiocb = (struct lpfc_iocbq *) arg; cmdiocb = (struct lpfc_iocbq *) arg;
rspiocb = cmdiocb->context_un.rsp_iocb; rspiocb = cmdiocb->context_un.rsp_iocb;
...@@ -1053,6 +1045,16 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, ...@@ -1053,6 +1045,16 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
if (irsp->ulpStatus) if (irsp->ulpStatus)
goto out; goto out;
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
"0133 PLOGI: no memory for reg_login "
"Data: x%x x%x x%x x%x\n",
ndlp->nlp_DID, ndlp->nlp_state,
ndlp->nlp_flag, ndlp->nlp_rpi);
goto out;
}
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list); prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);
...@@ -1094,14 +1096,38 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, ...@@ -1094,14 +1096,38 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
ndlp->nlp_maxframe = ndlp->nlp_maxframe =
((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb; ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if ((vport->fc_flag & FC_PT2PT) &&
if (!mbox) { (vport->fc_flag & FC_PT2PT_PLOGI)) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, ed_tov = be32_to_cpu(sp->cmn.e_d_tov);
"0133 PLOGI: no memory for reg_login " if (sp->cmn.edtovResolution) {
"Data: x%x x%x x%x x%x\n", /* E_D_TOV ticks are in nanoseconds */
ndlp->nlp_DID, ndlp->nlp_state, ed_tov = (phba->fc_edtov + 999999) / 1000000;
ndlp->nlp_flag, ndlp->nlp_rpi); }
goto out;
/*
* Use the larger EDTOV
* RATOV = 2 * EDTOV for pt-to-pt
*/
if (ed_tov > phba->fc_edtov)
phba->fc_edtov = ed_tov;
phba->fc_ratov = (2 * phba->fc_edtov) / 1000;
memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));
/* Issue config_link / reg_vfi to account for updated TOV's */
if (phba->sli_rev == LPFC_SLI_REV4) {
lpfc_issue_reg_vfi(vport);
} else {
lpfc_config_link(phba, mbox);
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
mbox->vport = vport;
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
mempool_free(mbox, phba->mbox_mem_pool);
goto out;
}
}
} }
lpfc_unreg_rpi(vport, ndlp); lpfc_unreg_rpi(vport, ndlp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment