svn commit: r298968 - stable/10/sys/dev/isp

Alexander Motin mav at FreeBSD.org
Tue May 3 08:03:08 UTC 2016


Author: mav
Date: Tue May  3 08:03:07 2016
New Revision: 298968
URL: https://svnweb.freebsd.org/changeset/base/298968

Log:
  MFC r297867: Make all CT Pass-Through (name server requests) asynchronous.
  
  Previously we had to do it synchronously because we could not drop the lock
  due to potential scratch memory use conflicts.  Previous commits fixed that
  collision, so here it goes -- slower and less reliable external requests
  are executed asynchronously without spinning in tight loop and with more
  safe timeout handling.

Modified:
  stable/10/sys/dev/isp/isp.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/isp/isp.c
==============================================================================
--- stable/10/sys/dev/isp/isp.c	Tue May  3 08:02:00 2016	(r298967)
+++ stable/10/sys/dev/isp/isp.c	Tue May  3 08:03:07 2016	(r298968)
@@ -3078,20 +3078,31 @@ isp_fclink_test(ispsoftc_t *isp, int cha
 			fcp->isp_fabric_params = mbs.param[7];
 			fcp->isp_sns_hdl = NPH_SNS_ID;
 			r = isp_register_fc4_type_24xx(isp, chan);
-			if (r == 0)
-				isp_register_fc4_features_24xx(isp, chan);
-			isp_register_port_name_24xx(isp, chan);
+			if (fcp->isp_loopstate < LOOP_TESTING_LINK)
+				goto abort;
+			if (r != 0)
+				goto not_on_fabric;
+			r = isp_register_fc4_features_24xx(isp, chan);
+			if (fcp->isp_loopstate < LOOP_TESTING_LINK)
+				goto abort;
+			if (r != 0)
+				goto not_on_fabric;
+			r = isp_register_port_name_24xx(isp, chan);
+			if (fcp->isp_loopstate < LOOP_TESTING_LINK)
+				goto abort;
+			if (r != 0)
+				goto not_on_fabric;
 			isp_register_node_name_24xx(isp, chan);
+			if (fcp->isp_loopstate < LOOP_TESTING_LINK)
+				goto abort;
 		} else {
 			fcp->isp_sns_hdl = SNS_ID;
 			r = isp_register_fc4_type(isp, chan);
-			if (r == 0 && fcp->role == ISP_ROLE_TARGET)
+			if (r != 0)
+				goto not_on_fabric;
+			if (fcp->role == ISP_ROLE_TARGET)
 				isp_send_change_request(isp, chan);
 		}
-		if (r) {
-			isp_prt(isp, ISP_LOGWARN|ISP_LOG_SANCFG, "%s: register fc4 type failed", __func__);
-			return (-1);
-		}
 	}
 
 not_on_fabric:
@@ -3505,65 +3516,66 @@ isp_gid_ft_sns(ispsoftc_t *isp, int chan
 static int
 isp_ct_passthru(ispsoftc_t *isp, int chan, uint32_t cmd_bcnt, uint32_t rsp_bcnt)
 {
-	mbreg_t mbs;
 	fcparam *fcp = FCPARAM(isp, chan);
-	union {
-		isp_ct_pt_t plocal;
-		uint8_t q[QENTRY_LEN];
-	} un;
-	isp_ct_pt_t *pt;
-	uint8_t *scp = fcp->isp_scratch;
+	isp_ct_pt_t pt;
+	void *reqp;
+	uint8_t resp[QENTRY_LEN];
 
 	/*
 	 * Build a Passthrough IOCB in memory.
 	 */
-	pt = &un.plocal;
-	ISP_MEMZERO(un.q, QENTRY_LEN);
-	pt->ctp_header.rqs_entry_count = 1;
-	pt->ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
-	pt->ctp_handle = 0xffffffff;
-	pt->ctp_nphdl = fcp->isp_sns_hdl;
-	pt->ctp_cmd_cnt = 1;
-	pt->ctp_vpidx = ISP_GET_VPIDX(isp, chan);
-	pt->ctp_time = 10;
-	pt->ctp_rsp_cnt = 1;
-	pt->ctp_rsp_bcnt = rsp_bcnt;
-	pt->ctp_cmd_bcnt = cmd_bcnt;
-	pt->ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma+XTXOFF);
-	pt->ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma+XTXOFF);
-	pt->ctp_dataseg[0].ds_count = cmd_bcnt;
-	pt->ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma);
-	pt->ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma);
-	pt->ctp_dataseg[1].ds_count = rsp_bcnt;
-	isp_put_ct_pt(isp, pt, (isp_ct_pt_t *)&scp[CTXOFF]);
-	if (isp->isp_dblev & ISP_LOGDEBUG1)
-		isp_print_bytes(isp, "CT IOCB request", QENTRY_LEN, &scp[CTXOFF]);
+	ISP_MEMZERO(&pt, sizeof(pt));
+	pt.ctp_header.rqs_entry_count = 1;
+	pt.ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
+	pt.ctp_nphdl = fcp->isp_sns_hdl;
+	pt.ctp_cmd_cnt = 1;
+	pt.ctp_vpidx = ISP_GET_VPIDX(isp, chan);
+	pt.ctp_time = 10;
+	pt.ctp_rsp_cnt = 1;
+	pt.ctp_rsp_bcnt = rsp_bcnt;
+	pt.ctp_cmd_bcnt = cmd_bcnt;
+	pt.ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma+XTXOFF);
+	pt.ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma+XTXOFF);
+	pt.ctp_dataseg[0].ds_count = cmd_bcnt;
+	pt.ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma);
+	pt.ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma);
+	pt.ctp_dataseg[1].ds_count = rsp_bcnt;
+
+	/* Prepare space for response in memory */
+	memset(resp, 0xff, sizeof(resp));
+	pt.ctp_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL);
+	if (pt.ctp_handle == 0) {
+		isp_prt(isp, ISP_LOGERR,
+		    "%s: CTP of Chan %d out of handles", __func__, chan);
+		return (-1);
+	}
 
