summaryrefslogtreecommitdiffstats
path: root/sys/dev/isp
diff options
context:
space:
mode:
authornjl <njl@FreeBSD.org>2004-05-24 07:02:25 +0000
committernjl <njl@FreeBSD.org>2004-05-24 07:02:25 +0000
commit25ebfa5a90823db1401fda08ed867702c8ae818e (patch)
tree98d7ca75febb72f045bd84f9fa945072084c8cc1 /sys/dev/isp
parentdbca8d97f6192e497120f0cf64e601271422a9ff (diff)
downloadFreeBSD-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.c8
-rw-r--r--sys/dev/isp/isp_freebsd.c33
-rw-r--r--sys/dev/isp/isp_inline.h65
-rw-r--r--sys/dev/isp/isp_pci.c21
-rw-r--r--sys/dev/isp/isp_target.c4
-rw-r--r--sys/dev/isp/ispvar.h9
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.
*/
OpenPOWER on IntegriCloud