Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 26 Dec 2015 04:26:33 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r292739 - head/sys/dev/isp
Message-ID:  <201512260426.tBQ4QXmq073553@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Sat Dec 26 04:26:32 2015
New Revision: 292739
URL: https://svnweb.freebsd.org/changeset/base/292739

Log:
  Make virtual ports control asynchronous.
  
  Before this change virtual ports control IOCBs were executed synchronously
  via Execute IOCB mailbox command.  It required exclusive use of scratch
  space of driver and mailbox registers of the hardware.  Because of that
  shared resources use this code could not really sleep, having to spin for
  completion, blocking any other operation.
  
  This change introduces new asynchronous design, sending the IOCBs directly
  on request queue and gracefully waiting for their return on response queue.
  Returned IOCBs are identified with unified handle space from r292725.

Modified:
  head/sys/dev/isp/isp.c
  head/sys/dev/isp/isp_library.c
  head/sys/dev/isp/ispvar.h

Modified: head/sys/dev/isp/isp.c
==============================================================================
--- head/sys/dev/isp/isp.c	Sat Dec 26 02:31:39 2015	(r292738)
+++ head/sys/dev/isp/isp.c	Sat Dec 26 04:26:32 2015	(r292739)
@@ -2348,64 +2348,64 @@ static int
 isp_fc_enable_vp(ispsoftc_t *isp, int chan)
 {
 	fcparam *fcp = FCPARAM(isp, chan);
-	mbreg_t mbs;
-	vp_modify_t *vp;
-	uint8_t qe[QENTRY_LEN], *scp;
-
-	ISP_MEMZERO(qe, QENTRY_LEN);
-	if (FC_SCRATCH_ACQUIRE(isp, chan)) {
-		return (EBUSY);
-	}
-	scp = fcp->isp_scratch;
+	vp_modify_t vp;
+	void *reqp;
+	uint8_t resp[QENTRY_LEN];
 
 	/* Build a VP MODIFY command in memory */
-	vp = (vp_modify_t *) qe;
-	vp->vp_mod_hdr.rqs_entry_type = RQSTYPE_VP_MODIFY;
-	vp->vp_mod_hdr.rqs_entry_count = 1;
-	vp->vp_mod_cnt = 1;
-	vp->vp_mod_idx0 = chan;
-	vp->vp_mod_cmd = VP_MODIFY_ENA;
-	vp->vp_mod_ports[0].options = ICB2400_VPOPT_ENABLED |
+	ISP_MEMZERO(&vp, sizeof(vp));
+	vp.vp_mod_hdr.rqs_entry_type = RQSTYPE_VP_MODIFY;
+	vp.vp_mod_hdr.rqs_entry_count = 1;
+	vp.vp_mod_cnt = 1;
+	vp.vp_mod_idx0 = chan;
+	vp.vp_mod_cmd = VP_MODIFY_ENA;
+	vp.vp_mod_ports[0].options = ICB2400_VPOPT_ENABLED |
 	    ICB2400_VPOPT_ENA_SNSLOGIN;
-	if (fcp->role & ISP_ROLE_INITIATOR) {
-		vp->vp_mod_ports[0].options |= ICB2400_VPOPT_INI_ENABLE;
-	}
-	if ((fcp->role & ISP_ROLE_TARGET) == 0) {
-		vp->vp_mod_ports[0].options |= ICB2400_VPOPT_TGT_DISABLE;
-	}
+	if (fcp->role & ISP_ROLE_INITIATOR)
+		vp.vp_mod_ports[0].options |= ICB2400_VPOPT_INI_ENABLE;
+	if ((fcp->role & ISP_ROLE_TARGET) == 0)
+		vp.vp_mod_ports[0].options |= ICB2400_VPOPT_TGT_DISABLE;
 	if (fcp->isp_loopid < LOCAL_LOOP_LIM) {
-		vp->vp_mod_ports[0].loopid = fcp->isp_loopid;
+		vp.vp_mod_ports[0].loopid = fcp->isp_loopid;
 		if (isp->isp_confopts & ISP_CFG_OWNLOOPID)
-			vp->vp_mod_ports[0].options |=
-			    ICB2400_VPOPT_HARD_ADDRESS;
+			vp.vp_mod_ports[0].options |= ICB2400_VPOPT_HARD_ADDRESS;
 		else
-			vp->vp_mod_ports[0].options |=
-			    ICB2400_VPOPT_PREV_ADDRESS;
+			vp.vp_mod_ports[0].options |= ICB2400_VPOPT_PREV_ADDRESS;
 	}
-	MAKE_NODE_NAME_FROM_WWN(vp->vp_mod_ports[0].wwpn, fcp->isp_wwpn);
-	MAKE_NODE_NAME_FROM_WWN(vp->vp_mod_ports[0].wwnn, fcp->isp_wwnn);
-	isp_put_vp_modify(isp, vp, (vp_modify_t *) scp);
+	MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwpn, fcp->isp_wwpn);
+	MAKE_NODE_NAME_FROM_WWN(vp.vp_mod_ports[0].wwnn, fcp->isp_wwnn);
 
