diff options
author | James Smart <james.smart@emulex.com> | 2010-06-07 15:23:17 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-07-27 13:01:31 -0400 |
commit | ffc954936b134cc6d2eba1282cc71084929c3704 (patch) | |
tree | 22cbdde46b1ee531c8664335ec35a0c8767bad79 /drivers/scsi | |
parent | 8701f18504751a5b89be3203e28c5ec04c147167 (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.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_disc.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 9 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 35 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 7 |
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 *); | |||
41 | void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *); | 41 | void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *); |
42 | int lpfc_reg_rpi(struct lpfc_hba *, uint16_t, uint32_t, uint8_t *, | 42 | int lpfc_reg_rpi(struct lpfc_hba *, uint16_t, uint32_t, uint8_t *, |
43 | LPFC_MBOXQ_t *, uint32_t); | 43 | LPFC_MBOXQ_t *, uint32_t); |
44 | void lpfc_set_var(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t); | ||
44 | void lpfc_unreg_login(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); | 45 | void lpfc_unreg_login(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); |
45 | void lpfc_unreg_did(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); | 46 | void lpfc_unreg_did(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); |
46 | void lpfc_reg_vpi(struct lpfc_vport *, LPFC_MBOXQ_t *); | 47 | void 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); |