summary refs log tree commit diff
path: root/drivers/scsi/lpfc/lpfc_ct.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2007-06-17 19:56:39 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-06-17 22:38:11 -0500
commit858c9f6c19c6f9bf86cbbc64ce0d17c61d6131b8 (patch)
tree9591b15b4424066023e375ad0aa33fdd37e1c452 /drivers/scsi/lpfc/lpfc_ct.c
parent92d7f7b0cde3ad2260e7462b40867b57efd49851 (diff)
downloadlinux-858c9f6c19c6f9bf86cbbc64ce0d17c61d6131b8.tar.gz
[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>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_ct.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c217
1 files changed, 164 insertions, 53 deletions
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 5584f395314c..ae9d6f385a6c 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -41,6 +41,7 @@
 #include "lpfc_crtn.h"
 #include "lpfc_version.h"
 #include "lpfc_vport.h"
+#include "lpfc_debugfs.h"
 
 #define HBA_PORTSPEED_UNKNOWN               0	/* Unknown - transceiver
 						 * incapable of reporting */
@@ -251,6 +252,32 @@ lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl,
 	return mlist;
 }
 
+int
+lpfc_ct_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocb)
+{
+	struct lpfc_dmabuf *buf_ptr;
+
+	if (ctiocb->context1) {
+		buf_ptr = (struct lpfc_dmabuf *) ctiocb->context1;
+		lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
+		kfree(buf_ptr);
+		ctiocb->context1 = NULL;
+	}
+	if (ctiocb->context2) {
+		lpfc_free_ct_rsp(phba, (struct lpfc_dmabuf *) ctiocb->context2);
+		ctiocb->context2 = NULL;
+	}
+
+	if (ctiocb->context3) {
+		buf_ptr = (struct lpfc_dmabuf *) ctiocb->context3;
+		lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
+		kfree(buf_ptr);
+		ctiocb->context1 = NULL;
+	}
+	lpfc_sli_release_iocbq(phba, ctiocb);
+	return 0;
+}
+
 static int
 lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
 	     struct lpfc_dmabuf *inp, struct lpfc_dmabuf *outp,
@@ -428,6 +455,13 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)
 				    (!phba->cfg_vport_restrict_login)) {
 					ndlp = lpfc_setup_disc_node(vport, Did);
 					if (ndlp) {
+						lpfc_debugfs_disc_trc(vport,
+						LPFC_DISC_TRC_CT,
+						"Parse GID_FTrsp: "
+						"did:x%x flg:x%x x%x",
+						Did, ndlp->nlp_flag,
+						vport->fc_flag);
+
 						lpfc_printf_log(phba, KERN_INFO,
 							LOG_DISCOVERY,
 							"%d (%d):0238 Process "
@@ -439,6 +473,13 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)
 							vport->fc_flag,
 							vport->fc_rscn_id_cnt);
 					} else {
+						lpfc_debugfs_disc_trc(vport,
+						LPFC_DISC_TRC_CT,
+						"Skip1 GID_FTrsp: "
+						"did:x%x flg:x%x cnt:%d",
+						Did, vport->fc_flag,
+						vport->fc_rscn_id_cnt);
+
 						lpfc_printf_log(phba, KERN_INFO,
 							LOG_DISCOVERY,
 							"%d (%d):0239 Skip x%x "
@@ -453,12 +494,26 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)
 				} else {
 					if (!(vport->fc_flag & FC_RSCN_MODE) ||
 					(lpfc_rscn_payload_check(vport, Did))) {
+						lpfc_debugfs_disc_trc(vport,
+						LPFC_DISC_TRC_CT,
+						"Query GID_FTrsp: "
+						"did:x%x flg:x%x cnt:%d",
+						Did, vport->fc_flag,
+						vport->fc_rscn_id_cnt);
+
 						if (lpfc_ns_cmd(vport,
 							SLI_CTNS_GFF_ID,
 							0, Did) == 0)
 							vport->num_disc_nodes++;
 					}
 					else {
+						lpfc_debugfs_disc_trc(vport,
+						LPFC_DISC_TRC_CT,
+						"Skip2 GID_FTrsp: "
+						"did:x%x flg:x%x cnt:%d",
+						Did, vport->fc_flag,
+						vport->fc_rscn_id_cnt);
+
 						lpfc_printf_log(phba, KERN_INFO,
 							LOG_DISCOVERY,
 							"%d (%d):0245 Skip x%x "
@@ -492,7 +547,6 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 	IOCB_t *irsp;
 	struct lpfc_dmabuf *bmp;
-	struct lpfc_dmabuf *inp;
 	struct lpfc_dmabuf *outp;
 	struct lpfc_sli_ct_request *CTrsp;
 	int rc;
@@ -500,31 +554,39 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 	/* we pass cmdiocb to state machine which needs rspiocb as well */
 	cmdiocb->context_un.rsp_iocb = rspiocb;
 
-	inp = (struct lpfc_dmabuf *) cmdiocb->context1;
 	outp = (struct lpfc_dmabuf *) cmdiocb->context2;
 	bmp = (struct lpfc_dmabuf *) cmdiocb->context3;
+	irsp = &rspiocb->iocb;
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+		 "GID_FT cmpl:     status:x%x/x%x rtry:%d",
+		irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_ns_retry);
 
 	/* Don't bother processing response if vport is being torn down. */
 	if (vport->load_flag & FC_UNLOADING)
 		goto out;
 
-	irsp = &rspiocb->iocb;
-	if (irsp->ulpStatus) {
-		if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
-			((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) ||
-			 (irsp->un.ulpWord[4] == IOERR_SLI_ABORTED)))
-			goto err1;
 
+	if (lpfc_els_chk_latt(vport) || lpfc_error_lost_link(irsp)) {
+		lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+				"%d (%d):0216 Link event during NS query\n",
+				phba->brd_no, vport->vpi);
+		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+		goto out;
+	}
+
+	if (irsp->ulpStatus) {
 		/* Check for retry */
 		if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
-			vport->fc_ns_retry++;
+			if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
+				(irsp->un.ulpWord[4] != IOERR_NO_RESOURCES))
+				vport->fc_ns_retry++;
 			/* CT command is being retried */
 			rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
 					 vport->fc_ns_retry, 0);
 			if (rc == 0)
 				goto out;
 		}
