diff options
author | njl <njl@FreeBSD.org> | 2004-05-24 07:02:25 +0000 |
---|---|---|
committer | njl <njl@FreeBSD.org> | 2004-05-24 07:02:25 +0000 |
commit | 25ebfa5a90823db1401fda08ed867702c8ae818e (patch) | |
tree | 98d7ca75febb72f045bd84f9fa945072084c8cc1 /sys/dev/isp | |
parent | dbca8d97f6192e497120f0cf64e601271422a9ff (diff) | |
download | FreeBSD-src-25ebfa5a90823db1401fda08ed867702c8ae818e.zip FreeBSD-src-25ebfa5a90823db1401fda08ed867702c8ae818e.tar.gz |
Store the target handles in a separate list from normal commands. Add a
CTIO fast post routine to handle CTIO completions.
Submitted by: mjacob
Diffstat (limited to 'sys/dev/isp')
-rw-r--r-- | sys/dev/isp/isp.c | 8 | ||||
-rw-r--r-- | sys/dev/isp/isp_freebsd.c | 33 | ||||
-rw-r--r-- | sys/dev/isp/isp_inline.h | 65 | ||||
-rw-r--r-- | sys/dev/isp/isp_pci.c | 21 | ||||
-rw-r--r-- | sys/dev/isp/isp_target.c | 4 | ||||
-rw-r--r-- | sys/dev/isp/ispvar.h | 9 |
6 files changed, 125 insertions, 15 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index 060a106..a12c3d4 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -5843,7 +5843,7 @@ void isp_reinit(struct ispsoftc *isp) { XS_T *xs; - u_int16_t handle; + int i; if (IS_FC(isp)) { isp_mark_getpdb_all(isp); @@ -5863,11 +5863,13 @@ isp_reinit(struct ispsoftc *isp) } isp->isp_nactive = 0; - for (handle = 1; (int) handle <= isp->isp_maxcmds; handle++) { - xs = isp_find_xs(isp, handle); + for (i = 0; i < isp->isp_maxcmds; i++) { + u_int16_t handle; + xs = isp->isp_xflist[i]; if (xs == NULL) { continue; } + handle = isp_index_handle(i); isp_destroy_handle(isp, handle); if (XS_XFRLEN(xs)) { ISP_DMAFREE(isp, xs, handle); diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index 460d430..c7f908f 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -545,6 +545,7 @@ static cam_status isp_target_start_ctio(struct ispsoftc *, union ccb *); static int isp_handle_platform_atio(struct ispsoftc *, at_entry_t *); static int isp_handle_platform_atio2(struct ispsoftc *, at2_entry_t *); static int isp_handle_platform_ctio(struct ispsoftc *, void *); +static void isp_handle_platform_ctio_fastpost(struct ispsoftc *, u_int32_t); static int isp_handle_platform_notify_scsi(struct ispsoftc *, in_entry_t *); static int isp_handle_platform_notify_fc(struct ispsoftc *, in_fcentry_t *); @@ -1272,7 +1273,7 @@ isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb) hp = &cto->ct_syshandle; } - if (isp_save_xs(isp, (XS_T *)ccb, hp)) { + if (isp_save_xs_tgt(isp, ccb, hp)) { xpt_print_path(ccb->ccb_h.path); printf("No XFLIST pointers for isp_target_start_ctio\n"); return (CAM_RESRC_UNAVAIL); @@ -1297,11 +1298,11 @@ isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb) case CMD_EAGAIN: ccb->ccb_h.status = CAM_RESRC_UNAVAIL; - isp_destroy_handle(isp, save_handle); + isp_destroy_tgt_handle(isp, save_handle); return (CAM_RESRC_UNAVAIL); default: - isp_destroy_handle(isp, save_handle); + isp_destroy_tgt_handle(isp, save_handle); return (XS_ERR(ccb)); } } @@ -1637,9 +1638,9 @@ isp_handle_platform_ctio(struct ispsoftc *isp, void *arg) * CTIO and CTIO2 are close enough.... */ - ccb = (union ccb *) isp_find_xs(isp, ((ct_entry_t *)arg)->ct_syshandle); + ccb = isp_find_xs_tgt(isp, ((ct_entry_t *)arg)->ct_syshandle); KASSERT((ccb != NULL), ("null ccb in isp_handle_platform_ctio")); - isp_destroy_handle(isp, ((ct_entry_t *)arg)->ct_syshandle); + isp_destroy_tgt_handle(isp, ((ct_entry_t *)arg)->ct_syshandle); if (IS_FC(isp)) { ct2_entry_t *ct = arg; @@ -1734,6 +1735,19 @@ isp_handle_platform_ctio(struct ispsoftc *isp, void *arg) return (0); } +static void +isp_handle_platform_ctio_fastpost(struct ispsoftc *isp, u_int32_t token) +{ + union ccb *ccb; + ccb = isp_find_xs_tgt(isp, token & 0xffff); + KASSERT((ccb != NULL), + ("null ccb in isp_handle_platform_ctio_fastpost")); + isp_destroy_tgt_handle(isp, token & 0xffff); + isp_prt(isp, ISP_LOGTDEBUG1, "CTIOx[%x] fastpost complete", + token & 0xffff); + isp_complete_ctio(ccb); +} + static int isp_handle_platform_notify_scsi(struct ispsoftc *isp, in_entry_t *inp) { @@ -3019,6 +3033,15 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg) case ISPASYNC_TARGET_EVENT: { tmd_event_t *ep = arg; + if (ep->ev_event == ASYNC_CTIO_DONE) { + /* + * ACK the interrupt first + */ + ISP_WRITE(isp, BIU_SEMA, 0); + ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); + isp_handle_platform_ctio_fastpost(isp, ep->ev_bus); + break; + } isp_prt(isp, ISP_LOGALL, "bus %d event code 0x%x", ep->ev_bus, ep->ev_event); break; diff --git a/sys/dev/isp/isp_inline.h b/sys/dev/isp/isp_inline.h index 17ac1d0..6bc54fb 100644 --- a/sys/dev/isp/isp_inline.h +++ b/sys/dev/isp/isp_inline.h @@ -43,8 +43,8 @@ static INLINE int isp_save_xs(struct ispsoftc *, XS_T *, u_int16_t *); static INLINE XS_T *isp_find_xs(struct ispsoftc *, u_int16_t); static INLINE u_int16_t isp_find_handle(struct ispsoftc *, XS_T *); static INLINE int isp_handle_index(u_int16_t); +static INLINE u_int16_t isp_index_handle(int); static INLINE void isp_destroy_handle(struct ispsoftc *, u_int16_t); -static INLINE void isp_remove_handle(struct ispsoftc *, XS_T *); static INLINE int isp_save_xs(struct ispsoftc *isp, XS_T *xs, u_int16_t *handlep) @@ -100,19 +100,76 @@ isp_handle_index(u_int16_t handle) return (handle-1); } +static INLINE u_int16_t +isp_index_handle(int index) +{ + return (index+1); +} + static INLINE void isp_destroy_handle(struct ispsoftc *isp, u_int16_t handle) { if (handle > 0 && handle <= (u_int16_t) isp->isp_maxcmds) { - isp->isp_xflist[isp_handle_index(handle)] = NULL; + isp->isp_xflist[handle - 1] = NULL; + } +} + +#ifdef ISP_TARGET_MODE +static INLINE int isp_save_xs_tgt(struct ispsoftc *, void *, u_int16_t *); +static INLINE void *isp_find_xs_tgt(struct ispsoftc *, u_int16_t); +static INLINE void isp_destroy_tgt_handle(struct ispsoftc *, u_int16_t); + +static INLINE int +isp_save_xs_tgt(struct ispsoftc *isp, void *xs, u_int16_t *handlep) +{ + int i; + + for (i = 0; i < (int) isp->isp_maxcmds; i++) { + if (isp->isp_tgtlist[i] == NULL) { + break; + } + } + if (i == isp->isp_maxcmds) { + return (-1); + } + isp->isp_tgtlist[i] = xs; + *handlep = i+1; + return (0); +} + +static INLINE void * +isp_find_xs_tgt(struct ispsoftc *isp, u_int16_t handle) +{ + if (handle < 1 || handle > (u_int16_t) isp->isp_maxcmds) { + return (NULL); + } else { + return (isp->isp_tgtlist[handle - 1]); } } +static INLINE u_int16_t +isp_find_tgt_handle(struct ispsoftc *isp, void *xs) +{ + int i; + if (xs != NULL) { + for (i = 0; i < isp->isp_maxcmds; i++) { + if (isp->isp_tgtlist[i] == xs) { + return ((u_int16_t) i+1); + } + } + } + return (0); +} + static INLINE void -isp_remove_handle(struct ispsoftc *isp, XS_T *xs) +isp_destroy_tgt_handle(struct ispsoftc *isp, u_int16_t handle) { - isp_destroy_handle(isp, isp_find_handle(isp, xs)); + if (handle > 0 && handle <= (u_int16_t) isp->isp_maxcmds) { + isp->isp_tgtlist[handle - 1] = NULL; + } } +#endif + static INLINE int isp_getrqentry(struct ispsoftc *, u_int16_t *, u_int16_t *, void **); diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c index f23a048..f5b0128 100644 --- a/sys/dev/isp/isp_pci.c +++ b/sys/dev/isp/isp_pci.c @@ -1113,11 +1113,23 @@ isp_pci_mbxdma(struct ispsoftc *isp) ISP_LOCK(isp); return (1); } +#ifdef ISP_TARGET_MODE + len = sizeof (void **) * isp->isp_maxcmds; + isp->isp_tgtlist = (void **) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); + if (isp->isp_tgtlist == NULL) { + isp_prt(isp, ISP_LOGERR, "cannot alloc tgtlist array"); + ISP_LOCK(isp); + return (1); + } +#endif len = sizeof (bus_dmamap_t) * isp->isp_maxcmds; pcs->dmaps = (bus_dmamap_t *) malloc(len, M_DEVBUF, M_WAITOK); if (pcs->dmaps == NULL) { isp_prt(isp, ISP_LOGERR, "can't alloc dma map storage"); free(isp->isp_xflist, M_DEVBUF); +#ifdef ISP_TARGET_MODE + free(isp->isp_tgtlist, M_DEVBUF); +#endif ISP_LOCK(isp); return (1); } @@ -1139,6 +1151,9 @@ isp_pci_mbxdma(struct ispsoftc *isp) "cannot create a dma tag for control spaces"); free(pcs->dmaps, M_DEVBUF); free(isp->isp_xflist, M_DEVBUF); +#ifdef ISP_TARGET_MODE + free(isp->isp_tgtlist, M_DEVBUF); +#endif ISP_LOCK(isp); return (1); } @@ -1149,6 +1164,9 @@ isp_pci_mbxdma(struct ispsoftc *isp) "cannot allocate %d bytes of CCB memory", len); bus_dma_tag_destroy(isp->isp_cdmat); free(isp->isp_xflist, M_DEVBUF); +#ifdef ISP_TARGET_MODE + free(isp->isp_tgtlist, M_DEVBUF); +#endif free(pcs->dmaps, M_DEVBUF); ISP_LOCK(isp); return (1); @@ -1189,6 +1207,9 @@ bad: bus_dmamem_free(isp->isp_cdmat, base, isp->isp_cdmap); bus_dma_tag_destroy(isp->isp_cdmat); free(isp->isp_xflist, M_DEVBUF); +#ifdef ISP_TARGET_MODE + free(isp->isp_tgtlist, M_DEVBUF); +#endif free(pcs->dmaps, M_DEVBUF); ISP_LOCK(isp); isp->isp_rquest = NULL; diff --git a/sys/dev/isp/isp_target.c b/sys/dev/isp/isp_target.c index 03e71ee..d26d1e3 100644 --- a/sys/dev/isp/isp_target.c +++ b/sys/dev/isp/isp_target.c @@ -882,7 +882,7 @@ isp_handle_ctio(struct ispsoftc *isp, ct_entry_t *ct) char *fmsg = NULL; if (ct->ct_syshandle) { - xs = isp_find_xs(isp, ct->ct_syshandle); + xs = isp_find_xs_tgt(isp, ct->ct_syshandle); if (xs == NULL) pl = ISP_LOGALL; } else { @@ -1042,7 +1042,7 @@ isp_handle_ctio2(struct ispsoftc *isp, ct2_entry_t *ct) char *fmsg = NULL; if (ct->ct_syshandle) { - xs = isp_find_xs(isp, ct->ct_syshandle); + xs = isp_find_xs_tgt(isp, ct->ct_syshandle); if (xs == NULL) pl = ISP_LOGALL; } else { diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h index 6cd11a7..1e99dc9 100644 --- a/sys/dev/isp/ispvar.h +++ b/sys/dev/isp/ispvar.h @@ -54,7 +54,7 @@ #endif #define ISP_CORE_VERSION_MAJOR 2 -#define ISP_CORE_VERSION_MINOR 7 +#define ISP_CORE_VERSION_MINOR 8 /* * Vector for bus specific code to provide specific services. @@ -426,6 +426,13 @@ typedef struct ispsoftc { */ XS_T **isp_xflist; +#ifdef ISP_TARGET_MODE + /* + * Active target commands are stored here, indexed by handle function. + */ + void **isp_tgtlist; +#endif + /* * request/result queue pointers and DMA handles for them. */ |