svn commit: r203444 - head/sys/dev/isp

Matt Jacob mjacob at FreeBSD.org
Wed Feb 3 21:09:33 UTC 2010


Author: mjacob
Date: Wed Feb  3 21:09:32 2010
New Revision: 203444
URL: http://svn.freebsd.org/changeset/base/203444

Log:
  Redo how commands handles are created and managed and implement sequence
  numbers and handle types in rational way. This will better protect from
  (unwittingly) dealing with stale handles/commands.
  
  Fix the watchdog timeout code to better protect itself from mistakes.
  
  If we run an abort on a putatively timed out command, the command
  may in fact get completed, so check to make sure the command we're
  timing it out is still around. If the abort succeeds, btw, the command
  should get returned via a different path.

Modified:
  head/sys/dev/isp/isp.c
  head/sys/dev/isp/isp_freebsd.c
  head/sys/dev/isp/isp_library.c
  head/sys/dev/isp/isp_library.h
  head/sys/dev/isp/isp_pci.c
  head/sys/dev/isp/isp_sbus.c
  head/sys/dev/isp/ispmbox.h
  head/sys/dev/isp/ispvar.h

Modified: head/sys/dev/isp/isp.c
==============================================================================
--- head/sys/dev/isp/isp.c	Wed Feb  3 21:06:13 2010	(r203443)
+++ head/sys/dev/isp/isp.c	Wed Feb  3 21:09:32 2010	(r203444)
@@ -694,7 +694,7 @@ isp_reset(ispsoftc_t *isp, int do_load_d
 	mbs.logval = MBLOGALL;
 	isp_mboxcmd(isp, &mbs);
 	if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
-		isp_prt(isp, ISP_LOGERR, "NOP ommand failed (%x)", mbs.param[0]);
+		isp_prt(isp, ISP_LOGERR, "NOP command failed (%x)", mbs.param[0]);
 		ISP_RESET0(isp);
 		return;
 	}
@@ -4417,7 +4417,7 @@ isp_start(XS_T *xs)
 		*tptr = 0x1999;
 	}
 
-	if (isp_save_xs(isp, xs, &handle)) {
+	if (isp_allocate_xs(isp, xs, &handle)) {
 		isp_prt(isp, ISP_LOGDEBUG0, "out of xflist pointers");
 		XS_SETERR(xs, HBA_BOTCH);
 		return (CMD_EAGAIN);
@@ -5163,8 +5163,8 @@ again:
 			}
 		}
 