-err1:
 		lpfc_vport_set_state(vport, FC_VPORT_FAILED);
 		lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
 			"%d (%d):0257 GID_FT Query error: 0x%x 0x%x\n",
@@ -553,6 +615,13 @@ err1:
 					(uint32_t) CTrsp->ReasonCode,
 					(uint32_t) CTrsp->Explanation,
 					vport->fc_flag);
+
+			lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+				"GID_FT rsp err1  cmd:x%x rsn:x%x exp:x%x",
+				(uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
+				(uint32_t) CTrsp->ReasonCode,
+				(uint32_t) CTrsp->Explanation);
+
 		} else {
 			/* NameServer Rsp Error */
 			lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
@@ -563,6 +632,12 @@ err1:
 					(uint32_t) CTrsp->ReasonCode,
 					(uint32_t) CTrsp->Explanation,
 					vport->fc_flag);
+
+			lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+				"GID_FT rsp err2  cmd:x%x rsn:x%x exp:x%x",
+				(uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
+				(uint32_t) CTrsp->ReasonCode,
+				(uint32_t) CTrsp->Explanation);
 		}
 	}
 	/* Link up / RSCN discovery */
@@ -586,12 +661,7 @@ err1:
 		lpfc_disc_start(vport);
 	}
 out:
-	lpfc_free_ct_rsp(phba, outp);
-	lpfc_mbuf_free(phba, inp->virt, inp->phys);
-	lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
-	kfree(inp);
-	kfree(bmp);
-	lpfc_sli_release_iocbq(phba, cmdiocb);
+	lpfc_ct_free_iocb(phba, cmdiocb);
 	return;
 }
 
@@ -602,7 +672,6 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 	struct lpfc_vport *vport = cmdiocb->vport;
 	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 	IOCB_t *irsp = &rspiocb->iocb;
-	struct lpfc_dmabuf *bmp = (struct lpfc_dmabuf *) cmdiocb->context3;
 	struct lpfc_dmabuf *inp = (struct lpfc_dmabuf *) cmdiocb->context1;
 	struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *) cmdiocb->context2;
 	struct lpfc_sli_ct_request *CTrsp;
