summaryrefslogtreecommitdiffstats
path: root/sys/dev/isp
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2001-10-01 03:48:42 +0000
committermjacob <mjacob@FreeBSD.org>2001-10-01 03:48:42 +0000
commit2dbbccb697e6b707fc0b29a58cc4113cea5cdc34 (patch)
treeee3f35af7318ef72f236a9b8884c73c229b6945a /sys/dev/isp
parent9dcaf49f6a97d3369812404353462fce77a0a74b (diff)
downloadFreeBSD-src-2dbbccb697e6b707fc0b29a58cc4113cea5cdc34.zip
FreeBSD-src-2dbbccb697e6b707fc0b29a58cc4113cea5cdc34.tar.gz
Begin to implement target mode that for Fibre Channel has a private
per-command component that we *don't* try and pass thru CAM. CAM just is too risky and too much of a pain- structures get copied, but not all info of interest can be considered safely transported thru all consumers (including user space) from the incoming ATIO to the outgoing CTIO- it's just much safer to have a buddy structure, identified by the command's tag which *does* make it thru safely. Pay attention to link speed and report 200MB/s xfer speed for a 23XX card in 2GPs mode. MFC after: 1 week
Diffstat (limited to 'sys/dev/isp')
-rw-r--r--sys/dev/isp/isp_freebsd.c88
-rw-r--r--sys/dev/isp/isp_freebsd.h9
2 files changed, 68 insertions, 29 deletions
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index 32e0151..b4c606e 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -340,6 +340,7 @@ static __inline int isp_psema_sig_rqe(struct ispsoftc *, int);
static __inline int isp_cv_wait_timed_rqe(struct ispsoftc *, int, int);
static __inline void isp_cv_signal_rqe(struct ispsoftc *, int, int);
static __inline void isp_vsema_rqe(struct ispsoftc *, int);
+static __inline atio_private_data_t *isp_get_atpd(struct ispsoftc *, int);
static cam_status
create_lun_state(struct ispsoftc *, int, struct cam_path *, tstate_t **);
static void destroy_lun_state(struct ispsoftc *, tstate_t *);
@@ -461,6 +462,18 @@ isp_vsema_rqe(struct ispsoftc *isp, int bus)
isp->isp_osinfo.tmflags[bus] &= ~TM_BUSY;
}
+static __inline atio_private_data_t *
+isp_get_atpd(struct ispsoftc *isp, int tag)
+{
+ atio_private_data_t *atp;
+ for (atp = isp->isp_osinfo.atpdp;
+ atp < &isp->isp_osinfo.atpdp[ATPDPSIZE]; atp++) {
+ if (atp->tag == tag)
+ return (atp);
+ }
+ return (NULL);
+}
+
static cam_status
create_lun_state(struct ispsoftc *isp, int bus,
struct cam_path *path, tstate_t **rslt)
@@ -931,7 +944,7 @@ isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb)
*/
if (IS_FC(isp)) {
- int resid;
+ atio_private_data_t *atp;
ct2_entry_t *cto = qe;
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
@@ -940,16 +953,12 @@ isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb)
if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) {
cto->ct_lun = ccb->ccb_h.target_lun;
}
- /*
- * Start with a residual based on what the original datalength
- * was supposed to be. Basically, we ignore what CAM has set
- * for residuals. The data transfer routines will knock off
- * the residual for each byte actually moved- and also will
- * be responsible for setting the underrun flag.
- */
- /* HACK! HACK! */
- resid = ccb->ccb_h.spriv_field0;
- cto->ct_resid = 0;
+
+ atp = isp_get_atpd(isp, cso->tag_id);
+ if (atp == NULL) {
+ panic("cannot find private data adjunct for tag %x",
+ cso->tag_id);
+ }
cto->ct_rxid = cso->tag_id;
if (cso->dxfer_len == 0) {
@@ -957,7 +966,8 @@ isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb)
if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
cto->ct_flags |= CT2_SENDSTATUS;
cto->rsp.m1.ct_scsi_status = cso->scsi_status;
- cto->ct_resid = resid;
+ cto->ct_resid =
+ atp->orig_datalen - atp->bytes_xfered;
}
if ((ccb->ccb_h.flags & CAM_SEND_SENSE) != 0) {
int m = min(cso->sense_len, MAXRESPLEN);
@@ -975,7 +985,11 @@ isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb)
if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
cto->ct_flags |= CT2_SENDSTATUS;
cto->rsp.m0.ct_scsi_status = cso->scsi_status;
- cto->ct_resid = resid;
+ cto->ct_resid =
+ atp->orig_datalen -
+ (atp->bytes_xfered + cso->dxfer_len);
+ } else {
+ atp->last_xframt = cso->dxfer_len;
}
/*
* If we're sending data and status back together,
@@ -983,11 +997,12 @@ isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb)
*/
ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
}
+
if (cto->ct_flags & CT2_SENDSTATUS) {
isp_prt(isp, ISP_LOGTDEBUG0,
- "CTIO2[%x] SCSI STATUS 0x%x curxf %u finalresid %u",
- cto->ct_rxid, cso->scsi_status, cso->dxfer_len,
- resid);
+ "CTIO2[%x] STATUS %x origd %u curd %u resid %u",
+ cto->ct_rxid, cso->scsi_status, atp->orig_datalen,
+ cso->dxfer_len, cto->ct_resid);
cto->ct_flags |= CT2_CCINCR;
}
cto->ct_timeout = 10;
@@ -1017,16 +1032,13 @@ isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb)
cto->ct_flags |= CT_DATA_OUT;
}
if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
- cto->ct_flags |= CT_SENDSTATUS;
+ cto->ct_flags |= CT_SENDSTATUS|CT_CCINCR;
cto->ct_scsi_status = cso->scsi_status;
cto->ct_resid = cso->resid;
- }
- if (cto->ct_flags & CT_SENDSTATUS) {
isp_prt(isp, ISP_LOGTDEBUG0,
"CTIO[%x] SCSI STATUS 0x%x resid %d tag_id %x",
cto->ct_fwhandle, cso->scsi_status, cso->resid,
cso->tag_id);
- cto->ct_flags |= CT_CCINCR;
}
ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
cto->ct_timeout = 10;
@@ -1280,6 +1292,7 @@ isp_handle_platform_atio2(struct ispsoftc *isp, at2_entry_t *aep)
lun_id_t lun;
tstate_t *tptr;
struct ccb_accept_tio *atiop;
+ atio_private_data_t *atp;
/*
* The firmware status (except for the QLTM_SVALID bit)
@@ -1344,8 +1357,9 @@ isp_handle_platform_atio2(struct ispsoftc *isp, at2_entry_t *aep)
return (0);
}
+ atp = isp_get_atpd(isp, 0);
atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios);
- if (atiop == NULL) {
+ if (atiop == NULL || atp == NULL) {
/*
* Because we can't autofeed sense data back with
* a command for parallel SCSI, we can't give back
@@ -1401,10 +1415,10 @@ isp_handle_platform_atio2(struct ispsoftc *isp, at2_entry_t *aep)
atiop->ccb_h.status |= CAM_TAG_ACTION_VALID;
}
- /*
- * Preserve overall command datalength in private field.
- */
- atiop->ccb_h.spriv_field0 = aep->at_datalen;
+ atp->tag = atiop->tag_id;
+ atp->orig_datalen = aep->at_datalen;
+ atp->last_xframt = 0;
+ atp->bytes_xfered = 0;
xpt_done((union ccb*)atiop);
isp_prt(isp, ISP_LOGTDEBUG0,
@@ -1439,7 +1453,17 @@ isp_handle_platform_ctio(struct ispsoftc *isp, void *arg)
}
notify_cam = ct->ct_header.rqs_seqno & 0x1;
if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) {
+ atio_private_data_t *atp =
+ isp_get_atpd(isp, ct->ct_rxid);
+ if (atp == NULL) {
+ panic("cannot find adjunct after I/O");
+ }
resid = ct->ct_resid;
+ atp->bytes_xfered += (atp->last_xframt - resid);
+ atp->last_xframt = 0;
+ if (sentstatus) {
+ atp->tag = 0;
+ }
}
isp_prt(isp, ISP_LOGTDEBUG0,
"CTIO2[%x] sts 0x%x flg 0x%x sns %d resid %d %s",
@@ -1496,8 +1520,8 @@ isp_handle_platform_ctio(struct ispsoftc *isp, void *arg)
return (0);
}
- isp_prt(isp, ISP_LOGTDEBUG0, "%s CTIO[0x%x] done (resid %d)",
- (sentstatus)? " FINAL " : "MIDTERM ", tval, ccb->csio.resid);
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s CTIO[0x%x] done",
+ (sentstatus)? " FINAL " : "MIDTERM ", tval);
if (!ok) {
isp_target_putback_atio(ccb);
@@ -2118,7 +2142,10 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
cts->transport_version = 0;
fc->valid = CTS_FC_VALID_SPEED;
- fc->bitrate = 100000;
+ if (fcp->isp_gbspeed == 2)
+ fc->bitrate = 200000;
+ else
+ fc->bitrate = 100000;
if (tgt > 0 && tgt < MAX_FC_TARG) {
struct lportdb *lp = &fcp->portdb[tgt];
fc->wwnn = lp->node_wwn;
@@ -2301,7 +2328,10 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
* what media we're running on top of- but we'll
* look good if we always say 100MB/s.
*/
- cpi->base_transfer_speed = 100000;
+ if (FCPARAM(isp)->isp_gbspeed == 2)
+ cpi->base_transfer_speed = 200000;
+ else
+ cpi->base_transfer_speed = 100000;
cpi->hba_inquiry = PI_TAG_ABLE;
#ifdef CAM_NEW_TRAN_CODE
cpi->transport = XPORT_FC;
diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h
index 91b837d..67abd62 100644
--- a/sys/dev/isp/isp_freebsd.h
+++ b/sys/dev/isp/isp_freebsd.h
@@ -66,6 +66,14 @@
typedef void ispfwfunc __P((int, int, int, const u_int16_t **));
#ifdef ISP_TARGET_MODE
+#define ATPDPSIZE 256
+typedef struct {
+ u_int32_t orig_datalen;
+ u_int32_t bytes_xfered;
+ u_int32_t last_xframt;
+ u_int32_t tag;
+} atio_private_data_t;
+
typedef struct tstate {
struct tstate *next;
struct cam_path *owner;
@@ -112,6 +120,7 @@ struct isposinfo {
u_int16_t rollinfo;
tstate_t tsdflt[2]; /* two busses */
tstate_t *lun_hash[LUN_HASH_SIZE];
+ atio_private_data_t atpdp[ATPDPSIZE];
#endif
};
OpenPOWER on IntegriCloud