-		if ((sp->req_handle != ISP_SPCL_HANDLE) && (sp->req_handle > isp->isp_maxcmds || sp->req_handle < 1)) {
-			isp_prt(isp, ISP_LOGERR, "bad request handle %d (type 0x%x)", sp->req_handle, etype);
+		if (!ISP_VALID_HANDLE(isp, sp->req_handle)) {
+			isp_prt(isp, ISP_LOGERR, "bad request handle 0x%x (iocb type 0x%x)", sp->req_handle, etype);
 			ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
 			ISP_WRITE(isp, isp->isp_respoutrp, optr);
 			continue;
@@ -5178,7 +5178,7 @@ again:
 			 */
 			if (etype != RQSTYPE_RESPONSE) {
 				isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (type 0x%x)", sp->req_handle, etype);
-			} else if (ts != RQCS_ABORTED && ts != RQCS_RESET_OCCURRED && sp->req_handle != ISP_SPCL_HANDLE) {
+			} else if (ts != RQCS_ABORTED && ts != RQCS_RESET_OCCURRED) {
 				isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (status 0x%x)", sp->req_handle, ts);
 			}
 			ISP_MEMZERO(hp, QENTRY_LEN);	/* PERF */
@@ -5681,16 +5681,19 @@ isp_parse_async(ispsoftc_t *isp, uint16_
 			 * commands that complete (with no apparent error) after
 			 * we receive a LIP. This has been observed mostly on
 			 * Local Loop topologies. To be safe, let's just mark
-			 * all active commands as dead.
+			 * all active initiator commands as dead.
 			 */
 			if (topo == TOPO_NL_PORT || topo == TOPO_FL_PORT) {
 				int i, j;
 				for (i = j = 0; i < isp->isp_maxcmds; i++) {
 					XS_T *xs;
-					xs = isp->isp_xflist[i];
-					if (xs == NULL) {
+					isp_hdl_t *hdp;
+
+					hdp = &isp->isp_xflist[i];
+					if (ISP_H2HT(hdp->handle) != ISP_HANDLE_INITIATOR) {
 						continue;
 					}
+					xs = hdp->cmd;
 					if (XS_CHANNEL(xs) != chan) {
 						continue;
 					}

Modified: head/sys/dev/isp/isp_freebsd.c
==============================================================================
--- head/sys/dev/isp/isp_freebsd.c	Wed Feb  3 21:06:13 2010	(r203443)
+++ head/sys/dev/isp/isp_freebsd.c	Wed Feb  3 21:09:32 2010	(r203444)
@@ -1653,7 +1653,7 @@ isp_target_start_ctio(ispsoftc_t *isp, u
 		cto->ct_timeout = 10;
 	}
 
-	if (isp_save_xs_tgt(isp, ccb, &handle)) {
+	if (isp_allocate_xs_tgt(isp, ccb, &handle)) {
 		xpt_print(ccb->ccb_h.path, "No XFLIST pointers for %s\n", __func__);
 		ccb->ccb_h.status = CAM_REQUEUE_REQ;
 		goto out;
@@ -3834,21 +3834,41 @@ isp_watchdog(void *arg)
 	isp = XS_ISP(xs);
 
 	handle = isp_find_handle(isp, xs);
-	if (handle) {
+	if (handle != ISP_HANDLE_FREE) {
 		/*
-		 * Make sure the command is *really* dead before we
-		 * release the handle (and DMA resources) for reuse.
+		 * Try and make sure the command is really dead before
+		 * we release the handle (and DMA resources) for reuse.
+		 *
+		 * If we are successful in aborting the command then
+		 * we're done here because we'll get the command returned
+		 * back separately.
+		 */
+		if (isp_control(isp, ISPCTL_ABORT_CMD, xs) == 0) {
+			return;
+		}
+
+		/*
+		 * Note that after calling the above, the command may in
+		 * fact have been completed.
 		 */
-		(void) isp_control(isp, ISPCTL_ABORT_CMD, xs);
+		xs = isp_find_xs(isp, handle);
+
+		/*
+		 * If the command no longer exists, then we won't
+		 * be able to find the xs again with this handle.
+		 */
+		if (xs == NULL) {
+			return;
+		}
 
 		/*
-		 * After this point, the comamnd is really dead.
+		 * After this point, the command is really dead.
 		 */
 		if (XS_XFRLEN(xs)) {
 			ISP_DMAFREE(isp, xs, handle);
 		} 
 		isp_destroy_handle(isp, handle);
-		xpt_print(xs->ccb_h.path, "watchdog timeout for handle 0x%x\n", handle);
+		isp_prt(isp, ISP_LOGERR, "%s: timeout for handle 0x%x", __func__, handle);
 		XS_SETERR(xs, CAM_CMD_TIMEOUT);
 		isp_done(xs);
 	}

Modified: head/sys/dev/isp/isp_library.c
==============================================================================
--- head/sys/dev/isp/isp_library.c	Wed Feb  3 21:06:13 2010	(r203443)
+++ head/sys/dev/isp/isp_library.c	Wed Feb  3 21:09:32 2010	(r203444)
@@ -246,65 +246,70 @@ copy_and_sync:
 }
 
 int
-isp_save_xs(ispsoftc_t *isp, XS_T *xs, uint32_t *handlep)
+isp_allocate_xs(ispsoftc_t *isp, XS_T *xs, uint32_t *handlep)
 {
-	uint16_t i, j;
+	isp_hdl_t *hdp;
 
-	for (j = isp->isp_lasthdls, i = 0; i < isp->isp_maxcmds; i++) {
-		if (isp->isp_xflist[j] == NULL) {
-			break;
-		}
-		if (++j == isp->isp_maxcmds) {
-			j = 0;
-		}
-	}
-	if (i == isp->isp_maxcmds) {
+	hdp = isp->isp_xffree;
+	if (hdp == NULL) {
 		return (-1);
 	}
-	isp->isp_xflist[j] = xs;
-	*handlep = j+1;
-	if (++j == isp->isp_maxcmds) {
-		j = 0;
-	}
-	isp->isp_lasthdls = (uint32_t)j;
+	isp->isp_xffree = hdp->cmd;
+	hdp->cmd = xs;
+	hdp->handle = (hdp - isp->isp_xflist);
+	hdp->handle |= (ISP_HANDLE_INITIATOR << ISP_HANDLE_USAGE_SHIFT);
+	hdp->handle |= (isp->isp_seqno++ << ISP_HANDLE_SEQ_SHIFT);
+	*handlep = hdp->handle;
 	return (0);
 }
 
 XS_T *
 isp_find_xs(ispsoftc_t *isp, uint32_t handle)
 {
-	if (handle < 1 || handle > (uint32_t) isp->isp_maxcmds) {
+	if (!ISP_VALID_INI_HANDLE(isp, handle)) {
+		isp_prt(isp, ISP_LOGERR, "%s: bad handle 0x%x", __func__, handle);
 		return (NULL);
-	} else {
-		return (isp->isp_xflist[handle - 1]);
 	}
+	return (isp->isp_xflist[(handle & ISP_HANDLE_CMD_MASK)].cmd);
 }
 
 uint32_t
 isp_find_handle(ispsoftc_t *isp, XS_T *xs)
 {
-	uint16_t i;
+	uint32_t i, foundhdl = ISP_HANDLE_FREE;
+
 	if (xs != NULL) {
 		for (i = 0; i < isp->isp_maxcmds; i++) {
-			if (isp->isp_xflist[i] == xs) {
-				return ((uint32_t) (i+1));
+			if (isp->isp_xflist[i].cmd != xs) {
+				continue;
 			}
+			foundhdl = isp->isp_xflist[i].handle;
+			break;
 		}
 	}
-	return (0);
+	return (foundhdl);
 }
 
 uint32_t
-isp_handle_index(uint32_t handle)
+isp_handle_index(ispsoftc_t *isp, uint32_t handle)
 {
-	return (handle - 1);
+	if (!ISP_VALID_HANDLE(isp, handle)) {
+		return (handle & ISP_HANDLE_CMD_MASK);
+	} else {
+		isp_prt(isp, ISP_LOGERR, "%s: bad handle 0x%x", __func__, handle);
+		return (ISP_BAD_HANDLE_INDEX);
+	}
 }
 
 void
 isp_destroy_handle(ispsoftc_t *isp, uint32_t handle)
 {
-	if (handle > 0 && handle <= (uint32_t) isp->isp_maxcmds) {
-		isp->isp_xflist[handle - 1] = NULL;
+	if (!ISP_VALID_INI_HANDLE(isp, handle)) {
+		isp_prt(isp, ISP_LOGERR, "%s: bad handle 0x%x", __func__, handle);
+	} else {
+		isp->isp_xflist[(handle & ISP_HANDLE_CMD_MASK)].handle = ISP_HANDLE_FREE;
+		isp->isp_xflist[(handle & ISP_HANDLE_CMD_MASK)].cmd = isp->isp_xffree;
+		isp->isp_xffree = &isp->isp_xflist[(handle & ISP_HANDLE_CMD_MASK)];
 	}
 }
 
@@ -617,54 +622,48 @@ isp_fc_change_role(ispsoftc_t *isp, int 
 void
 isp_clear_commands(ispsoftc_t *isp)
 {
-	XS_T *xs;
-	uint32_t tmp, handle;
+	uint32_t tmp;
+	isp_hdl_t *hdp;
 #ifdef	ISP_TARGET_MODE
 	isp_notify_t notify;
 #endif
 
 	for (tmp = 0; isp->isp_xflist && tmp < isp->isp_maxcmds; tmp++) {
-		xs = isp->isp_xflist[tmp];
-		if (xs == NULL) {
-			continue;
-		}
-		handle = isp_find_handle(isp, xs);
-		if (handle == 0) {
+		XS_T *xs;
+
+		hdp = &isp->isp_xflist[tmp];
+		if (hdp->handle == ISP_HANDLE_FREE) {
 			continue;
 		}
+		xs = hdp->cmd;
 		if (XS_XFRLEN(xs)) {
-			ISP_DMAFREE(isp, xs, handle);
+			ISP_DMAFREE(isp, xs, hdp->handle);
 			XS_SET_RESID(xs, XS_XFRLEN(xs));
 		} else {
 			XS_SET_RESID(xs, 0);
 		}
-		isp_destroy_handle(isp, handle);
+		hdp->handle = 0;
+		hdp->cmd = NULL;
 		XS_SETERR(xs, HBA_BUSRESET);
 		isp_done(xs);
 	}
 #ifdef	ISP_TARGET_MODE
 	for (tmp = 0; isp->isp_tgtlist && tmp < isp->isp_maxcmds; tmp++) {
 		uint8_t local[QENTRY_LEN];
-
-		xs = isp->isp_tgtlist[tmp];
-		if (xs == NULL) {
-			continue;
-		}
-		handle = isp_find_tgt_handle(isp, xs);
-		if (handle == 0) {
+		hdp = &isp->isp_tgt_xflist[tmp];
+		if (hdp->handle == ISP_HANDLE_FREE) {
 			continue;
 		}
-		ISP_DMAFREE(isp, xs, handle);
-
+		ISP_DMAFREE(isp, hdp->cmd, hdp->handle);
 		ISP_MEMZERO(local, QENTRY_LEN);
 		if (IS_24XX(isp)) {
 			ct7_entry_t *ctio = (ct7_entry_t *) local;
-			ctio->ct_syshandle = handle;
+			ctio->ct_syshandle = hdp->handle;
 			ctio->ct_nphdl = CT_HBA_RESET;
 			ctio->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
 		} else if (IS_FC(isp)) {
 			ct2_entry_t *ctio = (ct2_entry_t *) local;
-			ctio->ct_syshandle = handle;
+			ctio->ct_syshandle = hdp->handle;
 			ctio->ct_status = CT_HBA_RESET;
 			ctio->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
 		} else {
@@ -2229,59 +2228,59 @@ isp_send_tgt_cmd(ispsoftc_t *isp, void *
 }
 
 int
-isp_save_xs_tgt(ispsoftc_t *isp, void *xs, uint32_t *handlep)
+isp_allocate_xs_tgt(ispsoftc_t *isp, void *xs, uint32_t *handlep)
 {
-	int i;
+	isp_hdl_t *hdp;
 
-	for (i = 0; i < (int) isp->isp_maxcmds; i++) {
-		if (isp->isp_tgtlist[i] == NULL) {
-			break;
-		}
-	}
-	if (i == isp->isp_maxcmds) {
+	hdp = isp->isp_tgtfree;
+	if (hdp == NULL) {
 		return (-1);
 	}
-	isp->isp_tgtlist[i] = xs;
-	*handlep = (i+1) | 0x8000;
+	isp->isp_tgtfree = hdp->cmd;
+	hdp->cmd = xs;
+	hdp->handle = (hdp - isp->isp_tgtlist);
+	hdp->handle |= (ISP_HANDLE_TARGET << ISP_HANDLE_USAGE_SHIFT);
+	hdp->handle |= (isp->isp_seqno++ << ISP_HANDLE_SEQ_SHIFT);
+	*handlep = hdp->handle;
 	return (0);
 }
 
 void *
 isp_find_xs_tgt(ispsoftc_t *isp, uint32_t handle)
 {
-	if (handle == 0 || IS_TARGET_HANDLE(handle) == 0 || (handle & ISP_HANDLE_MASK) > isp->isp_maxcmds) {
-		isp_prt(isp, ISP_LOGERR, "bad handle %u in isp_find_xs_tgt", handle);
+	if (!ISP_VALID_TGT_HANDLE(isp, handle)) {
+		isp_prt(isp, ISP_LOGERR, "%s: bad handle 0x%x", __func__, handle);
 		return (NULL);
-	} else {
-		return (isp->isp_tgtlist[(handle & ISP_HANDLE_MASK) - 1]);
 	}
+	return (isp->isp_tgtlist[(handle & ISP_HANDLE_CMD_MASK)].cmd);
 }
 
 uint32_t
 isp_find_tgt_handle(ispsoftc_t *isp, void *xs)
 {
-	int i;
+	uint32_t i, foundhdl = ISP_HANDLE_FREE;
+
 	if (xs != NULL) {
 		for (i = 0; i < isp->isp_maxcmds; i++) {
-			if (isp->isp_tgtlist[i] == xs) {
-				uint32_t handle = i;
-				handle += 1;
-				handle &= ISP_HANDLE_MASK;
-				handle |= 0x8000;
-				return (handle);
+			if (isp->isp_tgtlist[i].cmd != xs) {
+				continue;
 			}
+			foundhdl = isp->isp_tgtlist[i].handle;
+			break;
 		}
 	}
-	return (0);
+	return (foundhdl);
 }
 
 void
 isp_destroy_tgt_handle(ispsoftc_t *isp, uint32_t handle)
 {
-	if (handle == 0 || IS_TARGET_HANDLE(handle) == 0 || (handle & ISP_HANDLE_MASK) > isp->isp_maxcmds) {
-		isp_prt(isp, ISP_LOGERR, "bad handle in isp_destroy_tgt_handle");
+	if (!ISP_VALID_TGT_HANDLE(handle)) {
+		isp_prt(isp, ISP_LOGERR, "%s: bad handle 0x%x", __func__, handle);
 	} else {
-		isp->isp_tgtlist[(handle & ISP_HANDLE_MASK) - 1] = NULL;
+		isp->isp_tgtlist[(handle & ISP_HANDLE_CMD_MASK)].handle = ISP_HANDLE_FREE;
+		isp->isp_tgtlist[(handle & ISP_HANDLE_CMD_MASK)].cmd = isp->isp_tgtfree;
+		isp->isp_tgtfree = &isp->isp_tgtlist[(handle & ISP_HANDLE_CMD_MASK)];
 	}
 }
 

Modified: head/sys/dev/isp/isp_library.h
==============================================================================
--- head/sys/dev/isp/isp_library.h	Wed Feb  3 21:06:13 2010	(r203443)
+++ head/sys/dev/isp/isp_library.h	Wed Feb  3 21:09:32 2010	(r203444)
@@ -43,10 +43,10 @@ int isp_send_cmd(ispsoftc_t *, void *, v
  *
  * These handles are associate with a command.
  */
-int isp_save_xs(ispsoftc_t *, XS_T *, uint32_t *);
+int isp_allocate_xs(ispsoftc_t *, XS_T *, uint32_t *);
 XS_T * isp_find_xs(ispsoftc_t *, uint32_t);
 uint32_t isp_find_handle(ispsoftc_t *, XS_T *);
-uint32_t isp_handle_index(uint32_t);
+uint32_t isp_handle_index(ispsoftc_t *, uint32_t);
 void isp_destroy_handle(ispsoftc_t *, uint32_t);
 
 /*
@@ -156,9 +156,7 @@ void isp_put_ct_hdr(ispsoftc_t *isp, ct_
 
 int isp_send_tgt_cmd(ispsoftc_t *, void *, void *, uint32_t, uint32_t, isp_ddir_t, void *, uint32_t);
 
-#define IS_TARGET_HANDLE(x)     ((x) & 0x8000)
-
-int isp_save_xs_tgt(ispsoftc_t *, void *, uint32_t *);
+int isp_allocate_xs_tgt(ispsoftc_t *, void *, uint32_t *);
 void *isp_find_xs_tgt(ispsoftc_t *, uint32_t);
 uint32_t isp_find_tgt_handle(ispsoftc_t *, void *);
 void isp_destroy_tgt_handle(ispsoftc_t *, uint32_t);

Modified: head/sys/dev/isp/isp_pci.c
==============================================================================
--- head/sys/dev/isp/isp_pci.c	Wed Feb  3 21:06:13 2010	(r203443)
+++ head/sys/dev/isp/isp_pci.c	Wed Feb  3 21:09:32 2010	(r203444)
@@ -1516,17 +1516,21 @@ isp_pci_mbxdma(ispsoftc_t *isp)
 		return (1);
 	}
 
-	len = sizeof (XS_T **) * isp->isp_maxcmds;
-	isp->isp_xflist = (XS_T **) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
+	len = sizeof (isp_hdl_t) * isp->isp_maxcmds;
+	isp->isp_xflist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
 	if (isp->isp_xflist == NULL) {
 		free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
 		ISP_LOCK(isp);
 		isp_prt(isp, ISP_LOGERR, "cannot alloc xflist array");
 		return (1);
 	}
+	for (len = 0; len < isp->isp_maxcmds - 1; len++) {
+		isp->isp_xflist[len].cmd = &isp->isp_xflist[len+1];
+	}
+	isp->isp_xffree = isp->isp_xflist;
 #ifdef	ISP_TARGET_MODE
-	len = sizeof (void **) * isp->isp_maxcmds;
-	isp->isp_tgtlist = (void **) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
+	len = sizeof (isp_hdl_t *) * isp->isp_maxcmds;
+	isp->isp_tgtlist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
 	if (isp->isp_tgtlist == NULL) {
 		free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
 		free(isp->isp_xflist, M_DEVBUF);
@@ -1534,6 +1538,10 @@ isp_pci_mbxdma(ispsoftc_t *isp)
 		isp_prt(isp, ISP_LOGERR, "cannot alloc tgtlist array");
 		return (1);
 	}
+	for (len = 0; len < isp->isp_maxcmds - 1; len++) {
+		isp->isp_tgtlist[len].cmd = &isp->isp_tgtlist[len+1];
+	}
+	isp->isp_tgtfree = isp->isp_tgtlist;
 #endif
 
 	/*

Modified: head/sys/dev/isp/isp_sbus.c
==============================================================================
--- head/sys/dev/isp/isp_sbus.c	Wed Feb  3 21:06:13 2010	(r203443)
+++ head/sys/dev/isp/isp_sbus.c	Wed Feb  3 21:09:32 2010	(r203444)
@@ -455,13 +455,17 @@ isp_sbus_mbxdma(ispsoftc_t *isp)
 		return (1);
 	}
 
-	len = sizeof (XS_T **) * isp->isp_maxcmds;
-	isp->isp_xflist = (XS_T **) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
+	len = sizeof (isp_hdl_t *) * isp->isp_maxcmds;
+	isp->isp_xflist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
 	if (isp->isp_xflist == NULL) {
 		isp_prt(isp, ISP_LOGERR, "cannot alloc xflist array");
 		ISP_LOCK(isp);
 		return (1);
 	}
+	for (len = 0; len < isp->isp_maxcmds - 1; len++) {
+		isp->isp_xflist[len].cmd = &isp->isp_xflist[len+1];
+	}
+	isp->isp_xffree = isp->isp_xflist;
 	len = sizeof (bus_dmamap_t) * isp->isp_maxcmds;
 
 	if (isp_dma_tag_create(BUS_DMA_ROOTARG(ISP_SBD(isp)), 1,

Modified: head/sys/dev/isp/ispmbox.h
==============================================================================
--- head/sys/dev/isp/ispmbox.h	Wed Feb  3 21:06:13 2010	(r203443)
+++ head/sys/dev/isp/ispmbox.h	Wed Feb  3 21:09:32 2010	(r203444)
@@ -288,11 +288,6 @@
 #define	QENTRY_LEN			64
 
 /*
- * Special Internal Handle for IOCBs
- */
-#define	ISP_SPCL_HANDLE			0xa5dead5a
-
-/*
  * Command Structure Definitions
  */
 

Modified: head/sys/dev/isp/ispvar.h
==============================================================================
--- head/sys/dev/isp/ispvar.h	Wed Feb  3 21:06:13 2010	(r203443)
+++ head/sys/dev/isp/ispvar.h	Wed Feb  3 21:09:32 2010	(r203444)
@@ -50,7 +50,7 @@
 #include "ispmbox.h"
 #endif
 
-#define	ISP_CORE_VERSION_MAJOR	6
+#define	ISP_CORE_VERSION_MAJOR	7
 #define	ISP_CORE_VERSION_MINOR	0
 
 /*
@@ -288,6 +288,53 @@ typedef struct {
 #define	DOMAIN_CONTROLLER_BASE	0xFFFC00
 #define	DOMAIN_CONTROLLER_END	0xFFFCFF
 
+/*
+ * Command Handles
+ *
+ * Most QLogic initiator or target have 32 bit handles associated with them.
+ * We want to have a quick way to index back and forth between a local SCSI
+ * command context and what the firmware is passing back to us. We also
+ * want to avoid working on stale information. This structure handles both
+ * at the expense of some local memory.
+ *
+ * The handle is architected thusly:
+ *
+ *	0 means "free handle"
+ *	bits  0..12 index commands
+ *	bits 13..15 bits index usage
+ *	bits 16..31 contain a rolling sequence
+ *
+ * 
+ */
+typedef struct {
+	void *		cmd;	/* associated command context */
+	uint32_t	handle;	/* handle associated with this command */
+} isp_hdl_t;
+#define	ISP_HANDLE_FREE		0x00000000
+#define	ISP_HANDLE_CMD_MASK	0x00001fff
+#define	ISP_HANDLE_USAGE_MASK	0x0000e000
+#define	ISP_HANDLE_USAGE_SHIFT	13
+#define	ISP_H2HT(hdl)	((hdl & ISP_HANDLE_USAGE_MASK) >> ISP_HANDLE_USAGE_SHIFT)
+#	define	ISP_HANDLE_NONE		0
+#	define	ISP_HANDLE_INITIATOR	1
+#	define	ISP_HANDLE_TARGET	2
+#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_INI_HANDLE(c, hdl)	\
+	(ISP_H2HT(hdl) == ISP_HANDLE_INITIATOR && (hdl & ISP_HANDLE_CMD_MASK) < (c)->isp_maxcmds && \
+	 ISP_H2SEQ(hdl) == ISP_H2SEQ((c)->isp_xflist[hdl & ISP_HANDLE_CMD_MASK].handle))
+#ifdef	ISP_TARGET_MODE
+#define	ISP_VALID_TGT_HANDLE(c, hdl)	\
+	(ISP_H2HT(hdl) == ISP_HANDLE_TARGET && (hdl & ISP_HANDLE_CMD_MASK) < (c)->isp_maxcmds && \
+	 ISP_H2SEQ(hdl) == ISP_H2SEQ((c)->isp_tgtlist[hdl & ISP_HANDLE_CMD_MASK].handle))
+#define	ISP_VALID_HANDLE(c, hdl)	\
+	(ISP_VALID_INI_HANDLE((c), hdl) || ISP_VALID_TGT_HANDLE((c), hdl))
+#else
+#define	ISP_VALID_HANDLE	ISP_VALID_INI_HANDLE
+#endif
+#define	ISP_BAD_HANDLE_INDEX	0xffffffff
+
 
 /*
  * FC Port Database entry.
@@ -562,11 +609,11 @@ struct ispsoftc {
 		isp_mboxbsy	:	1,	/* mailbox command active */
 		isp_state	:	3,
 		isp_nactive	:	16;	/* how many commands active */
+	volatile mbreg_t	isp_curmbx;	/* currently active mailbox command */
 	volatile uint32_t	isp_reqodx;	/* index of last ISP pickup */
 	volatile uint32_t	isp_reqidx;	/* index of next request */
 	volatile uint32_t	isp_residx;	/* index of next result */
 	volatile uint32_t	isp_resodx;	/* index of next result */
-	volatile uint32_t	isp_lasthdls;	/* last handle seed */
 	volatile uint32_t	isp_obits;	/* mailbox command output */
 	volatile uint32_t	isp_serno;	/* rolling serial number */
 	volatile uint16_t	isp_mboxtmp[MAILBOX_STORAGE];
@@ -575,18 +622,21 @@ struct ispsoftc {
 	volatile uint16_t	isp_mbxwrk1;
 	volatile uint16_t	isp_mbxwrk2;
 	volatile uint16_t	isp_mbxwrk8;
+	volatile uint16_t	isp_seqno;	/* running sequence number */
 	void *			isp_mbxworkp;
 
 	/*
 	 * Active commands are stored here, indexed by handle functions.
 	 */
-	XS_T **isp_xflist;
+	isp_hdl_t		*isp_xflist;
+	isp_hdl_t		*isp_xffree;
 
 #ifdef	ISP_TARGET_MODE
 	/*
 	 * Active target commands are stored here, indexed by handle functions.
 	 */
-	void **isp_tgtlist;
+	isp_hdl_t		*isp_tgtlist;
+	isp_hdl_t		*isp_tgtfree;
 #endif
 
 	/*


More information about the svn-src-all mailing list