[SCSI] lpfc: bug fixes

 Following the NPIV support, the following changes have been accumulated
 in the testing and qualification of the driver:

 - Fix affinity of ELS ring to slow/deferred event processing
 - Fix Ring attention masks
 - Defer dev_loss_tmo timeout handling to worker thread
 - Consolidate link down error classification for better error checking
 - Remove unused/deprecated nlp_initiator_tmr timer
 - Fix for async scan - move adapter init code back into pci_probe_one
   context. Fix async scan interfaces.
 - Expand validation of ability to create vports
 - Extract VPI resource cnt from firmware
 - Tuning of Login/Reject policies to better deal with overwhelmned targets
 - Misc ELS and discovery fixes
 - Export the npiv_enable attribute to sysfs
 - Mailbox handling fix
 - Add debugfs support
 - A few other small misc fixes:
    - wrong return values, double-frees, bad locking
 - Added adapter failure heartbeat

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_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
index 786125b..85797db 100644
--- a/drivers/scsi/lpfc/lpfc_vport.c
+++ b/drivers/scsi/lpfc/lpfc_vport.c
@@ -82,7 +82,8 @@
 	int  vpi;
 
 	spin_lock_irq(&phba->hbalock);
-	vpi = find_next_zero_bit(phba->vpi_bmask, phba->max_vpi, 1);
+	/* Start at bit 1 because vpi zero is reserved for the physical port */
+	vpi = find_next_zero_bit(phba->vpi_bmask, (phba->max_vpi + 1), 1);
 	if (vpi > phba->max_vpi)
 		vpi = 0;
 	else
@@ -131,7 +132,8 @@
 				mb->mbxCommand, mb->mbxStatus, rc);
 		lpfc_mbuf_free(phba, mp->virt, mp->phys);
 		kfree(mp);
-		mempool_free(pmb, phba->mbox_mem_pool);
+		if (rc != MBX_TIMEOUT)
+			mempool_free(pmb, phba->mbox_mem_pool);
 		return -EIO;
 	}
 
@@ -241,6 +243,8 @@
 	}
 
 	vport->vpi = vpi;
+	lpfc_debugfs_initialize(vport);
+
 	if (lpfc_vport_sparm(phba, vport)) {
 		lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
 				"%d:1813 Create VPORT failed: vpi:%d "
@@ -306,8 +310,16 @@
 	 */
 	ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
 	if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
-		lpfc_set_disctmo(vport);
-		lpfc_initial_fdisc(vport);
+		if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) {
+			lpfc_set_disctmo(vport);
+			lpfc_initial_fdisc(vport);
+		} else {
+			lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
+			lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+					"%d (%d):0262 No NPIV Fabric "
+					"support\n",
+					phba->brd_no, vport->vpi);
+		}
 	} else {
 		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
 	}
@@ -383,8 +395,16 @@
 	 */
 	ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
 	if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
-		lpfc_set_disctmo(vport);
-		lpfc_initial_fdisc(vport);
+		if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) {
+			lpfc_set_disctmo(vport);
+			lpfc_initial_fdisc(vport);
+		} else {
+			lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
+			lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+					"%d (%d):0264 No NPIV Fabric "
+					"support\n",
+					phba->brd_no, vport->vpi);
+		}
 	} else {
 		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
 	}
@@ -441,6 +461,7 @@
 	vport->load_flag |= FC_UNLOADING;
 
 	kfree(vport->vname);
+	lpfc_debugfs_terminate(vport);
 	fc_remove_host(lpfc_shost_from_vport(vport));
 	scsi_remove_host(lpfc_shost_from_vport(vport));
 
@@ -476,12 +497,6 @@
 					     NLP_EVT_DEVICE_RM);
 	}
 
-	list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
-		/* free any ndlp's in unused state */
-		if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
-			lpfc_drop_node(vport, ndlp);
-	}
-
 	lpfc_stop_vport_timers(vport);
 	lpfc_unreg_all_rpis(vport);
 	lpfc_unreg_default_rpis(vport);