@@ -613,6 +682,10 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 	did = ((struct lpfc_sli_ct_request *) inp->virt)->un.gff.PortId;
 	did = be32_to_cpu(did);
 
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+		"GFF_ID cmpl:     status:x%x/x%x did:x%x",
+		irsp->ulpStatus, irsp->un.ulpWord[4], did);
+
 	if (irsp->ulpStatus == IOSTAT_SUCCESS) {
 		/* Good status, continue checking */
 		CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
@@ -632,6 +705,15 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 			}
 		}
 	}
+	else {
+		lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+				"%d (%d):0267 NameServer GFF Rsp"
+				" x%x Error (%d %d) Data: x%x x%x\n",
+				phba->brd_no, vport->vpi, did,
+				irsp->ulpStatus, irsp->un.ulpWord[4],
+				vport->fc_flag, vport->fc_rscn_id_cnt)
+	}
+
 	/* This is a target port, unregistered port, or the GFF_ID failed */
 	ndlp = lpfc_setup_disc_node(vport, did);
 	if (ndlp) {
@@ -670,13 +752,7 @@ out:
 		}
 		lpfc_disc_start(vport);
 	}
-
-	lpfc_free_ct_rsp(phba, outp);
-	lpfc_mbuf_free(phba, inp->virt, inp->phys);
-	lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
-	kfree(inp);
-	kfree(bmp);
-	lpfc_sli_release_iocbq(phba, cmdiocb);
+	lpfc_ct_free_iocb(phba, cmdiocb);
 	return;
 }
 
@@ -686,37 +762,45 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 			struct lpfc_iocbq *rspiocb)
 {
 	struct lpfc_vport *vport = cmdiocb->vport;
-	struct lpfc_dmabuf *bmp;
 	struct lpfc_dmabuf *inp;
 	struct lpfc_dmabuf *outp;
 	IOCB_t *irsp;
 	struct lpfc_sli_ct_request *CTrsp;
 	int cmdcode, rc;
 	uint8_t retry;
+	uint32_t latt;
 
 	/* we pass cmdiocb to state machine which needs rspiocb as well */
 	cmdiocb->context_un.rsp_iocb = rspiocb;
 
 	inp = (struct lpfc_dmabuf *) cmdiocb->context1;
 	outp = (struct lpfc_dmabuf *) cmdiocb->context2;
-	bmp = (struct lpfc_dmabuf *) cmdiocb->context3;
 	irsp = &rspiocb->iocb;
 
 	cmdcode = be16_to_cpu(((struct lpfc_sli_ct_request *) inp->virt)->
 					CommandResponse.bits.CmdRsp);
 	CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
 
-	/* NS request completes status <ulpStatus> CmdRsp <CmdRsp> */
+	latt = lpfc_els_chk_latt(vport);
+
+	/* RFT request completes status <ulpStatus> CmdRsp <CmdRsp> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-			"%d (%d):0209 NS request %x completes "
-			"ulpStatus x%x / x%x "
-			"CmdRsp x%x, Context x%x, Tag x%x\n",
-			phba->brd_no, vport->vpi,
-			cmdcode, irsp->ulpStatus, irsp->un.ulpWord[4],
+			"%d (%d):0209 RFT request completes, latt %d, "
+			"ulpStatus x%x CmdRsp x%x, Context x%x, Tag x%x\n",
+			phba->brd_no, vport->vpi, latt, irsp->ulpStatus,
 			CTrsp->CommandResponse.bits.CmdRsp,
 			cmdiocb->iocb.ulpContext, cmdiocb->iocb.ulpIoTag);
 
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+		"CT cmd cmpl:     status:x%x/x%x cmd:x%x",
+		irsp->ulpStatus, irsp->un.ulpWord[4], cmdcode);
+
 	if (irsp->ulpStatus) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+			"%d (%d):0268 NS cmd %x Error (%d %d)\n",
+			phba->brd_no, vport->vpi, cmdcode,
+			irsp->ulpStatus, irsp->un.ulpWord[4]);
+
 		if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
 			((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) ||
 			 (irsp->un.ulpWord[4] == IOERR_SLI_ABORTED)))
@@ -736,12 +820,7 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 	}
 
 out:
-	lpfc_free_ct_rsp(phba, outp);
-	lpfc_mbuf_free(phba, inp->virt, inp->phys);
-	lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
-	kfree(inp);
-	kfree(bmp);
-	lpfc_sli_release_iocbq(phba, cmdiocb);
+	lpfc_ct_free_iocb(phba, cmdiocb);
 	return;
 }
 
@@ -840,31 +919,42 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
 		      struct lpfc_iocbq *) = NULL;
 	uint32_t rsp_size = 1024;
 	size_t   size;
+	int rc = 0;
 
 	ndlp = lpfc_findnode_did(vport, NameServer_DID);
-	if (ndlp == NULL || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)
-		return 1;
+	if (ndlp == NULL || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) {
+		rc=1;
+		goto ns_cmd_exit;
+	}
 
 	/* fill in BDEs for command */
 	/* Allocate buffer for command payload */
 	mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
-	if (!mp)
+	if (!mp) {
+		rc=2;
 		goto ns_cmd_exit;
+	}
 
 	INIT_LIST_HEAD(&mp->list);
 	mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys));
