From fdcebe282fd8654381852260efec267eff8002fb Mon Sep 17 00:00:00 2001
From: James Smart <James.Smart@Emulex.Com>
Date: Tue, 7 Mar 2006 15:04:01 -0500
Subject: [PATCH] [SCSI] lpfc 8.1.4 : Fixed RSCN handling when a PLOGI is in
 retry

Fixed RSCN handling when a PLOGI is in retry.

Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
---
 drivers/scsi/lpfc/lpfc_crtn.h      |  1 +
 drivers/scsi/lpfc/lpfc_els.c       | 51 ++++++++++++++++++++++++------
 drivers/scsi/lpfc/lpfc_hbadisc.c   | 24 +++-----------
 drivers/scsi/lpfc/lpfc_nportdisc.c | 21 +++---------
 4 files changed, 52 insertions(+), 45 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 7b6534a1c315..f716c1d85f41 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -84,6 +84,7 @@ int lpfc_els_rsp_adisc_acc(struct lpfc_hba *, struct lpfc_iocbq *,
 			   struct lpfc_nodelist *);
 int lpfc_els_rsp_prli_acc(struct lpfc_hba *, struct lpfc_iocbq *,
 			  struct lpfc_nodelist *);
+void lpfc_cancel_retry_delay_tmo(struct lpfc_hba *, struct lpfc_nodelist *);
 void lpfc_els_retry_delay(unsigned long);
 void lpfc_els_retry_delay_handler(struct lpfc_nodelist *);
 void lpfc_els_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index efba875e53e4..6d12cd0c49ff 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1434,6 +1434,46 @@ lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry)
 	return 0;
 }
 
+void
+lpfc_cancel_retry_delay_tmo(struct lpfc_hba *phba, struct lpfc_nodelist * nlp)
+{
+	nlp->nlp_flag &= ~NLP_DELAY_TMO;
+	del_timer_sync(&nlp->nlp_delayfunc);
+	nlp->nlp_last_elscmd = 0;
+
+	if (!list_empty(&nlp->els_retry_evt.evt_listp))
+		list_del_init(&nlp->els_retry_evt.evt_listp);
+
+	if (nlp->nlp_flag & NLP_NPR_2B_DISC) {
+		nlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+		if (phba->num_disc_nodes) {
+			/* Check to see if there are more
+			 * PLOGIs to be sent
+			 */
+			lpfc_more_plogi(phba);
+		}
+
+		if (phba->num_disc_nodes == 0) {
+			phba->fc_flag &= ~FC_NDISC_ACTIVE;
+			lpfc_can_disctmo(phba);
+			if (phba->fc_flag & FC_RSCN_MODE) {
+				/* Check to see if more RSCNs
+				 * came in while we were
+				 * processing this one.
+				 */
+				if((phba->fc_rscn_id_cnt==0) &&
+				   (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
+					phba->fc_flag &= ~FC_RSCN_MODE;
+				}
+				else {
+					lpfc_els_handle_rscn(phba);
+				}
+			}
+		}
+	}
+	return;
+}
+
 void
 lpfc_els_retry_delay(unsigned long ptr)
 {
@@ -2415,15 +2455,8 @@ lpfc_rscn_recovery_check(struct lpfc_hba * phba)
 			/* Make sure NLP_DELAY_TMO is NOT running
 			 * after a device recovery event.
 			 */
-			if (ndlp->nlp_flag & NLP_DELAY_TMO) {
-				ndlp->nlp_flag &= ~NLP_DELAY_TMO;
-				ndlp->nlp_last_elscmd = 0;
-				del_timer_sync(&ndlp->nlp_delayfunc);
-				if (!list_empty(&ndlp->
-						els_retry_evt.evt_listp))
-					list_del_init(&ndlp->
-						els_retry_evt.evt_listp);
-			}
+			if (ndlp->nlp_flag & NLP_DELAY_TMO)
+				lpfc_cancel_retry_delay_tmo(phba, ndlp);
 		}
 	}
 	return 0;
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 2b227b363ae3..e15120d21aaa 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1152,13 +1152,9 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
 		/* Stop delay tmo if taking node off NPR list */
 		if ((nlp->nlp_flag & NLP_DELAY_TMO) &&
 		   (list != NLP_NPR_LIST)) {
-			nlp->nlp_flag &= ~NLP_DELAY_TMO;
-			nlp->nlp_last_elscmd = 0;
 			spin_unlock_irq(phba->host->host_lock);
-			del_timer_sync(&nlp->nlp_delayfunc);
+			lpfc_cancel_retry_delay_tmo(phba, nlp);
 			spin_lock_irq(phba->host->host_lock);
-			if (!list_empty(&nlp->els_retry_evt.evt_listp))
-				list_del_init(&nlp->els_retry_evt.evt_listp);
 		}
 		break;
 	}
