diff options
author | James Smart <James.Smart@Emulex.Com> | 2008-06-14 22:52:47 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-07-12 09:22:27 -0400 |
commit | 0d2b6b83030d6a88cbf7db57f84f2daf0e0b251b (patch) | |
tree | 7523cdfa622916864ccd1cecef6f407a482e35e6 /drivers/scsi/lpfc/lpfc_nportdisc.c | |
parent | 915caaaf622172bd3451e7b76ba9cfcea80e87c7 (diff) |
[SCSI] lpfc 8.2.7 : Discovery Fixes
- Fix ADISC timeout on initiators causing devloss timeout on targets
- Correct FAN processing : port state vs unreg rpi's wasn't consistent
- Correct mismatches between ASICs and PLOGI that would skip PLOGI
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_nportdisc.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 145 |
1 files changed, 54 insertions, 91 deletions
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index d08c4c890744..6688a8689b56 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -235,10 +235,7 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | |||
235 | (iocb->iocb_cmpl) (phba, iocb, iocb); | 235 | (iocb->iocb_cmpl) (phba, iocb, iocb); |
236 | } | 236 | } |
237 | } | 237 | } |
238 | 238 | lpfc_cancel_retry_delay_tmo(phba->pport, ndlp); | |
239 | /* If we are delaying issuing an ELS command, cancel it */ | ||
240 | if (ndlp->nlp_flag & NLP_DELAY_TMO) | ||
241 | lpfc_cancel_retry_delay_tmo(phba->pport, ndlp); | ||
242 | return 0; | 239 | return 0; |
243 | } | 240 | } |
244 | 241 | ||
@@ -249,7 +246,6 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
249 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 246 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
250 | struct lpfc_hba *phba = vport->phba; | 247 | struct lpfc_hba *phba = vport->phba; |
251 | struct lpfc_dmabuf *pcmd; | 248 | struct lpfc_dmabuf *pcmd; |
252 | struct lpfc_work_evt *evtp; | ||
253 | uint32_t *lp; | 249 | uint32_t *lp; |
254 | IOCB_t *icmd; | 250 | IOCB_t *icmd; |
255 | struct serv_parm *sp; | 251 | struct serv_parm *sp; |
@@ -425,73 +421,8 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
425 | ndlp, mbox); | 421 | ndlp, mbox); |
426 | return 1; | 422 | return 1; |
427 | } | 423 | } |
428 | |||
429 | /* If the remote NPort logs into us, before we can initiate | ||
430 | * discovery to them, cleanup the NPort from discovery accordingly. | ||
431 | */ | ||
432 | if (ndlp->nlp_state == NLP_STE_NPR_NODE) { | ||
433 | spin_lock_irq(shost->host_lock); | ||
434 | ndlp->nlp_flag &= ~NLP_DELAY_TMO; | ||
435 | spin_unlock_irq(shost->host_lock); | ||
436 | del_timer_sync(&ndlp->nlp_delayfunc); | ||
437 | ndlp->nlp_last_elscmd = 0; | ||
438 | |||
439 | if (!list_empty(&ndlp->els_retry_evt.evt_listp)) { | ||
440 | list_del_init(&ndlp->els_retry_evt.evt_listp); | ||
441 | /* Decrement ndlp reference count held for the | ||
442 | * delayed retry | ||
443 | */ | ||
444 | evtp = &ndlp->els_retry_evt; | ||
445 | lpfc_nlp_put((struct lpfc_nodelist *)evtp->evt_arg1); | ||
446 | } | ||
447 | |||
448 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { | ||
449 | spin_lock_irq(shost->host_lock); | ||
450 | ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; | ||
451 | spin_unlock_irq(shost->host_lock); | ||
452 | |||
453 | if ((ndlp->nlp_flag & NLP_ADISC_SND) && | ||
454 | (vport->num_disc_nodes)) { | ||
455 | /* Check to see if there are more | ||
456 | * ADISCs to be sent | ||
457 | */ | ||
458 | lpfc_more_adisc(vport); | ||
459 | |||
460 | if ((vport->num_disc_nodes == 0) && | ||
461 | (vport->fc_npr_cnt)) | ||
462 | lpfc_els_disc_plogi(vport); | ||
463 | |||
464 | if (vport->num_disc_nodes == 0) { | ||
465 | spin_lock_irq(shost->host_lock); | ||
466 | vport->fc_flag &= ~FC_NDISC_ACTIVE; | ||
467 | spin_unlock_irq(shost->host_lock); | ||
468 | lpfc_can_disctmo(vport); | ||
469 | lpfc_end_rscn(vport); | ||
470 | } | ||
471 | } | ||
472 | } | ||
473 | } else if ((ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) && | ||
474 | (ndlp->nlp_flag & NLP_NPR_2B_DISC) && | ||
475 | (vport->num_disc_nodes)) { | ||
476 | spin_lock_irq(shost->host_lock); | ||
477 | ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; | ||
478 | spin_unlock_irq(shost->host_lock); | ||
479 | /* Check to see if there are more | ||
480 | * PLOGIs to be sent | ||
481 | */ | ||
482 | lpfc_more_plogi(vport); | ||
483 | if (vport->num_disc_nodes == 0) { | ||
484 | spin_lock_irq(shost->host_lock); | ||
485 | vport->fc_flag &= ~FC_NDISC_ACTIVE; | ||
486 | spin_unlock_irq(shost->host_lock); | ||
487 | lpfc_can_disctmo(vport); | ||
488 | lpfc_end_rscn(vport); | ||
489 | } | ||
490 | } | ||
491 | |||
492 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox); | 424 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox); |
493 | return 1; | 425 | return 1; |
494 | |||
495 | out: | 426 | out: |
496 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 427 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
497 | stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE; | 428 | stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE; |
@@ -574,7 +505,9 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
574 | else | 505 | else |
575 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); | 506 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
576 | 507 | ||
577 | if (!(ndlp->nlp_type & NLP_FABRIC) || | 508 | if ((!(ndlp->nlp_type & NLP_FABRIC) && |
509 | ((ndlp->nlp_type & NLP_FCP_TARGET) || | ||
510 | !(ndlp->nlp_type & NLP_FCP_INITIATOR))) || | ||
578 | (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) { | 511 | (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) { |
579 | /* Only try to re-login if this is NOT a Fabric Node */ | 512 | /* Only try to re-login if this is NOT a Fabric Node */ |
580 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); | 513 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); |
@@ -751,6 +684,7 @@ static uint32_t | |||
751 | lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | 684 | lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
752 | void *arg, uint32_t evt) | 685 | void *arg, uint32_t evt) |
753 | { | 686 | { |
687 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
754 | struct lpfc_hba *phba = vport->phba; | 688 | struct lpfc_hba *phba = vport->phba; |
755 | struct lpfc_iocbq *cmdiocb = arg; | 689 | struct lpfc_iocbq *cmdiocb = arg; |
756 | struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | 690 | struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; |
@@ -776,7 +710,22 @@ lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
776 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, | 710 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, |
777 | NULL); | 711 | NULL); |
778 | } else { | 712 | } else { |
779 | lpfc_rcv_plogi(vport, ndlp, cmdiocb); | 713 | if (lpfc_rcv_plogi(vport, ndlp, cmdiocb) && |
714 | (ndlp->nlp_flag & NLP_NPR_2B_DISC) && | ||
715 | (vport->num_disc_nodes)) { | ||
716 | spin_lock_irq(shost->host_lock); | ||
717 | ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; | ||
718 | spin_unlock_irq(shost->host_lock); | ||
719 | /* Check if there are more PLOGIs to be sent */ | ||
720 | lpfc_more_plogi(vport); | ||
721 | if (vport->num_disc_nodes == 0) { | ||
722 | spin_lock_irq(shost->host_lock); | ||
723 | vport->fc_flag &= ~FC_NDISC_ACTIVE; | ||
724 | spin_unlock_irq(shost->host_lock); | ||
725 | lpfc_can_disctmo(vport); | ||
726 | lpfc_end_rscn(vport); | ||
727 | } | ||
728 | } | ||
780 | } /* If our portname was less */ | 729 | } /* If our portname was less */ |
781 | 730 | ||
782 | return ndlp->nlp_state; | 731 | return ndlp->nlp_state; |
@@ -1040,6 +989,7 @@ static uint32_t | |||
1040 | lpfc_rcv_plogi_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | 989 | lpfc_rcv_plogi_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1041 | void *arg, uint32_t evt) | 990 | void *arg, uint32_t evt) |
1042 | { | 991 | { |
992 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1043 | struct lpfc_hba *phba = vport->phba; | 993 | struct lpfc_hba *phba = vport->phba; |
1044 | struct lpfc_iocbq *cmdiocb; | 994 | struct lpfc_iocbq *cmdiocb; |
1045 | 995 | ||
@@ -1048,9 +998,28 @@ lpfc_rcv_plogi_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1048 | 998 | ||
1049 | cmdiocb = (struct lpfc_iocbq *) arg; | 999 | cmdiocb = (struct lpfc_iocbq *) arg; |
1050 | 1000 | ||
1051 | if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) | 1001 | if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) { |
1052 | return ndlp->nlp_state; | 1002 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { |
1003 | spin_lock_irq(shost->host_lock); | ||
1004 | ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; | ||
1005 | spin_unlock_irq(shost->host_lock); | ||
1053 | 1006 | ||
1007 | if (vport->num_disc_nodes) { | ||
1008 | lpfc_more_adisc(vport); | ||
1009 | if ((vport->num_disc_nodes == 0) && | ||
1010 | (vport->fc_npr_cnt)) | ||
1011 | lpfc_els_disc_plogi(vport); | ||
1012 | if (vport->num_disc_nodes == 0) { | ||
1013 | spin_lock_irq(shost->host_lock); | ||
1014 | vport->fc_flag &= ~FC_NDISC_ACTIVE; | ||
1015 | spin_unlock_irq(shost->host_lock); | ||
1016 | lpfc_can_disctmo(vport); | ||
1017 | lpfc_end_rscn(vport); | ||
1018 | } | ||
1019 | } | ||
1020 | } | ||
1021 | return ndlp->nlp_state; | ||
1022 | } | ||
1054 | ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; | 1023 | ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; |
1055 | lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); | 1024 | lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); |
1056 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); | 1025 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); |
@@ -1742,24 +1711,21 @@ lpfc_rcv_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1742 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; | 1711 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1743 | 1712 | ||
1744 | /* Ignore PLOGI if we have an outstanding LOGO */ | 1713 | /* Ignore PLOGI if we have an outstanding LOGO */ |
1745 | if (ndlp->nlp_flag & (NLP_LOGO_SND | NLP_LOGO_ACC)) { | 1714 | if (ndlp->nlp_flag & (NLP_LOGO_SND | NLP_LOGO_ACC)) |
1746 | return ndlp->nlp_state; | 1715 | return ndlp->nlp_state; |
1747 | } | ||
1748 | |||
1749 | if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) { | 1716 | if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) { |
1717 | lpfc_cancel_retry_delay_tmo(vport, ndlp); | ||
1750 | spin_lock_irq(shost->host_lock); | 1718 | spin_lock_irq(shost->host_lock); |
1751 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | 1719 | ndlp->nlp_flag &= ~(NLP_NPR_ADISC | NLP_NPR_2B_DISC); |
1752 | spin_unlock_irq(shost->host_lock); | 1720 | spin_unlock_irq(shost->host_lock); |
1753 | return ndlp->nlp_state; | 1721 | } else if (!(ndlp->nlp_flag & NLP_NPR_2B_DISC)) { |
1754 | } | 1722 | /* send PLOGI immediately, move to PLOGI issue state */ |
1755 | 1723 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { | |
1756 | /* send PLOGI immediately, move to PLOGI issue state */ | 1724 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; |
1757 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { | 1725 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); |
1758 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; | 1726 | lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); |
1759 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); | 1727 | } |
1760 | lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); | ||
1761 | } | 1728 | } |
1762 | |||
1763 | return ndlp->nlp_state; | 1729 | return ndlp->nlp_state; |
1764 | } | 1730 | } |
1765 | 1731 | ||
@@ -1810,7 +1776,6 @@ lpfc_rcv_padisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1810 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; | 1776 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1811 | 1777 | ||
1812 | lpfc_rcv_padisc(vport, ndlp, cmdiocb); | 1778 | lpfc_rcv_padisc(vport, ndlp, cmdiocb); |
1813 | |||
1814 | /* | 1779 | /* |
1815 | * Do not start discovery if discovery is about to start | 1780 | * Do not start discovery if discovery is about to start |
1816 | * or discovery in progress for this node. Starting discovery | 1781 | * or discovery in progress for this node. Starting discovery |
@@ -1973,9 +1938,7 @@ lpfc_device_recov_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1973 | spin_lock_irq(shost->host_lock); | 1938 | spin_lock_irq(shost->host_lock); |
1974 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); | 1939 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); |
1975 | spin_unlock_irq(shost->host_lock); | 1940 | spin_unlock_irq(shost->host_lock); |
1976 | if (ndlp->nlp_flag & NLP_DELAY_TMO) { | 1941 | lpfc_cancel_retry_delay_tmo(vport, ndlp); |
1977 | lpfc_cancel_retry_delay_tmo(vport, ndlp); | ||
1978 | } | ||
1979 | return ndlp->nlp_state; | 1942 | return ndlp->nlp_state; |
1980 | } | 1943 | } |
1981 | 1944 | ||