aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2010-06-07 15:23:17 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-07-27 13:01:31 -0400
commitffc954936b134cc6d2eba1282cc71084929c3704 (patch)
tree22cbdde46b1ee531c8664335ec35a0c8767bad79 /drivers/scsi
parent8701f18504751a5b89be3203e28c5ec04c147167 (diff)
[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: Alex Iannicelli <alex.iannicelli@emulex.com> Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_disc.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c9
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c35
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c7
5 files changed, 50 insertions, 4 deletions
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index fbc9baeb6048..6b404e510a3b 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -41,6 +41,7 @@ void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *);
41void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *); 41void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *);
42int lpfc_reg_rpi(struct lpfc_hba *, uint16_t, uint32_t, uint8_t *, 42int lpfc_reg_rpi(struct lpfc_hba *, uint16_t, uint32_t, uint8_t *,
43 LPFC_MBOXQ_t *, uint32_t); 43 LPFC_MBOXQ_t *, uint32_t);
44void lpfc_set_var(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
44void lpfc_unreg_login(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); 45void lpfc_unreg_login(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
45void lpfc_unreg_did(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); 46void lpfc_unreg_did(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
46void lpfc_reg_vpi(struct lpfc_vport *, LPFC_MBOXQ_t *); 47void lpfc_reg_vpi(struct lpfc_vport *, LPFC_MBOXQ_t *);
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 36257a685509..7cae69de36f7 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -114,6 +114,8 @@ struct lpfc_nodelist {
114}; 114};
115 115
116/* Defines for nlp_flag (uint32) */ 116/* Defines for nlp_flag (uint32) */
117#define NLP_IGNR_REG_CMPL 0x00000001 /* Rcvd rscn before we cmpl reg login */
118#define NLP_REG_LOGIN_SEND 0x00000002 /* sent reglogin to adapter */
117#define NLP_PLOGI_SND 0x00000020 /* sent PLOGI request for this entry */ 119#define NLP_PLOGI_SND 0x00000020 /* sent PLOGI request for this entry */
118#define NLP_PRLI_SND 0x00000040 /* sent PRLI request for this entry */ 120#define NLP_PRLI_SND 0x00000040 /* sent PRLI request for this entry */
119#define NLP_ADISC_SND 0x00000080 /* sent ADISC request for this entry */ 121#define NLP_ADISC_SND 0x00000080 /* sent ADISC request for this entry */
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index c4c7f0ad7468..6b1850c9fdff 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -2740,6 +2740,15 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
2740 retry = 1; 2740 retry = 1;
2741 break; 2741 break;
2742 } 2742 }
2743 if (stat.un.b.lsRjtRsnCodeExp ==
2744 LSEXP_CANT_GIVE_DATA) {
2745 if (cmd == ELS_CMD_PLOGI) {
2746 delay = 1000;
2747 maxretry = 48;
2748 }
2749 retry = 1;
2750 break;
2751 }
2743 if (cmd == ELS_CMD_PLOGI) { 2752 if (cmd == ELS_CMD_PLOGI) {
2744 delay = 1000; 2753 delay = 1000;
2745 maxretry = lpfc_max_els_tries + 1; 2754 maxretry = lpfc_max_els_tries + 1;
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 1f87b4fb8b50..8082d69ea730 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -275,7 +275,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
275 if (!(vport->load_flag & FC_UNLOADING) && 275 if (!(vport->load_flag & FC_UNLOADING) &&
276 !(ndlp->nlp_flag & NLP_DELAY_TMO) && 276 !(ndlp->nlp_flag & NLP_DELAY_TMO) &&
277 !(ndlp->nlp_flag & NLP_NPR_2B_DISC) && 277 !(ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
278 (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)) 278 (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
279 (ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE))
279 lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); 280 lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM);
280 281
281 lpfc_unregister_unused_fcf(phba); 282 lpfc_unregister_unused_fcf(phba);
@@ -2715,11 +2716,35 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
2715 struct lpfc_vport *vport = pmb->vport; 2716 struct lpfc_vport *vport = pmb->vport;
2716 struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); 2717 struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
2717 struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2; 2718 struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
2719 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2718 2720
2719 pmb->context1 = NULL; 2721 pmb->context1 = NULL;
2720 2722
2721 /* Good status, call state machine */ 2723 if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND)
2722 lpfc_disc_state_machine(vport, ndlp, pmb, NLP_EVT_CMPL_REG_LOGIN); 2724 ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND;
2725
2726 if (ndlp->nlp_flag & NLP_IGNR_REG_CMPL ||
2727 ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE) {
2728 /* We rcvd a rscn after issuing this
2729 * mbox reg login, we may have cycled
2730 * back through the state and be
2731 * back at reg login state so this
2732 * mbox needs to be ignored becase
2733 * there is another reg login in
2734 * proccess.
2735 */
2736 spin_lock_irq(shost->host_lock);
2737 ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL;
2738 spin_unlock_irq(shost->host_lock);
2739 if (phba->sli_rev == LPFC_SLI_REV4)
2740 lpfc_sli4_free_rpi(phba,
2741 pmb->u.mb.un.varRegLogin.rpi);
2742
2743 } else
2744 /* Good status, call state machine */
2745 lpfc_disc_state_machine(vport, ndlp, pmb,
2746 NLP_EVT_CMPL_REG_LOGIN);
2747
2723 lpfc_mbuf_free(phba, mp->virt, mp->phys); 2748 lpfc_mbuf_free(phba, mp->virt, mp->phys);
2724 kfree(mp); 2749 kfree(mp);
2725 mempool_free(pmb, phba->mbox_mem_pool); 2750 mempool_free(pmb, phba->mbox_mem_pool);
@@ -3842,6 +3867,9 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
3842 kfree(mp); 3867 kfree(mp);
3843 } 3868 }
3844 list_del(&mb->list); 3869 list_del(&mb->list);
3870 if (phba->sli_rev == LPFC_SLI_REV4)
3871 lpfc_sli4_free_rpi(phba,
3872 mb->u.mb.un.varRegLogin.rpi);
3845 mempool_free(mb, phba->mbox_mem_pool); 3873 mempool_free(mb, phba->mbox_mem_pool);
3846 /* We shall not invoke the lpfc_nlp_put to decrement 3874 /* We shall not invoke the lpfc_nlp_put to decrement
3847 * the ndlp reference count as we are in the process 3875 * 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 3911
3884 lpfc_cancel_retry_delay_tmo(vport, ndlp); 3912 lpfc_cancel_retry_delay_tmo(vport, ndlp);
3885 if ((ndlp->nlp_flag & NLP_DEFER_RM) && 3913 if ((ndlp->nlp_flag & NLP_DEFER_RM) &&
3914 !(ndlp->nlp_flag & NLP_REG_LOGIN_SEND) &&
3886 !(ndlp->nlp_flag & NLP_RPI_VALID)) { 3915 !(ndlp->nlp_flag & NLP_RPI_VALID)) {
3887 /* For this case we need to cleanup the default rpi 3916 /* For this case we need to cleanup the default rpi
3888 * allocated by the firmware. 3917 * allocated by the firmware.
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index b90820a699fd..9810b3d3cc53 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -626,7 +626,8 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
626 if (!(vport->fc_flag & FC_PT2PT)) { 626 if (!(vport->fc_flag & FC_PT2PT)) {
627 /* Check config parameter use-adisc or FCP-2 */ 627 /* Check config parameter use-adisc or FCP-2 */
628 if ((vport->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) || 628 if ((vport->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) ||
629 ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { 629 ((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) &&
630 (ndlp->nlp_type & NLP_FCP_TARGET))) {
630 spin_lock_irq(shost->host_lock); 631 spin_lock_irq(shost->host_lock);
631 ndlp->nlp_flag |= NLP_NPR_ADISC; 632 ndlp->nlp_flag |= NLP_NPR_ADISC;
632 spin_unlock_irq(shost->host_lock); 633 spin_unlock_irq(shost->host_lock);
@@ -962,6 +963,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
962 mbox->mbox_cmpl = lpfc_mbx_cmpl_fdmi_reg_login; 963 mbox->mbox_cmpl = lpfc_mbx_cmpl_fdmi_reg_login;
963 break; 964 break;
964 default: 965 default:
966 ndlp->nlp_flag |= NLP_REG_LOGIN_SEND;
965 mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; 967 mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
966 } 968 }
967 mbox->context2 = lpfc_nlp_get(ndlp); 969 mbox->context2 = lpfc_nlp_get(ndlp);
@@ -972,6 +974,8 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
972 NLP_STE_REG_LOGIN_ISSUE); 974 NLP_STE_REG_LOGIN_ISSUE);
973 return ndlp->nlp_state; 975 return ndlp->nlp_state;
974 } 976 }
977 if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND)
978 ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND;
975 /* decrement node reference count to the failed mbox 979 /* decrement node reference count to the failed mbox
976 * command 980 * command
977 */ 981 */
@@ -1458,6 +1462,7 @@ lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport,
1458 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; 1462 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
1459 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); 1463 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1460 spin_lock_irq(shost->host_lock); 1464 spin_lock_irq(shost->host_lock);
1465 ndlp->nlp_flag |= NLP_IGNR_REG_CMPL;
1461 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); 1466 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
1462 spin_unlock_irq(shost->host_lock); 1467 spin_unlock_irq(shost->host_lock);
1463 lpfc_disc_set_adisc(vport, ndlp); 1468 lpfc_disc_set_adisc(vport, ndlp);