-	/* Build a EXEC IOCB A64 command that points to the VP MODIFY command */
-	MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 0);
-	mbs.param[1] = QENTRY_LEN;
-	mbs.param[2] = DMA_WD1(fcp->isp_scdma);
-	mbs.param[3] = DMA_WD0(fcp->isp_scdma);
-	mbs.param[6] = DMA_WD3(fcp->isp_scdma);
-	mbs.param[7] = DMA_WD2(fcp->isp_scdma);
-	MEMORYBARRIER(isp, SYNC_SFORDEV, 0, 2 * QENTRY_LEN, chan);
-	isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
-	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
-		FC_SCRATCH_RELEASE(isp, chan);
+	/* Prepare space for response in memory */
+	memset(resp, 0xff, sizeof(resp));
+	vp.vp_mod_hdl = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL);
+	if (vp.vp_mod_hdl == 0) {
+		isp_prt(isp, ISP_LOGERR,
+		    "%s: VP_MODIFY of Chan %d out of handles", __func__, chan);
 		return (EIO);
 	}
-	MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN, QENTRY_LEN, chan);
-	isp_get_vp_modify(isp, (vp_modify_t *)&scp[QENTRY_LEN], vp);
 
-	FC_SCRATCH_RELEASE(isp, chan);
+	/* Send request and wait for response. */
+	reqp = isp_getrqentry(isp);
+	if (reqp == NULL) {
+		isp_prt(isp, ISP_LOGERR,
+		    "%s: VP_MODIFY of Chan %d out of rqent", __func__, chan);
+		isp_destroy_handle(isp, vp.vp_mod_hdl);
+		return (EIO);
+	}
+	isp_put_vp_modify(isp, &vp, (vp_modify_t *)reqp);
+	ISP_SYNC_REQUEST(isp);
+	if (msleep(resp, &isp->isp_lock, 0, "VP_MODIFY", 5*hz) == EWOULDBLOCK) {
+		isp_prt(isp, ISP_LOGERR,
+		    "%s: VP_MODIFY of Chan %d timed out", __func__, chan);
+		isp_destroy_handle(isp, vp.vp_mod_hdl);
+		return (EIO);
+	}
+	isp_get_vp_modify(isp, (vp_modify_t *)resp, &vp);
 