@@ -1598,13 +1594,7 @@ lpfc_nlp_remove(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
 
 
 	if (ndlp->nlp_flag & NLP_DELAY_TMO) {
-		spin_lock_irq(phba->host->host_lock);
-		ndlp->nlp_flag &= ~NLP_DELAY_TMO;
-		spin_unlock_irq(phba->host->host_lock);
-		ndlp->nlp_last_elscmd = 0;
-		del_timer_sync(&ndlp->nlp_delayfunc);
-		if (!list_empty(&ndlp->els_retry_evt.evt_listp))
-			list_del_init(&ndlp->els_retry_evt.evt_listp);
+		lpfc_cancel_retry_delay_tmo(phba, ndlp);
 	}
 
 	if (ndlp->nlp_disc_refcnt) {
@@ -1896,14 +1886,8 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
 			/* Since this node is marked for discovery,
 			 * delay timeout is not needed.
 			 */
-			if (ndlp->nlp_flag & NLP_DELAY_TMO) {
-				ndlp->nlp_flag &= ~NLP_DELAY_TMO;
-				del_timer_sync(&ndlp->nlp_delayfunc);
-				if (!list_empty(&ndlp->els_retry_evt.
-								evt_listp))
-					list_del_init(&ndlp->els_retry_evt.
-						      		evt_listp);
-			}
+			if (ndlp->nlp_flag & NLP_DELAY_TMO)
+				lpfc_cancel_retry_delay_tmo(phba, ndlp);
 		} else {
 			ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
 			ndlp = NULL;
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 8affc1543c6e..3d77bd999b70 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -259,13 +259,8 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
 	} while(found);
 
 	/* If we are delaying issuing an ELS command, cancel it */
-	if (ndlp->nlp_flag & NLP_DELAY_TMO) {
-		ndlp->nlp_flag &= ~NLP_DELAY_TMO;
-		ndlp->nlp_last_elscmd = 0;
-		del_timer_sync(&ndlp->nlp_delayfunc);
-		if (!list_empty(&ndlp->els_retry_evt.evt_listp))
-			list_del_init(&ndlp->els_retry_evt.evt_listp);
-	}
+	if (ndlp->nlp_flag & NLP_DELAY_TMO)
+		lpfc_cancel_retry_delay_tmo(phba, ndlp);
 	return 0;
 }
 
@@ -1496,7 +1491,7 @@ lpfc_rcv_plogi_npr_node(struct lpfc_hba * phba,
 
 	if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) {
 		spin_lock_irq(phba->host->host_lock);
-		ndlp->nlp_flag &= ~(NLP_NPR_ADISC | NLP_NPR_2B_DISC);
+		ndlp->nlp_flag &= ~NLP_NPR_ADISC;
 		spin_unlock_irq(phba->host->host_lock);
 		return ndlp->nlp_state;
 	}
@@ -1693,16 +1688,10 @@ lpfc_device_recov_npr_node(struct lpfc_hba * phba,
 {
 	spin_lock_irq(phba->host->host_lock);
 	ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+	spin_unlock_irq(phba->host->host_lock);
 	if (ndlp->nlp_flag & NLP_DELAY_TMO) {
-		ndlp->nlp_flag &= ~NLP_DELAY_TMO;
-		if (!list_empty(&ndlp->els_retry_evt.evt_listp))
-			list_del_init(&ndlp->els_retry_evt.evt_listp);
-		spin_unlock_irq(phba->host->host_lock);
-		ndlp->nlp_last_elscmd = 0;
-		del_timer_sync(&ndlp->nlp_delayfunc);
-		return ndlp->nlp_state;
+		lpfc_cancel_retry_delay_tmo(phba, ndlp);
 	}
-	spin_unlock_irq(phba->host->host_lock);
 	return ndlp->nlp_state;
 }
 
-- 
GitLab