diff options
author | mjacob <mjacob@FreeBSD.org> | 2010-02-03 21:09:32 +0000 |
---|---|---|
committer | mjacob <mjacob@FreeBSD.org> | 2010-02-03 21:09:32 +0000 |
commit | df42a0ca6b960167d6735a4fb358950b6d690ce6 (patch) | |
tree | fdde0434a01b70cd56bc51a41aa3aaccfc6b07f8 /sys | |
parent | c499a83bba8f8470ae5c8ef7a572fe3892a87d8c (diff) | |
download | FreeBSD-src-df42a0ca6b960167d6735a4fb358950b6d690ce6.zip FreeBSD-src-df42a0ca6b960167d6735a4fb358950b6d690ce6.tar.gz |
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.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/isp/isp.c | 19 | ||||
-rw-r--r-- | sys/dev/isp/isp_freebsd.c | 34 | ||||
-rw-r--r-- | sys/dev/isp/isp_library.c | 147 | ||||
-rw-r--r-- | sys/dev/isp/isp_library.h | 8 | ||||
-rw-r--r-- | sys/dev/isp/isp_pci.c | 16 | ||||
-rw-r--r-- | sys/dev/isp/isp_sbus.c | 8 | ||||
-rw-r--r-- | sys/dev/isp/ispmbox.h | 5 | ||||
-rw-r--r-- | sys/dev/isp/ispvar.h | 58 |
8 files changed, 186 insertions, 109 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index 3f22d72..1945e4f 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -694,7 +694,7 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) 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_t mbox) * 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; } diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index 2861d7b..cd6ec09 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -1653,7 +1653,7 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb) 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); } diff --git a/sys/dev/isp/isp_library.c b/sys/dev/isp/isp_library.c index acc2492..877303e 100644 --- a/sys/dev/isp/isp_library.c +++ b/sys/dev/isp/isp_library.c @@ -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 chan, int new_role) 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 *fqe, void *segp, uint32_t nsegs, uint32_ } 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)]; } } diff --git a/sys/dev/isp/isp_library.h b/sys/dev/isp/isp_library.h index 9a9e397..b055dd8 100644 --- a/sys/dev/isp/isp_library.h +++ b/sys/dev/isp/isp_library.h @@ -43,10 +43,10 @@ int isp_send_cmd(ispsoftc_t *, void *, void *, uint32_t, uint32_t, isp_ddir_t); * * 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_hdr_t *, ct_hdr_t *); 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); diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c index 47dd350..4eb2e0c 100644 --- a/sys/dev/isp/isp_pci.c +++ b/sys/dev/isp/isp_pci.c @@ -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 /* diff --git a/sys/dev/isp/isp_sbus.c b/sys/dev/isp/isp_sbus.c index a50d0f2..e2dd78f 100644 --- a/sys/dev/isp/isp_sbus.c +++ b/sys/dev/isp/isp_sbus.c @@ -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, diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h index 2f9d152..eb3ab63 100644 --- a/sys/dev/isp/ispmbox.h +++ b/sys/dev/isp/ispmbox.h @@ -288,11 +288,6 @@ #define QENTRY_LEN 64 /* - * Special Internal Handle for IOCBs - */ -#define ISP_SPCL_HANDLE 0xa5dead5a - -/* * Command Structure Definitions */ diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h index e568a1c..5c8508c 100644 --- a/sys/dev/isp/ispvar.h +++ b/sys/dev/isp/ispvar.h @@ -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 /* |