-	if (vp->vp_mod_status != VP_STS_OK) {
-		isp_prt(isp, ISP_LOGERR, "%s: VP_MODIFY of Chan %d failed with status %d", __func__, chan, vp->vp_mod_status);
+	if (vp.vp_mod_hdr.rqs_flags != 0 || vp.vp_mod_status != VP_STS_OK) {
+		isp_prt(isp, ISP_LOGERR,
+		    "%s: VP_MODIFY of Chan %d failed with flags %x status %d",
+		    __func__, chan, vp.vp_mod_hdr.rqs_flags, vp.vp_mod_status);
 		return (EIO);
 	}
 	return (0);
@@ -2414,54 +2414,56 @@ isp_fc_enable_vp(ispsoftc_t *isp, int ch
 static int
 isp_fc_disable_vp(ispsoftc_t *isp, int chan)
 {
-	fcparam *fcp = FCPARAM(isp, chan);
-	mbreg_t mbs;
-	vp_ctrl_info_t *vp;
-	uint8_t qe[QENTRY_LEN], *scp;
-
-	ISP_MEMZERO(qe, QENTRY_LEN);
-	if (FC_SCRATCH_ACQUIRE(isp, chan)) {
-		return (EBUSY);
-	}
-	scp = fcp->isp_scratch;
+	vp_ctrl_info_t vp;
+	void *reqp;
+	uint8_t resp[QENTRY_LEN];
 
 	/* Build a VP CTRL command in memory */
-	vp = (vp_ctrl_info_t *) qe;
-	vp->vp_ctrl_hdr.rqs_entry_type = RQSTYPE_VP_CTRL;
-	vp->vp_ctrl_hdr.rqs_entry_count = 1;
+	ISP_MEMZERO(&vp, sizeof(vp));
+	vp.vp_ctrl_hdr.rqs_entry_type = RQSTYPE_VP_CTRL;
+	vp.vp_ctrl_hdr.rqs_entry_count = 1;
 	if (ISP_CAP_VP0(isp)) {
-		vp->vp_ctrl_status = 1;
+		vp.vp_ctrl_status = 1;
 	} else {
-		vp->vp_ctrl_status = 0;
+		vp.vp_ctrl_status = 0;
 		chan--;	/* VP0 can not be controlled in this case. */
 	}
-	vp->vp_ctrl_command = VP_CTRL_CMD_DISABLE_VP_LOGO_ALL;
-	vp->vp_ctrl_vp_count = 1;
-	vp->vp_ctrl_idmap[chan / 16] |= (1 << chan % 16);
-	isp_put_vp_ctrl_info(isp, vp, (vp_ctrl_info_t *) scp);
-
-	/* Build a EXEC IOCB A64 command that points to the VP CTRL command */
-	MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 0);
-	mbs.param[1] = QENTRY_LEN;
-	mbs.param[2] = DMA_WD1(fcp->isp_scdma);
-	mbs.param[3] = DMA_WD0(fcp->isp_scdma);
-	mbs.param[6] = DMA_WD3(fcp->isp_scdma);
-	mbs.param[7] = DMA_WD2(fcp->isp_scdma);
-	MEMORYBARRIER(isp, SYNC_SFORDEV, 0, 2 * QENTRY_LEN, chan);
-	isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
-	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
-		FC_SCRATCH_RELEASE(isp, chan);
+	vp.vp_ctrl_command = VP_CTRL_CMD_DISABLE_VP_LOGO_ALL;
+	vp.vp_ctrl_vp_count = 1;
+	vp.vp_ctrl_idmap[chan / 16] |= (1 << chan % 16);
+
+	/* Prepare space for response in memory */
+	memset(resp, 0xff, sizeof(resp));
+	vp.vp_ctrl_handle = isp_allocate_handle(isp, resp, ISP_HANDLE_CTRL);
+	if (vp.vp_ctrl_handle == 0) {
+		isp_prt(isp, ISP_LOGERR,
+		    "%s: VP_CTRL of Chan %d out of handles", __func__, chan);
 		return (EIO);
 	}
-	MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN, QENTRY_LEN, chan);
-	isp_get_vp_ctrl_info(isp, (vp_ctrl_info_t *)&scp[QENTRY_LEN], vp);
 
-	FC_SCRATCH_RELEASE(isp, chan);
+	/* Send request and wait for response. */
+	reqp = isp_getrqentry(isp);
+	if (reqp == NULL) {
+		isp_prt(isp, ISP_LOGERR,
+		    "%s: VP_CTRL of Chan %d out of rqent", __func__, chan);
+		isp_destroy_handle(isp, vp.vp_ctrl_handle);
+		return (EIO);
+	}
+	isp_put_vp_ctrl_info(isp, &vp, (vp_ctrl_info_t *)reqp);
+	ISP_SYNC_REQUEST(isp);
+	if (msleep(resp, &isp->isp_lock, 0, "VP_CTRL", 5*hz) == EWOULDBLOCK) {
+		isp_prt(isp, ISP_LOGERR,
+		    "%s: VP_CTRL of Chan %d timed out", __func__, chan);
+		isp_destroy_handle(isp, vp.vp_ctrl_handle);
+		return (EIO);
+	}
+	isp_get_vp_ctrl_info(isp, (vp_ctrl_info_t *)resp, &vp);
 
-	if (vp->vp_ctrl_status != 0) {
+	if (vp.vp_ctrl_hdr.rqs_flags != 0 || vp.vp_ctrl_status != 0) {
 		isp_prt(isp, ISP_LOGERR,
-		    "%s: VP_CTRL of Chan %d failed with status %d %d",
-		    __func__, chan, vp->vp_ctrl_status, vp->vp_ctrl_index_fail);
+		    "%s: VP_CTRL of Chan %d failed with flags %x status %d %d",
+		    __func__, chan, vp.vp_ctrl_hdr.rqs_flags,
+		    vp.vp_ctrl_status, vp.vp_ctrl_index_fail);
 		return (EIO);
 	}
 	return (0);
@@ -6123,6 +6125,8 @@ isp_handle_other_response(ispsoftc_t *is
 {
 	isp_ridacq_t rid;
 	int chan, c;
+	uint32_t hdl;
+	void *ptr;
 
 	switch (type) {
 	case RQSTYPE_STATUS_CONT:
@@ -6164,6 +6168,16 @@ isp_handle_other_response(ispsoftc_t *is
 			}
 		}
 		return (1);
+	case RQSTYPE_VP_MODIFY:
+	case RQSTYPE_VP_CTRL:
+		ISP_IOXGET_32(isp, (uint32_t *)(hp + 1), hdl);
+		ptr = isp_find_xs(isp, hdl);
+		if (ptr != NULL) {
+			isp_destroy_handle(isp, hdl);
+			memcpy(ptr, hp, QENTRY_LEN);
+			wakeup(ptr);
+		}
+		return (1);
 	case RQSTYPE_ATIO:
 	case RQSTYPE_CTIO:
 	case RQSTYPE_ENABLE_LUN:

Modified: head/sys/dev/isp/isp_library.c
==============================================================================
--- head/sys/dev/isp/isp_library.c	Sat Dec 26 02:31:39 2015	(r292738)
+++ head/sys/dev/isp/isp_library.c	Sat Dec 26 04:26:32 2015	(r292739)
@@ -572,7 +572,8 @@ isp_clear_commands(ispsoftc_t *isp)
 	for (tmp = 0; isp->isp_xflist && tmp < isp->isp_maxcmds; tmp++) {
 
 		hdp = &isp->isp_xflist[tmp];
-		if (ISP_H2HT(hdp->handle) == ISP_HANDLE_INITIATOR) {
+		switch (ISP_H2HT(hdp->handle)) {
+		case ISP_HANDLE_INITIATOR: {
 			XS_T *xs = hdp->cmd;
 			if (XS_XFRLEN(xs)) {
 				ISP_DMAFREE(isp, xs, hdp->handle);
@@ -580,12 +581,13 @@ isp_clear_commands(ispsoftc_t *isp)
 			} else {
 				XS_SET_RESID(xs, 0);
 			}
-			hdp->handle = 0;
-			hdp->cmd = NULL;
+			isp_destroy_handle(isp, hdp->handle);
 			XS_SETERR(xs, HBA_BUSRESET);
 			isp_done(xs);
+			break;
+		}
 #ifdef	ISP_TARGET_MODE
-		} else if (ISP_H2HT(hdp->handle) == ISP_HANDLE_TARGET) {
+		case ISP_HANDLE_TARGET: {
 			uint8_t local[QENTRY_LEN];
 			ISP_DMAFREE(isp, hdp->cmd, hdp->handle);
 			ISP_MEMZERO(local, QENTRY_LEN);
@@ -601,7 +603,13 @@ isp_clear_commands(ispsoftc_t *isp)
 				ctio->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
 			}
 			isp_async(isp, ISPASYNC_TARGET_ACTION, local);
+			break;
+		}
 #endif
+		case ISP_HANDLE_CTRL:
+			wakeup(hdp->cmd);
+			isp_destroy_handle(isp, hdp->handle);
+			break;
 		}
 	}
 #ifdef	ISP_TARGET_MODE

Modified: head/sys/dev/isp/ispvar.h
==============================================================================
--- head/sys/dev/isp/ispvar.h	Sat Dec 26 02:31:39 2015	(r292738)
+++ head/sys/dev/isp/ispvar.h	Sat Dec 26 04:26:32 2015	(r292739)
@@ -315,12 +315,14 @@ typedef struct {
 #	define	ISP_HANDLE_NONE		0
 #	define	ISP_HANDLE_INITIATOR	1
 #	define	ISP_HANDLE_TARGET	2
+#	define	ISP_HANDLE_CTRL		3
 #define	ISP_HANDLE_SEQ_MASK	0xffff0000
 #define	ISP_HANDLE_SEQ_SHIFT	16
 #define	ISP_H2SEQ(hdl)	((hdl & ISP_HANDLE_SEQ_MASK) >> ISP_HANDLE_SEQ_SHIFT)
 #define	ISP_VALID_HANDLE(c, hdl)	\
 	((ISP_H2HT(hdl) == ISP_HANDLE_INITIATOR || \
-	  ISP_H2HT(hdl) == ISP_HANDLE_TARGET) && \
+	  ISP_H2HT(hdl) == ISP_HANDLE_TARGET || \
+	  ISP_H2HT(hdl) == ISP_HANDLE_CTRL) && \
 	 ((hdl) & ISP_HANDLE_CMD_MASK) < (c)->isp_maxcmds && \
 	 (hdl) == ((c)->isp_xflist[(hdl) & ISP_HANDLE_CMD_MASK].handle))
 #define	ISP_BAD_HANDLE_INDEX	0xffffffff



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201512260426.tBQ4QXmq073553>