Commit ffc95493 authored by James Smart's avatar James Smart Committed by James Bottomley

[SCSI] lpfc 8.3.13: FC Discovery Fixes and enhancements.

- Retry PLOGI up to 48 times when LS_RJT reason is
  "Unable to supply requested data."
- When dev loss timeout occures do not change state if there
  is an outstanding REG_LOGIN.
- Add logic to ignore REG_LOGIN completion if discovery is
  restarted while waiting for REG_LOGIN.
- Only change state on REG_LOGIN completion if still in
  state waiting for REG_LOGIN completion.
- Only send ADISCs to FCP-2 Targets (not Initiators).
Signed-off-by: default avatarAlex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 8701f185
...@@ -41,6 +41,7 @@ void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *); ...@@ -41,6 +41,7 @@ void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_reg_rpi(struct lpfc_hba *, uint16_t, uint32_t, uint8_t *, int lpfc_reg_rpi(struct lpfc_hba *, uint16_t, uint32_t, uint8_t *,
LPFC_MBOXQ_t *, uint32_t); LPFC_MBOXQ_t *, uint32_t);
void lpfc_set_var(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
void lpfc_unreg_login(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); void lpfc_unreg_login(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
void lpfc_unreg_did(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); void lpfc_unreg_did(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
void lpfc_reg_vpi(struct lpfc_vport *, LPFC_MBOXQ_t *); void lpfc_reg_vpi(struct lpfc_vport *, LPFC_MBOXQ_t *);
......
...@@ -114,6 +114,8 @@ struct lpfc_nodelist { ...@@ -114,6 +114,8 @@ struct lpfc_nodelist {
}; };
/* Defines for nlp_flag (uint32) */ /* Defines for nlp_flag (uint32) */
#define NLP_IGNR_REG_CMPL 0x00000001 /* Rcvd rscn before we cmpl reg login */
#define NLP_REG_LOGIN_SEND 0x00000002 /* sent reglogin to adapter */
#define NLP_PLOGI_SND 0x00000020 /* sent PLOGI request for this entry */ #define NLP_PLOGI_SND 0x00000020 /* sent PLOGI request for this entry */
#define NLP_PRLI_SND 0x00000040 /* sent PRLI request for this entry */ #define NLP_PRLI_SND 0x00000040 /* sent PRLI request for this entry */
#define NLP_ADISC_SND 0x00000080 /* sent ADISC request for this entry */ #define NLP_ADISC_SND 0x00000080 /* sent ADISC request for this entry */
......
...@@ -2740,6 +2740,15 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -2740,6 +2740,15 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
retry = 1; retry = 1;
break; break;
} }
if (stat.un.b.lsRjtRsnCodeExp ==
LSEXP_CANT_GIVE_DATA) {
if (cmd == ELS_CMD_PLOGI) {
delay = 1000;
maxretry = 48;
}
retry = 1;
break;
}
if (cmd == ELS_CMD_PLOGI) { if (cmd == ELS_CMD_PLOGI) {
delay = 1000; delay = 1000;
maxretry = lpfc_max_els_tries + 1; maxretry = lpfc_max_els_tries + 1;
......
...@@ -275,7 +275,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ...@@ -275,7 +275,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
if (!(vport->load_flag & FC_UNLOADING) && if (!(vport->load_flag & FC_UNLOADING) &&
!(ndlp->nlp_flag & NLP_DELAY_TMO) && !(ndlp->nlp_flag & NLP_DELAY_TMO) &&
!(ndlp->nlp_flag & NLP_NPR_2B_DISC) && !(ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
(ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)) (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
(ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE))
lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM);
lpfc_unregister_unused_fcf(phba); lpfc_unregister_unused_fcf(phba);
...@@ -2715,11 +2716,35 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -2715,11 +2716,35 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
struct lpfc_vport *vport = pmb->vport; struct lpfc_vport *vport = pmb->vport;
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2; struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
pmb->context1 = NULL; pmb->context1 = NULL;
/* Good status, call state machine */ if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND)
lpfc_disc_state_machine(vport, ndlp, pmb, NLP_EVT_CMPL_REG_LOGIN); ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND;
if (ndlp->nlp_flag & NLP_IGNR_REG_CMPL ||
ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE) {
/* We rcvd a rscn after issuing this
* mbox reg login, we may have cycled
* back through the state and be
* back at reg login state so this
* mbox needs to be ignored becase
* there is another reg login in
* proccess.
*/
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL;
spin_unlock_irq(shost->host_lock);
if (phba->sli_rev == LPFC_SLI_REV4)
lpfc_sli4_free_rpi(phba,
pmb->u.mb.un.varRegLogin.rpi);
} else
/* Good status, call state machine */
lpfc_disc_state_machine(vport, ndlp, pmb,
NLP_EVT_CMPL_REG_LOGIN);
lpfc_mbuf_free(phba, mp->virt, mp->phys); lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp); kfree(mp);
mempool_free(pmb, phba->mbox_mem_pool); mempool_free(pmb, phba->mbox_mem_pool);
...@@ -3842,6 +3867,9 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -3842,6 +3867,9 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
kfree(mp); kfree(mp);
} }
list_del(&mb->list); list_del(&mb->list);
if (phba->sli_rev == LPFC_SLI_REV4)
lpfc_sli4_free_rpi(phba,
mb->u.mb.un.varRegLogin.rpi);
mempool_free(mb, phba->mbox_mem_pool); mempool_free(mb, phba->mbox_mem_pool);
/* We shall not invoke the lpfc_nlp_put to decrement /* We shall not invoke the lpfc_nlp_put to decrement
* the ndlp reference count as we are in the process * the ndlp reference count as we are in the process
...@@ -3883,6 +3911,7 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -3883,6 +3911,7 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
lpfc_cancel_retry_delay_tmo(vport, ndlp); lpfc_cancel_retry_delay_tmo(vport, ndlp);
if ((ndlp->nlp_flag & NLP_DEFER_RM) && if ((ndlp->nlp_flag & NLP_DEFER_RM) &&
!(ndlp->nlp_flag & NLP_REG_LOGIN_SEND) &&
!(ndlp->nlp_flag & NLP_RPI_VALID)) { !(ndlp->nlp_flag & NLP_RPI_VALID)) {
/* For this case we need to cleanup the default rpi /* For this case we need to cleanup the default rpi
* allocated by the firmware. * allocated by the firmware.
......
...@@ -626,7 +626,8 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -626,7 +626,8 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
if (!(vport->fc_flag & FC_PT2PT)) { if (!(vport->fc_flag & FC_PT2PT)) {
/* Check config parameter use-adisc or FCP-2 */ /* Check config parameter use-adisc or FCP-2 */
if ((vport->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) || if ((vport->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) ||
ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { ((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) &&
(ndlp->nlp_type & NLP_FCP_TARGET))) {
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_NPR_ADISC; ndlp->nlp_flag |= NLP_NPR_ADISC;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
...@@ -962,6 +963,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, ...@@ -962,6 +963,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
mbox->mbox_cmpl = lpfc_mbx_cmpl_fdmi_reg_login; mbox->mbox_cmpl = lpfc_mbx_cmpl_fdmi_reg_login;
break; break;
default: default:
ndlp->nlp_flag |= NLP_REG_LOGIN_SEND;
mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
} }
mbox->context2 = lpfc_nlp_get(ndlp); mbox->context2 = lpfc_nlp_get(ndlp);
...@@ -972,6 +974,8 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, ...@@ -972,6 +974,8 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
NLP_STE_REG_LOGIN_ISSUE); NLP_STE_REG_LOGIN_ISSUE);
return ndlp->nlp_state; return ndlp->nlp_state;
} }
if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND)
ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND;
/* decrement node reference count to the failed mbox /* decrement node reference count to the failed mbox
* command * command
*/ */
...@@ -1458,6 +1462,7 @@ lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport, ...@@ -1458,6 +1462,7 @@ lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport,
ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_IGNR_REG_CMPL;
ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
lpfc_disc_set_adisc(vport, ndlp); lpfc_disc_set_adisc(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