From 2dbbccb697e6b707fc0b29a58cc4113cea5cdc34 Mon Sep 17 00:00:00 2001 From: mjacob Date: Mon, 1 Oct 2001 03:48:42 +0000 Subject: 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 --- sys/dev/isp/isp_freebsd.c | 88 +++++++++++++++++++++++++++++++---------------- sys/dev/isp/isp_freebsd.h | 9 +++++ 2 files changed, 68 insertions(+), 29 deletions(-) (limited to 'sys/dev/isp') 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 }; -- cgit v1.1