-	if (!mp->virt)
+	if (!mp->virt) {
+		rc=3;
 		goto ns_cmd_free_mp;
+	}
 
 	/* Allocate buffer for Buffer ptr list */
 	bmp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
-	if (!bmp)
+	if (!bmp) {
+		rc=4;
 		goto ns_cmd_free_mpvirt;
+	}
 
 	INIT_LIST_HEAD(&bmp->list);
 	bmp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(bmp->phys));
-	if (!bmp->virt)
+	if (!bmp->virt) {
+		rc=5;
 		goto ns_cmd_free_bmp;
+	}
 
 	/* NameServer Req */
 	lpfc_printf_log(phba, KERN_INFO ,LOG_DISCOVERY,
@@ -970,10 +1060,15 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
 		break;
 	}
 
-	if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry))
+	if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) {
 		/* On success, The cmpl function will free the buffers */
+		lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+			"Issue CT cmd:    cmd:x%x did:x%x",
+			cmdcode, ndlp->nlp_DID, 0);
 		return 0;
+	}
 
+	rc=6;
 	lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
 ns_cmd_free_bmp:
 	kfree(bmp);
@@ -982,6 +1077,10 @@ ns_cmd_free_mpvirt:
 ns_cmd_free_mp:
 	kfree(mp);
 ns_cmd_exit:
+	lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+		"%d (%d):0266 Issue NameServer Req x%x err %d Data: x%x x%x\n",
+			phba->brd_no, vport->vpi, cmdcode, rc, vport->fc_flag,
+			vport->fc_rscn_id_cnt);
 	return 1;
 }
 
@@ -989,7 +1088,6 @@ static void
 lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 		      struct lpfc_iocbq * rspiocb)
 {
-	struct lpfc_dmabuf *bmp = cmdiocb->context3;
 	struct lpfc_dmabuf *inp = cmdiocb->context1;
 	struct lpfc_dmabuf *outp = cmdiocb->context2;
 	struct lpfc_sli_ct_request *CTrsp = outp->virt;
@@ -998,6 +1096,25 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 	uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp;
 	uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp;
 	struct lpfc_vport *vport = cmdiocb->vport;
+	IOCB_t *irsp = &rspiocb->iocb;
+	uint32_t latt;
+
+	latt = lpfc_els_chk_latt(vport);
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
+		"FDMI cmpl:       status:x%x/x%x latt:%d",
+		irsp->ulpStatus, irsp->un.ulpWord[4], latt);
+
+	if (latt || irsp->ulpStatus) {
+		lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+			        "%d (%d):0229 FDMI cmd %04x failed, latt = %d "
+				"ulpStatus: x%x, rid x%x\n",
+			        phba->brd_no, vport->vpi,
+				be16_to_cpu(fdmi_cmd), latt, irsp->ulpStatus,
+				irsp->un.ulpWord[4]);
+		lpfc_ct_free_iocb(phba, cmdiocb);
+		return;
+	}
 
 	ndlp = lpfc_findnode_did(vport, FDMI_DID);
 	if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
@@ -1024,13 +1141,7 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 		lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RHBA);
 		break;
 	}
-
-	lpfc_free_ct_rsp(phba, outp);
-	lpfc_mbuf_free(phba, inp->virt, inp->phys);
-	lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
-	kfree(inp);
-	kfree(bmp);
-	lpfc_sli_release_iocbq(phba, cmdiocb);
+	lpfc_ct_free_iocb(phba, cmdiocb);
 	return;
 }