-	/*
-	 * Execute the Passthrough IOCB.
-	 */
-	ISP_MEMZERO(&scp[ZTXOFF], QENTRY_LEN);
-	MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL,
-	    MBCMD_DEFAULT_TIMEOUT + pt->ctp_time * 1000000);
-	mbs.param[1] = QENTRY_LEN;
-	mbs.param[2] = DMA_WD1(fcp->isp_scdma + CTXOFF);
-	mbs.param[3] = DMA_WD0(fcp->isp_scdma + CTXOFF);
-	mbs.param[6] = DMA_WD3(fcp->isp_scdma + CTXOFF);
-	mbs.param[7] = DMA_WD2(fcp->isp_scdma + CTXOFF);
-	MEMORYBARRIER(isp, SYNC_SFORDEV, XTXOFF, 2 * QENTRY_LEN, chan);
-	isp_mboxcmd(isp, &mbs);
-	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+	/* Send request and wait for response. */
+	reqp = isp_getrqentry(isp);
+	if (reqp == NULL) {
+		isp_prt(isp, ISP_LOGERR,
+		    "%s: CTP of Chan %d out of rqent", __func__, chan);
+		isp_destroy_handle(isp, pt.ctp_handle);
 		return (-1);
 	}
-	MEMORYBARRIER(isp, SYNC_SFORCPU, 0, ISP_FC_SCRLEN, chan);
+	isp_put_ct_pt(isp, &pt, (isp_ct_pt_t *)reqp);
 	if (isp->isp_dblev & ISP_LOGDEBUG1)
-		isp_print_bytes(isp, "CT IOCB response", QENTRY_LEN, &scp[ZTXOFF]);
-	pt = &un.plocal;
-	isp_get_ct_pt(isp, (isp_ct_pt_t *) &scp[ZTXOFF], pt);
-	if (pt->ctp_status && pt->ctp_status != RQCS_DATA_UNDERRUN) {
+		isp_print_bytes(isp, "CT IOCB request", QENTRY_LEN, reqp);
+	ISP_SYNC_REQUEST(isp);
+	if (msleep(resp, &isp->isp_lock, 0, "CTP", pt.ctp_time*hz) == EWOULDBLOCK) {
+		isp_prt(isp, ISP_LOGERR,
+		    "%s: CTP of Chan %d timed out", __func__, chan);
+		isp_destroy_handle(isp, pt.ctp_handle);
+		return (-1);
+	}
+	if (isp->isp_dblev & ISP_LOGDEBUG1)
+		isp_print_bytes(isp, "CT IOCB response", QENTRY_LEN, resp);
+
+	isp_get_ct_pt(isp, (isp_ct_pt_t *)resp, &pt);
+	if (pt.ctp_status && pt.ctp_status != RQCS_DATA_UNDERRUN) {
 		isp_prt(isp, ISP_LOGWARN,
 		    "Chan %d GID_FT CT Passthrough returned 0x%x",
-		    chan, pt->ctp_status);
+		    chan, pt.ctp_status);
 		return (-1);
 	}
 
@@ -3931,7 +3943,13 @@ isp_send_change_request(ispsoftc_t *isp,
 	mbs.param[1] = 0x03;
 	mbs.param[9] = chan;
 	isp_mboxcmd(isp, &mbs);
-	return (mbs.param[0] == MBOX_COMMAND_COMPLETE ? 0 : -1);
+	if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
+		return (0);
+	} else {
+		isp_prt(isp, ISP_LOGWARN, "Chan %d Send Change Request: 0x%x",
+		    chan, mbs.param[0]);
+		return (-1);
+	}
 }
 
 static int
@@ -3970,6 +3988,8 @@ isp_register_fc4_type(ispsoftc_t *isp, i
 	if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
 		return (0);
 	} else {
+		isp_prt(isp, ISP_LOGWARN, "Chan %d Register FC4 Type: 0x%x",
+		    chan, mbs.param[0]);
 		return (-1);
 	}
 }
@@ -6140,6 +6160,7 @@ isp_handle_other_response(ispsoftc_t *is
 			}
 		}
 		return (1);
+	case RQSTYPE_CT_PASSTHRU:
 	case RQSTYPE_VP_MODIFY:
 	case RQSTYPE_VP_CTRL:
 	case RQSTYPE_LOGIN:


More information about the svn-src-all mailing list