[SCSI] lpfc 8.2.2 : Miscellaneous Bug Fixes

- Fix vport ndlp ref counting errors
- Fix use after free of ndlp structure
- Use the correct flag to check for LOADING setting.
- Fix driver unload bugs (related to shost references) after link down or rscn
- Fix up HBQ initialization
- Fix port_list locking around driver unload.
- Fix references to hostdata as a phba
- Fix GFFID type offset to work correctly with big endian structure.
- Only call pci_disable_msi if the pci_enable_msi succeeded
- Fix vport_delete wait/fail if in discovery
- Put a reference on the nameservers ndlp when performing CT traffic.
- Remove unbalanced hba unlock.
- Fix up HBQ processing
- Fix lpfc debugfs discovery trace output for ELS rsp cmpl
- Send ADISC when rpi is 0
- Stop FDISC retrying forever
- Unable to retrieve correct config parameter for vport
- Fix sli_validate_fcp_iocb, sli_sum_iocb, sli_abort_iocb to be vport-aware.
- Fix index-out-of-range error in iocb. Spotted by Coverity.

Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index f96ab75..8788f14 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -83,10 +83,17 @@
 		ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag);
 
 	if (ndlp->nlp_sid != NLP_NO_SID) {
-		lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
-			ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
+		lpfc_sli_abort_iocb(ndlp->vport,
+			&phba->sli.ring[phba->sli.fcp_ring],
+			ndlp->nlp_sid, 0, LPFC_CTX_TGT);
 	}
 
+	/*
+	 * A device is normally blocked for rediscovery and unblocked when
+	 * devloss timeout happens.  In case a vport is removed or driver
+	 * unloaded before devloss timeout happens, we need to unblock here.
+	 */
+	scsi_target_unblock(&rport->dev);
 	return;
 }
 
@@ -194,8 +201,8 @@
 	if (ndlp->nlp_sid != NLP_NO_SID) {
 		warn_on = 1;
 		/* flush the target */
-		lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
-				    ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
+		lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring],
+				    ndlp->nlp_sid, 0, LPFC_CTX_TGT);
 	}
 	if (vport->load_flag & FC_UNLOADING)
 		warn_on = 0;
@@ -348,6 +355,7 @@
 	struct lpfc_sli_ring *pring;
 	uint32_t ha_copy, status, control, work_port_events;
 	struct lpfc_vport **vports;
+	struct lpfc_vport *vport;
 	int i;
 
 	spin_lock_irq(&phba->hbalock);
@@ -365,12 +373,22 @@
 		lpfc_handle_latt(phba);
 	vports = lpfc_create_vport_work_array(phba);
 	if (vports != NULL)
-		for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
-			work_port_events = vports[i]->work_port_events;
+		for(i = 0; i < LPFC_MAX_VPORTS; i++) {
+			/*
+			 * We could have no vports in array if unloading, so if
+			 * this happens then just use the pport
+			 */
+			if (vports[i] == NULL && i == 0)
+				vport = phba->pport;
+			else
+				vport = vports[i];
+			if (vport == NULL)
+				break;
+			work_port_events = vport->work_port_events;
 			if (work_port_events & WORKER_DISC_TMO)
-				lpfc_disc_timeout_handler(vports[i]);
+				lpfc_disc_timeout_handler(vport);
 			if (work_port_events & WORKER_ELS_TMO)
-				lpfc_els_timeout_handler(vports[i]);
+				lpfc_els_timeout_handler(vport);
 			if (work_port_events & WORKER_HB_TMO)
 				lpfc_hb_timeout_handler(phba);
 			if (work_port_events & WORKER_MBOX_TMO)
@@ -378,14 +396,14 @@
 			if (work_port_events & WORKER_FABRIC_BLOCK_TMO)
 				lpfc_unblock_fabric_iocbs(phba);
 			if (work_port_events & WORKER_FDMI_TMO)
-				lpfc_fdmi_timeout_handler(vports[i]);
+				lpfc_fdmi_timeout_handler(vport);
 			if (work_port_events & WORKER_RAMP_DOWN_QUEUE)
 				lpfc_ramp_down_queue_handler(phba);
 			if (work_port_events & WORKER_RAMP_UP_QUEUE)
 				lpfc_ramp_up_queue_handler(phba);
-			spin_lock_irq(&vports[i]->work_port_lock);
-			vports[i]->work_port_events &= ~work_port_events;
-			spin_unlock_irq(&vports[i]->work_port_lock);
+			spin_lock_irq(&vport->work_port_lock);
+			vport->work_port_events &= ~work_port_events;
+			spin_unlock_irq(&vport->work_port_lock);
 		}
 	lpfc_destroy_vport_work_array(vports);
 
@@ -1638,16 +1656,7 @@
 void
 lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 {
-	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-
-	if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0)
-		lpfc_cancel_retry_delay_tmo(vport, ndlp);
-	if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp))
-		lpfc_nlp_counters(vport, ndlp->nlp_state, -1);
-	spin_lock_irq(shost->host_lock);
-	list_del_init(&ndlp->nlp_listp);
-	ndlp->nlp_flag &= ~NLP_TARGET_REMOVE;
-	spin_unlock_irq(shost->host_lock);
+	lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
 	lpfc_nlp_put(ndlp);
 }