[Midnightbsd-cvs] src [7987] trunk/sys/dev/isp: make some changes with target mode
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Thu Sep 15 04:27:12 EDT 2016
Revision: 7987
http://svnweb.midnightbsd.org/src/?rev=7987
Author: laffer1
Date: 2016-09-15 04:27:12 -0400 (Thu, 15 Sep 2016)
Log Message:
-----------
make some changes with target mode
Modified Paths:
--------------
trunk/sys/dev/isp/isp_freebsd.c
trunk/sys/dev/isp/isp_freebsd.h
Modified: trunk/sys/dev/isp/isp_freebsd.c
===================================================================
--- trunk/sys/dev/isp/isp_freebsd.c 2016-09-15 08:26:26 UTC (rev 7986)
+++ trunk/sys/dev/isp/isp_freebsd.c 2016-09-15 08:27:12 UTC (rev 7987)
@@ -74,6 +74,7 @@
static void isp_target_thread_pi(void *);
static void isp_target_thread_fc(void *);
#endif
+static int isp_timer_count;
static void isp_timer(void *);
static struct cdevsw isp_cdevsw = {
@@ -225,7 +226,8 @@
}
callout_init_mtx(&isp->isp_osinfo.tmo, &isp->isp_osinfo.lock, 0);
- callout_reset(&isp->isp_osinfo.tmo, hz, isp_timer, isp);
+ isp_timer_count = hz >> 2;
+ callout_reset(&isp->isp_osinfo.tmo, isp_timer_count, isp_timer, isp);
isp->isp_osinfo.timer_active = 1;
isp->isp_osinfo.cdev = make_dev(&isp_cdevsw, du, UID_ROOT, GID_OPERATOR, 0600, "%s", nu);
@@ -777,6 +779,7 @@
isp_free_pcmd(ispsoftc_t *isp, union ccb *ccb)
{
if (ISP_PCMD(ccb)) {
+ memset(ISP_PCMD(ccb), 0, sizeof (struct isp_pcmd));
((struct isp_pcmd *)ISP_PCMD(ccb))->next = isp->isp_osinfo.pcmd_free;
isp->isp_osinfo.pcmd_free = ISP_PCMD(ccb);
ISP_PCMD(ccb) = NULL;
@@ -813,7 +816,7 @@
static timeout_t isp_refire_notify_ack;
static void isp_complete_ctio(union ccb *);
static void isp_target_putback_atio(union ccb *);
-enum Start_Ctio_How { FROM_CAM, FROM_SRR, FROM_CTIO_DONE };
+enum Start_Ctio_How { FROM_CAM, FROM_TIMER, FROM_SRR, FROM_CTIO_DONE };
static void isp_target_start_ctio(ispsoftc_t *, union ccb *, enum Start_Ctio_How);
static void isp_handle_platform_atio(ispsoftc_t *, at_entry_t *);
static void isp_handle_platform_atio2(ispsoftc_t *, at2_entry_t *);
@@ -975,7 +978,9 @@
isp_tmcmd_restart(ispsoftc_t *isp)
{
inot_private_data_t *ntp;
+ inot_private_data_t *restart_queue;
tstate_t *tptr;
+ union ccb *ccb;
struct tslist *lhp;
int bus, i;
@@ -983,8 +988,8 @@
for (i = 0; i < LUN_HASH_SIZE; i++) {
ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp);
SLIST_FOREACH(tptr, lhp, next) {
- inot_private_data_t *restart_queue = tptr->restart_queue;
- tptr->restart_queue = NULL;
+ if ((restart_queue = tptr->restart_queue) != NULL)
+ tptr->restart_queue = NULL;
while (restart_queue) {
ntp = restart_queue;
restart_queue = ntp->rd.nt.nt_hba;
@@ -1006,6 +1011,14 @@
break;
}
}
+ /*
+ * We only need to do this once per tptr
+ */
+ if (!TAILQ_EMPTY(&tptr->waitq)) {
+ ccb = (union ccb *)TAILQ_LAST(&tptr->waitq, isp_ccbq);
+ TAILQ_REMOVE(&tptr->waitq, &ccb->ccb_h, periph_links.tqe);
+ isp_target_start_ctio(isp, ccb, FROM_TIMER);
+ }
}
}
}
@@ -1052,8 +1065,8 @@
if (atp->tag == 0) {
continue;
}
- xpt_print(tptr->owner, "ATP: [0x%x] origdlen %u bytes_xfrd %u last_xfr %u lun %u nphdl 0x%04x s_id 0x%06x d_id 0x%06x oxid 0x%04x state %s\n",
- atp->tag, atp->orig_datalen, atp->bytes_xfered, atp->last_xframt, atp->lun, atp->nphdl, atp->sid, atp->portid, atp->oxid, states[atp->state & 0x7]);
+ xpt_print(tptr->owner, "ATP: [0x%x] origdlen %u bytes_xfrd %u lun %u nphdl 0x%04x s_id 0x%06x d_id 0x%06x oxid 0x%04x state %s\n",
+ atp->tag, atp->orig_datalen, atp->bytes_xfered, atp->lun, atp->nphdl, atp->sid, atp->portid, atp->oxid, states[atp->state & 0x7]);
}
}
@@ -1118,6 +1131,7 @@
}
SLIST_INIT(&tptr->atios);
SLIST_INIT(&tptr->inots);
+ TAILQ_INIT(&tptr->waitq);
for (i = 0; i < ATPDPSIZE-1; i++) {
tptr->atpool[i].next = &tptr->atpool[i+1];
tptr->ntpool[i].next = &tptr->ntpool[i+1];
@@ -1534,533 +1548,544 @@
static void
isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb, enum Start_Ctio_How how)
{
-
- void *qe;
- int fctape, sendstatus, resid, repval = ISP_LOGTDEBUG0;
+ int fctape, sendstatus, resid;
tstate_t *tptr;
fcparam *fcp;
atio_private_data_t *atp;
- struct ccb_scsiio *cso = &ccb->csio;
- uint32_t dmaresult, handle, xfrlen, sense_length;
+ struct ccb_scsiio *cso;
+ uint32_t dmaresult, handle, xfrlen, sense_length, tmp;
uint8_t local[QENTRY_LEN];
- /*
- * Do some sanity checks.
- */
- xfrlen = cso->dxfer_len;
- if (xfrlen == 0) {
- if ((ccb->ccb_h.flags & CAM_SEND_STATUS) == 0) {
- ISP_PATH_PRT(isp, ISP_LOGERR, ccb->ccb_h.path, "a data transfer length of zero but no status to send is wrong\n");
- ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
- return;
- }
- }
-
tptr = get_lun_statep(isp, XS_CHANNEL(ccb), XS_LUN(ccb));
if (tptr == NULL) {
tptr = get_lun_statep(isp, XS_CHANNEL(ccb), CAM_LUN_WILDCARD);
if (tptr == NULL) {
- ISP_PATH_PRT(isp, ISP_LOGERR, ccb->ccb_h.path, "%s: [0x%x] cannot find tstate pointer in %s\n", __func__, cso->tag_id);
+ isp_prt(isp, ISP_LOGERR, "%s: [0x%x] cannot find tstate pointer", __func__, ccb->csio.tag_id);
ccb->ccb_h.status = CAM_DEV_NOT_THERE;
xpt_done(ccb);
return;
}
}
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: ENTRY[0x%x] how %u xfrlen %u sendstatus %d sense_len %u", __func__, ccb->csio.tag_id, how, ccb->csio.dxfer_len,
+ (ccb->ccb_h.flags & CAM_SEND_STATUS) != 0, ((ccb->ccb_h.flags & CAM_SEND_SENSE)? ccb->csio.sense_len : 0));
- atp = isp_get_atpd(isp, tptr, cso->tag_id);
- if (atp == NULL) {
- ISP_PATH_PRT(isp, ISP_LOGERR, ccb->ccb_h.path, "%s: [0x%x] cannot find private data adjunct\n", __func__, cso->tag_id);
- isp_dump_atpd(isp, tptr);
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
- xpt_done(ccb);
- return;
+ switch (how) {
+ case FROM_TIMER:
+ case FROM_CAM:
+ /*
+ * Insert at the tail of the list, if any, waiting CTIO CCBs
+ */
+ TAILQ_INSERT_TAIL(&tptr->waitq, &ccb->ccb_h, periph_links.tqe);
+ break;
+ case FROM_SRR:
+ case FROM_CTIO_DONE:
+ TAILQ_INSERT_HEAD(&tptr->waitq, &ccb->ccb_h, periph_links.tqe);
+ break;
}
- /*
- * Is this command a dead duck?
- */
- if (atp->dead) {
- ISP_PATH_PRT(isp, ISP_LOGERR, ccb->ccb_h.path, "%s: [0x%x] not sending a CTIO for a dead command\n", __func__, cso->tag_id);
- ccb->ccb_h.status = CAM_REQ_ABORTED;
- xpt_done(ccb);
- return;
- }
+ while (TAILQ_FIRST(&tptr->waitq) != NULL) {
+ ccb = (union ccb *) TAILQ_FIRST(&tptr->waitq);
+ TAILQ_REMOVE(&tptr->waitq, &ccb->ccb_h, periph_links.tqe);
- /*
- * Check to make sure we're still in target mode.
- */
- fcp = FCPARAM(isp, XS_CHANNEL(ccb));
- if ((fcp->role & ISP_ROLE_TARGET) == 0) {
- ISP_PATH_PRT(isp, ISP_LOGERR, ccb->ccb_h.path, "%s: [0x%x] stopping sending a CTIO because we're no longer in target mode\n", __func__, cso->tag_id);
- ccb->ccb_h.status = CAM_PROVIDE_FAIL;
- xpt_done(ccb);
- return;
- }
+ cso = &ccb->csio;
+ xfrlen = cso->dxfer_len;
+ if (xfrlen == 0) {
+ if ((ccb->ccb_h.flags & CAM_SEND_STATUS) == 0) {
+ ISP_PATH_PRT(isp, ISP_LOGERR, ccb->ccb_h.path, "a data transfer length of zero but no status to send is wrong\n");
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ xpt_done(ccb);
+ continue;
+ }
+ }
- /*
- * We're only handling one outstanding CTIO at a time (which
- * could be split into two to split data and status)
- */
- if (atp->ctcnt) {
- ISP_PATH_PRT(isp, ISP_LOGINFO, ccb->ccb_h.path, "sending only one CTIO at a time\n");
- goto restart_delay;
- }
+ atp = isp_get_atpd(isp, tptr, cso->tag_id);
+ if (atp == NULL) {
+ isp_prt(isp, ISP_LOGERR, "%s: [0x%x] cannot find private data adjunct in %s", __func__, cso->tag_id, __func__);
+ isp_dump_atpd(isp, tptr);
+ ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+ xpt_done(ccb);
+ continue;
+ }
+ /*
+ * Is this command a dead duck?
+ */
+ if (atp->dead) {
+ isp_prt(isp, ISP_LOGERR, "%s: [0x%x] not sending a CTIO for a dead command", __func__, cso->tag_id);
+ ccb->ccb_h.status = CAM_REQ_ABORTED;
+ xpt_done(ccb);
+ continue;
+ }
- /*
- * Get some resources
- */
- if (isp_get_pcmd(isp, ccb)) {
- ISP_PATH_PRT(isp, ISP_LOGWARN, ccb->ccb_h.path, "out of PCMDs\n");
- goto restart_delay;
- }
- qe = isp_getrqentry(isp);
- if (qe == NULL) {
- ISP_PATH_PRT(isp, ISP_LOGWARN, ccb->ccb_h.path, rqo, __func__);
- goto restart_delay;
- }
- memset(local, 0, QENTRY_LEN);
+ /*
+ * Check to make sure we're still in target mode.
+ */
+ fcp = FCPARAM(isp, XS_CHANNEL(ccb));
+ if ((fcp->role & ISP_ROLE_TARGET) == 0) {
+ isp_prt(isp, ISP_LOGERR, "%s: [0x%x] stopping sending a CTIO because we're no longer in target mode", __func__, cso->tag_id);
+ ccb->ccb_h.status = CAM_PROVIDE_FAIL;
+ xpt_done(ccb);
+ continue;
+ }
- /*
- * Does the initiator expect FC-Tape style responses?
- * Can we provide them?
- */
- if ((atp->word3 & PRLI_WD3_RETRY) && fcp->fctape_enabled) {
- fctape = 1;
- } else {
- fctape = 0;
- }
+ /*
+ * We're only handling ATPD_CCB_OUTSTANDING outstanding CCB at a time (one of which
+ * could be split into two CTIOs to split data and status).
+ */
+ if (atp->ctcnt >= ATPD_CCB_OUTSTANDING) {
+ isp_prt(isp, ISP_LOGTINFO, "[0x%x] handling only %d CCBs at a time (flags for this ccb: 0x%x)", cso->tag_id, ATPD_CCB_OUTSTANDING, ccb->ccb_h.flags);
+ TAILQ_INSERT_HEAD(&tptr->waitq, &ccb->ccb_h, periph_links.tqe);
+ break;
+ }
- /*
- * If we already did the data xfer portion of a CTIO that sends data
- * and status, don't do it again and do the status portion now.
- */
- if (atp->sendst) {
- xfrlen = 0; /* we already did the data transfer */
- atp->sendst = 0;
- }
- if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
- sendstatus = 1;
- } else {
- sendstatus = 0;
- }
-
- if (ccb->ccb_h.flags & CAM_SEND_SENSE) {
/*
- * Sense length is not the entire sense data structure size. Periph
- * drivers don't seem to be setting sense_len to reflect the actual
- * size. We'll peek inside to get the right amount.
+ * Does the initiator expect FC-Tape style responses?
*/
- sense_length = cso->sense_len;
+ if ((atp->word3 & PRLI_WD3_RETRY) && fcp->fctape_enabled) {
+ fctape = 1;
+ } else {
+ fctape = 0;
+ }
/*
- * This 'cannot' happen
+ * If we already did the data xfer portion of a CTIO that sends data
+ * and status, don't do it again and do the status portion now.
*/
- if (sense_length > (XCMD_SIZE - MIN_FCP_RESPONSE_SIZE)) {
- sense_length = XCMD_SIZE - MIN_FCP_RESPONSE_SIZE;
+ if (atp->sendst) {
+ isp_prt(isp, ISP_LOGTINFO, "[0x%x] now sending synthesized status orig_dl=%u xfered=%u bit=%u",
+ cso->tag_id, atp->orig_datalen, atp->bytes_xfered, atp->bytes_in_transit);
+ xfrlen = 0; /* we already did the data transfer */
+ atp->sendst = 0;
}
- } else {
- sense_length = 0;
- }
+ if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
+ sendstatus = 1;
+ } else {
+ sendstatus = 0;
+ }
- if (how == FROM_SRR || atp->nsrr)
- repval = ISP_LOGINFO;
+ if (ccb->ccb_h.flags & CAM_SEND_SENSE) {
+ KASSERT((sendstatus != 0), ("how can you have CAM_SEND_SENSE w/o CAM_SEND_STATUS?"));
+ /*
+ * Sense length is not the entire sense data structure size. Periph
+ * drivers don't seem to be setting sense_len to reflect the actual
+ * size. We'll peek inside to get the right amount.
+ */
+ sense_length = cso->sense_len;
- if (IS_24XX(isp)) {
- ct7_entry_t *cto = (ct7_entry_t *) local;
+ /*
+ * This 'cannot' happen
+ */
+ if (sense_length > (XCMD_SIZE - MIN_FCP_RESPONSE_SIZE)) {
+ sense_length = XCMD_SIZE - MIN_FCP_RESPONSE_SIZE;
+ }
+ } else {
+ sense_length = 0;
+ }
- cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
- cto->ct_header.rqs_entry_count = 1;
- cto->ct_header.rqs_seqno = 1;
- cto->ct_nphdl = atp->nphdl;
- cto->ct_rxid = atp->tag;
- cto->ct_iid_lo = atp->portid;
- cto->ct_iid_hi = atp->portid >> 16;
- cto->ct_oxid = atp->oxid;
- cto->ct_vpidx = ISP_GET_VPIDX(isp, XS_CHANNEL(ccb));
- cto->ct_timeout = 120;
- cto->ct_flags = atp->tattr << CT7_TASK_ATTR_SHIFT;
+ memset(local, 0, QENTRY_LEN);
/*
- * Mode 1, status, no data. Only possible when we are sending status, have
- * no data to transfer, and any sense length can fit in the ct7_entry.
- *
- * Mode 2, status, no data. We have to use this in the case sense data
- * won't fit into a ct7_entry_t.
- *
+ * Check for overflow
*/
- if (sendstatus && xfrlen == 0) {
- cto->ct_flags |= CT7_SENDSTATUS | CT7_NO_DATA;
- resid = atp->orig_datalen - atp->bytes_xfered;
- if (sense_length <= MAXRESPLEN_24XX) {
- if (resid < 0) {
- cto->ct_resid = -resid;
- } else if (resid > 0) {
- cto->ct_resid = resid;
- }
- cto->ct_flags |= CT7_FLAG_MODE1;
- cto->ct_scsi_status = cso->scsi_status;
- if (resid < 0) {
- cto->ct_scsi_status |= (FCP_RESID_OVERFLOW << 8);
- } else if (resid > 0) {
- cto->ct_scsi_status |= (FCP_RESID_UNDERFLOW << 8);
- }
- if (fctape) {
- cto->ct_flags |= CT7_CONFIRM|CT7_EXPLCT_CONF;
- }
- if (sense_length) {
- cto->ct_scsi_status |= (FCP_SNSLEN_VALID << 8);
- cto->rsp.m1.ct_resplen = cto->ct_senselen = sense_length;
- memcpy(cto->rsp.m1.ct_resp, &cso->sense_data, sense_length);
- }
- } else {
- bus_addr_t addr;
- char buf[XCMD_SIZE];
- fcp_rsp_iu_t *rp;
+ tmp = atp->bytes_xfered + atp->bytes_in_transit + xfrlen;
+ if (tmp > atp->orig_datalen) {
+ isp_prt(isp, ISP_LOGERR, "%s: [0x%x] data overflow by %u bytes", __func__, cso->tag_id, tmp - atp->orig_datalen);
+ ccb->ccb_h.status = CAM_DATA_RUN_ERR;
+ xpt_done(ccb);
+ continue;
+ }
- if (atp->ests == NULL) {
- atp->ests = isp_get_ecmd(isp);
+ if (IS_24XX(isp)) {
+ ct7_entry_t *cto = (ct7_entry_t *) local;
+
+ cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
+ cto->ct_header.rqs_entry_count = 1;
+ cto->ct_header.rqs_seqno |= ATPD_SEQ_NOTIFY_CAM;
+ ATPD_SET_SEQNO(cto, atp);
+ cto->ct_nphdl = atp->nphdl;
+ cto->ct_rxid = atp->tag;
+ cto->ct_iid_lo = atp->portid;
+ cto->ct_iid_hi = atp->portid >> 16;
+ cto->ct_oxid = atp->oxid;
+ cto->ct_vpidx = ISP_GET_VPIDX(isp, XS_CHANNEL(ccb));
+ cto->ct_timeout = 120;
+ cto->ct_flags = atp->tattr << CT7_TASK_ATTR_SHIFT;
+
+ /*
+ * Mode 1, status, no data. Only possible when we are sending status, have
+ * no data to transfer, and any sense length can fit in the ct7_entry.
+ *
+ * Mode 2, status, no data. We have to use this in the case sense data
+ * won't fit into a ct7_entry_t.
+ *
+ */
+ if (sendstatus && xfrlen == 0) {
+ cto->ct_flags |= CT7_SENDSTATUS | CT7_NO_DATA;
+ resid = atp->orig_datalen - atp->bytes_xfered - atp->bytes_in_transit;
+ if (sense_length <= MAXRESPLEN_24XX) {
+ if (resid < 0) {
+ cto->ct_resid = -resid;
+ } else if (resid > 0) {
+ cto->ct_resid = resid;
+ }
+ cto->ct_flags |= CT7_FLAG_MODE1;
+ cto->ct_scsi_status = cso->scsi_status;
+ if (resid < 0) {
+ cto->ct_scsi_status |= (FCP_RESID_OVERFLOW << 8);
+ } else if (resid > 0) {
+ cto->ct_scsi_status |= (FCP_RESID_UNDERFLOW << 8);
+ }
+ if (fctape) {
+ cto->ct_flags |= CT7_CONFIRM|CT7_EXPLCT_CONF;
+ }
+ if (sense_length) {
+ cto->ct_scsi_status |= (FCP_SNSLEN_VALID << 8);
+ cto->rsp.m1.ct_resplen = cto->ct_senselen = sense_length;
+ memcpy(cto->rsp.m1.ct_resp, &cso->sense_data, sense_length);
+ }
+ } else {
+ bus_addr_t addr;
+ char buf[XCMD_SIZE];
+ fcp_rsp_iu_t *rp;
+
if (atp->ests == NULL) {
- goto restart_delay;
+ atp->ests = isp_get_ecmd(isp);
+ if (atp->ests == NULL) {
+ TAILQ_INSERT_HEAD(&tptr->waitq, &ccb->ccb_h, periph_links.tqe);
+ break;
+ }
}
+ memset(buf, 0, sizeof (buf));
+ rp = (fcp_rsp_iu_t *)buf;
+ if (fctape) {
+ cto->ct_flags |= CT7_CONFIRM|CT7_EXPLCT_CONF;
+ rp->fcp_rsp_bits |= FCP_CONF_REQ;
+ }
+ cto->ct_flags |= CT7_FLAG_MODE2;
+ rp->fcp_rsp_scsi_status = cso->scsi_status;
+ if (resid < 0) {
+ rp->fcp_rsp_resid = -resid;
+ rp->fcp_rsp_bits |= FCP_RESID_OVERFLOW;
+ } else if (resid > 0) {
+ rp->fcp_rsp_resid = resid;
+ rp->fcp_rsp_bits |= FCP_RESID_UNDERFLOW;
+ }
+ if (sense_length) {
+ rp->fcp_rsp_snslen = sense_length;
+ cto->ct_senselen = sense_length;
+ rp->fcp_rsp_bits |= FCP_SNSLEN_VALID;
+ isp_put_fcp_rsp_iu(isp, rp, atp->ests);
+ memcpy(((fcp_rsp_iu_t *)atp->ests)->fcp_rsp_extra, &cso->sense_data, sense_length);
+ } else {
+ isp_put_fcp_rsp_iu(isp, rp, atp->ests);
+ }
+ if (isp->isp_dblev & ISP_LOGTDEBUG1) {
+ isp_print_bytes(isp, "FCP Response Frame After Swizzling", MIN_FCP_RESPONSE_SIZE + sense_length, atp->ests);
+ }
+ addr = isp->isp_osinfo.ecmd_dma;
+ addr += ((((isp_ecmd_t *)atp->ests) - isp->isp_osinfo.ecmd_base) * XCMD_SIZE);
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: ests base %p vaddr %p ecmd_dma %jx addr %jx len %u", __func__, isp->isp_osinfo.ecmd_base, atp->ests,
+ (uintmax_t) isp->isp_osinfo.ecmd_dma, (uintmax_t)addr, MIN_FCP_RESPONSE_SIZE + sense_length);
+ cto->rsp.m2.ct_datalen = MIN_FCP_RESPONSE_SIZE + sense_length;
+ cto->rsp.m2.ct_fcp_rsp_iudata.ds_base = DMA_LO32(addr);
+ cto->rsp.m2.ct_fcp_rsp_iudata.ds_basehi = DMA_HI32(addr);
+ cto->rsp.m2.ct_fcp_rsp_iudata.ds_count = MIN_FCP_RESPONSE_SIZE + sense_length;
}
- memset(buf, 0, sizeof (buf));
- rp = (fcp_rsp_iu_t *)buf;
- if (fctape) {
- cto->ct_flags |= CT7_CONFIRM|CT7_EXPLCT_CONF;
- rp->fcp_rsp_bits |= FCP_CONF_REQ;
- }
- cto->ct_flags |= CT7_FLAG_MODE2;
- rp->fcp_rsp_scsi_status = cso->scsi_status;
- if (resid < 0) {
- rp->fcp_rsp_resid = -resid;
- rp->fcp_rsp_bits |= FCP_RESID_OVERFLOW;
- } else if (resid > 0) {
- rp->fcp_rsp_resid = resid;
- rp->fcp_rsp_bits |= FCP_RESID_UNDERFLOW;
- }
if (sense_length) {
- rp->fcp_rsp_snslen = sense_length;
- cto->ct_senselen = sense_length;
- rp->fcp_rsp_bits |= FCP_SNSLEN_VALID;
- isp_put_fcp_rsp_iu(isp, rp, atp->ests);
- memcpy(((fcp_rsp_iu_t *)atp->ests)->fcp_rsp_extra, &cso->sense_data, sense_length);
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO7[0x%x] seq %u nc %d CDB0=%x sstatus=0x%x flags=0x%x resid=%d slen %u sense: %x %x/%x/%x", __func__,
+ cto->ct_rxid, ATPD_GET_SEQNO(cto), ATPD_GET_NCAM(cto), atp->cdb0, cto->ct_scsi_status, cto->ct_flags, cto->ct_resid, sense_length,
+ cso->sense_data.error_code, cso->sense_data.sense_buf[1], cso->sense_data.sense_buf[11], cso->sense_data.sense_buf[12]);
} else {
- isp_put_fcp_rsp_iu(isp, rp, atp->ests);
+ isp_prt(isp, ISP_LOGDEBUG0, "%s: CTIO7[0x%x] seq %u nc %d CDB0=%x sstatus=0x%x flags=0x%x resid=%d", __func__,
+ cto->ct_rxid, ATPD_GET_SEQNO(cto), ATPD_GET_NCAM(cto), atp->cdb0, cto->ct_scsi_status, cto->ct_flags, cto->ct_resid);
}
- if (isp->isp_dblev & ISP_LOGTDEBUG1) {
- isp_print_bytes(isp, "FCP Response Frame After Swizzling", MIN_FCP_RESPONSE_SIZE + sense_length, atp->ests);
- }
- addr = isp->isp_osinfo.ecmd_dma;
- addr += ((((isp_ecmd_t *)atp->ests) - isp->isp_osinfo.ecmd_base) * XCMD_SIZE);
- isp_prt(isp, repval, "%s: ests base %p vaddr %p ecmd_dma %jx addr %jx len %u", __func__, isp->isp_osinfo.ecmd_base, atp->ests,
- (uintmax_t) isp->isp_osinfo.ecmd_dma, (uintmax_t)addr, MIN_FCP_RESPONSE_SIZE + sense_length);
- cto->rsp.m2.ct_datalen = MIN_FCP_RESPONSE_SIZE + sense_length;
- cto->rsp.m2.ct_fcp_rsp_iudata.ds_base = DMA_LO32(addr);
- cto->rsp.m2.ct_fcp_rsp_iudata.ds_basehi = DMA_HI32(addr);
- cto->rsp.m2.ct_fcp_rsp_iudata.ds_count = MIN_FCP_RESPONSE_SIZE + sense_length;
+ atp->state = ATPD_STATE_LAST_CTIO;
}
- if (sense_length) {
- isp_prt(isp, repval, "%s: CTIO7[0x%x] CDB0=%x sstatus=0x%x flags=0x%x resid=%d slen %u sense: %x %x/%x/%x", __func__,
- cto->ct_rxid, atp->cdb0, cto->ct_scsi_status, cto->ct_flags, cto->ct_resid, sense_length, cso->sense_data.error_code,
- cso->sense_data.sense_buf[1], cso->sense_data.sense_buf[11], cso->sense_data.sense_buf[12]);
- } else {
- isp_prt(isp, repval, "%s: CTIO7[0x%x] CDB0=%x sstatus=0x%x flags=0x%x resid=%d", __func__,
- cto->ct_rxid, atp->cdb0, cto->ct_scsi_status, cto->ct_flags, cto->ct_resid);
- }
- atp->state = ATPD_STATE_LAST_CTIO;
- }
- /*
- * Mode 0 data transfers, *possibly* with status.
- */
- if (xfrlen != 0) {
- cto->ct_flags |= CT7_FLAG_MODE0;
- if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- cto->ct_flags |= CT7_DATA_IN;
- } else {
- cto->ct_flags |= CT7_DATA_OUT;
- }
-
/*
- * Don't overrun the limits placed on us, but record it as
- * if we had so that we can set an overflow bit later.
+ * Mode 0 data transfers, *possibly* with status.
*/
- atp->last_xframt = xfrlen;
- if (atp->bytes_xfered >= atp->orig_datalen) {
- resid = atp->orig_datalen - (atp->bytes_xfered + xfrlen);
- } else if (atp->bytes_xfered + xfrlen > atp->orig_datalen) {
- resid = atp->orig_datalen - (atp->bytes_xfered + xfrlen);
- xfrlen = atp->orig_datalen - atp->bytes_xfered;
- } else {
- resid = atp->orig_datalen - xfrlen;
- }
- cto->rsp.m0.reloff = atp->bytes_xfered;
- cto->rsp.m0.ct_xfrlen = xfrlen;
+ if (xfrlen != 0) {
+ cto->ct_flags |= CT7_FLAG_MODE0;
+ if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
+ cto->ct_flags |= CT7_DATA_IN;
+ } else {
+ cto->ct_flags |= CT7_DATA_OUT;
+ }
+ cto->rsp.m0.reloff = atp->bytes_xfered + atp->bytes_in_transit;
+ cto->rsp.m0.ct_xfrlen = xfrlen;
+
#ifdef DEBUG
- if (ISP_FC_PC(isp, XS_CHANNEL(ccb))->inject_lost_data_frame && xfrlen > ISP_FC_PC(isp, XS_CHANNEL(ccb))->inject_lost_data_frame) {
- isp_prt(isp, ISP_LOGWARN, "%s: truncating data frame with xfrlen %d to %d", __func__, xfrlen, xfrlen - (xfrlen >> 2));
- ISP_FC_PC(isp, XS_CHANNEL(ccb))->inject_lost_data_frame = 0;
- cto->rsp.m0.ct_xfrlen -= xfrlen >> 2;
- }
+ if (ISP_FC_PC(isp, XS_CHANNEL(ccb))->inject_lost_data_frame && xfrlen > ISP_FC_PC(isp, XS_CHANNEL(ccb))->inject_lost_data_frame) {
+ isp_prt(isp, ISP_LOGWARN, "%s: truncating data frame with xfrlen %d to %d", __func__, xfrlen, xfrlen - (xfrlen >> 2));
+ ISP_FC_PC(isp, XS_CHANNEL(ccb))->inject_lost_data_frame = 0;
+ cto->rsp.m0.ct_xfrlen -= xfrlen >> 2;
+ }
#endif
- if (sendstatus) {
- if (cso->scsi_status == SCSI_STATUS_OK && resid == 0 && fctape == 0) {
- cto->ct_flags |= CT7_SENDSTATUS;
- atp->state = ATPD_STATE_LAST_CTIO;
+ if (sendstatus) {
+ resid = atp->orig_datalen - atp->bytes_xfered - xfrlen;
+ if (cso->scsi_status == SCSI_STATUS_OK && resid == 0 /* && fctape == 0 */) {
+ cto->ct_flags |= CT7_SENDSTATUS;
+ atp->state = ATPD_STATE_LAST_CTIO;
+ if (fctape) {
+ cto->ct_flags |= CT7_CONFIRM|CT7_EXPLCT_CONF;
+ }
+ } else {
+ atp->sendst = 1; /* send status later */
+ cto->ct_header.rqs_seqno &= ~ATPD_SEQ_NOTIFY_CAM;
+ atp->state = ATPD_STATE_CTIO;
+ }
} else {
- atp->sendst = 1; /* send status later */
- cto->ct_header.rqs_seqno = 0;
atp->state = ATPD_STATE_CTIO;
}
- } else {
- atp->state = ATPD_STATE_CTIO;
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO7[0x%x] seq %u nc %d CDB0=%x sstatus=0x%x flags=0x%x xfrlen=%u off=%u", __func__,
+ cto->ct_rxid, ATPD_GET_SEQNO(cto), ATPD_GET_NCAM(cto), atp->cdb0, cto->ct_scsi_status, cto->ct_flags, xfrlen, atp->bytes_xfered);
}
- isp_prt(isp, repval, "%s: CTIO7[0x%x] CDB0=%x sstatus=0x%x flags=0x%x xfrlen=%u off=%u", __func__,
- cto->ct_rxid, atp->cdb0, cto->ct_scsi_status, cto->ct_flags, xfrlen, atp->bytes_xfered);
- }
- } else if (IS_FC(isp)) {
- ct2_entry_t *cto = (ct2_entry_t *) local;
+ } else if (IS_FC(isp)) {
+ ct2_entry_t *cto = (ct2_entry_t *) local;
- if (isp->isp_osinfo.sixtyfourbit)
- cto->ct_header.rqs_entry_type = RQSTYPE_CTIO3;
- else
- cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
- cto->ct_header.rqs_entry_count = 1;
- cto->ct_header.rqs_seqno = 1;
- if (ISP_CAP_2KLOGIN(isp) == 0) {
- ((ct2e_entry_t *)cto)->ct_iid = cso->init_id;
- } else {
- cto->ct_iid = cso->init_id;
- if (ISP_CAP_SCCFW(isp) == 0) {
- cto->ct_lun = ccb->ccb_h.target_lun;
+ if (isp->isp_osinfo.sixtyfourbit)
+ cto->ct_header.rqs_entry_type = RQSTYPE_CTIO3;
+ else
+ cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
+ cto->ct_header.rqs_entry_count = 1;
+ cto->ct_header.rqs_seqno |= ATPD_SEQ_NOTIFY_CAM;
+ ATPD_SET_SEQNO(cto, atp);
+ if (ISP_CAP_2KLOGIN(isp) == 0) {
+ ((ct2e_entry_t *)cto)->ct_iid = cso->init_id;
+ } else {
+ cto->ct_iid = cso->init_id;
+ if (ISP_CAP_SCCFW(isp) == 0) {
+ cto->ct_lun = ccb->ccb_h.target_lun;
+ }
}
- }
- cto->ct_timeout = 10;
- cto->ct_rxid = cso->tag_id;
+ cto->ct_timeout = 10;
+ cto->ct_rxid = cso->tag_id;
- /*
- * Mode 1, status, no data. Only possible when we are sending status, have
- * no data to transfer, and the sense length can fit in the ct7_entry.
- *
- * Mode 2, status, no data. We have to use this in the case the the response
- * length won't fit into a ct2_entry_t.
- *
- * We'll fill out this structure with information as if this were a
- * Mode 1. The hardware layer will create the Mode 2 FCP RSP IU as
- * needed based upon this.
- */
- if (sendstatus && xfrlen == 0) {
- cto->ct_flags |= CT2_SENDSTATUS | CT2_NO_DATA;
- resid = atp->orig_datalen - atp->bytes_xfered;
- if (sense_length <= MAXRESPLEN) {
- if (resid < 0) {
- cto->ct_resid = -resid;
- } else if (resid > 0) {
- cto->ct_resid = resid;
- }
- cto->ct_flags |= CT2_FLAG_MODE1;
- cto->rsp.m1.ct_scsi_status = cso->scsi_status;
- if (resid < 0) {
- cto->rsp.m1.ct_scsi_status |= CT2_DATA_OVER;
- } else if (resid > 0) {
- cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER;
- }
- if (fctape) {
- cto->ct_flags |= CT2_CONFIRM;
- }
- if (sense_length) {
- cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID;
- cto->rsp.m1.ct_resplen = cto->rsp.m1.ct_senselen = sense_length;
- memcpy(cto->rsp.m1.ct_resp, &cso->sense_data, sense_length);
- }
- } else {
- bus_addr_t addr;
- char buf[XCMD_SIZE];
- fcp_rsp_iu_t *rp;
+ /*
+ * Mode 1, status, no data. Only possible when we are sending status, have
+ * no data to transfer, and the sense length can fit in the ct7_entry.
+ *
+ * Mode 2, status, no data. We have to use this in the case the the response
+ * length won't fit into a ct2_entry_t.
+ *
+ * We'll fill out this structure with information as if this were a
+ * Mode 1. The hardware layer will create the Mode 2 FCP RSP IU as
+ * needed based upon this.
+ */
+ if (sendstatus && xfrlen == 0) {
+ cto->ct_flags |= CT2_SENDSTATUS | CT2_NO_DATA;
+ resid = atp->orig_datalen - atp->bytes_xfered - atp->bytes_in_transit;
+ if (sense_length <= MAXRESPLEN) {
+ if (resid < 0) {
+ cto->ct_resid = -resid;
+ } else if (resid > 0) {
+ cto->ct_resid = resid;
+ }
+ cto->ct_flags |= CT2_FLAG_MODE1;
+ cto->rsp.m1.ct_scsi_status = cso->scsi_status;
+ if (resid < 0) {
+ cto->rsp.m1.ct_scsi_status |= CT2_DATA_OVER;
+ } else if (resid > 0) {
+ cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER;
+ }
+ if (fctape) {
+ cto->ct_flags |= CT2_CONFIRM;
+ }
+ if (sense_length) {
+ cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID;
+ cto->rsp.m1.ct_resplen = cto->rsp.m1.ct_senselen = sense_length;
+ memcpy(cto->rsp.m1.ct_resp, &cso->sense_data, sense_length);
+ }
+ } else {
+ bus_addr_t addr;
+ char buf[XCMD_SIZE];
+ fcp_rsp_iu_t *rp;
- if (atp->ests == NULL) {
- atp->ests = isp_get_ecmd(isp);
if (atp->ests == NULL) {
- goto restart_delay;
+ atp->ests = isp_get_ecmd(isp);
+ if (atp->ests == NULL) {
+ TAILQ_INSERT_HEAD(&tptr->waitq, &ccb->ccb_h, periph_links.tqe);
+ break;
+ }
}
+ memset(buf, 0, sizeof (buf));
+ rp = (fcp_rsp_iu_t *)buf;
+ if (fctape) {
+ cto->ct_flags |= CT2_CONFIRM;
+ rp->fcp_rsp_bits |= FCP_CONF_REQ;
+ }
+ cto->ct_flags |= CT2_FLAG_MODE2;
+ rp->fcp_rsp_scsi_status = cso->scsi_status;
+ if (resid < 0) {
+ rp->fcp_rsp_resid = -resid;
+ rp->fcp_rsp_bits |= FCP_RESID_OVERFLOW;
+ } else if (resid > 0) {
+ rp->fcp_rsp_resid = resid;
+ rp->fcp_rsp_bits |= FCP_RESID_UNDERFLOW;
+ }
+ if (sense_length) {
+ rp->fcp_rsp_snslen = sense_length;
+ rp->fcp_rsp_bits |= FCP_SNSLEN_VALID;
+ isp_put_fcp_rsp_iu(isp, rp, atp->ests);
+ memcpy(((fcp_rsp_iu_t *)atp->ests)->fcp_rsp_extra, &cso->sense_data, sense_length);
+ } else {
+ isp_put_fcp_rsp_iu(isp, rp, atp->ests);
+ }
+ if (isp->isp_dblev & ISP_LOGTDEBUG1) {
+ isp_print_bytes(isp, "FCP Response Frame After Swizzling", MIN_FCP_RESPONSE_SIZE + sense_length, atp->ests);
+ }
+ addr = isp->isp_osinfo.ecmd_dma;
+ addr += ((((isp_ecmd_t *)atp->ests) - isp->isp_osinfo.ecmd_base) * XCMD_SIZE);
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: ests base %p vaddr %p ecmd_dma %jx addr %jx len %u", __func__, isp->isp_osinfo.ecmd_base, atp->ests,
+ (uintmax_t) isp->isp_osinfo.ecmd_dma, (uintmax_t)addr, MIN_FCP_RESPONSE_SIZE + sense_length);
+ cto->rsp.m2.ct_datalen = MIN_FCP_RESPONSE_SIZE + sense_length;
+ if (isp->isp_osinfo.sixtyfourbit) {
+ cto->rsp.m2.u.ct_fcp_rsp_iudata_64.ds_base = DMA_LO32(addr);
+ cto->rsp.m2.u.ct_fcp_rsp_iudata_64.ds_basehi = DMA_HI32(addr);
+ cto->rsp.m2.u.ct_fcp_rsp_iudata_64.ds_count = MIN_FCP_RESPONSE_SIZE + sense_length;
+ } else {
+ cto->rsp.m2.u.ct_fcp_rsp_iudata_32.ds_base = DMA_LO32(addr);
+ cto->rsp.m2.u.ct_fcp_rsp_iudata_32.ds_count = MIN_FCP_RESPONSE_SIZE + sense_length;
+ }
}
- memset(buf, 0, sizeof (buf));
- rp = (fcp_rsp_iu_t *)buf;
- if (fctape) {
- cto->ct_flags |= CT2_CONFIRM;
- rp->fcp_rsp_bits |= FCP_CONF_REQ;
- }
- cto->ct_flags |= CT2_FLAG_MODE2;
- rp->fcp_rsp_scsi_status = cso->scsi_status;
- if (resid < 0) {
- rp->fcp_rsp_resid = -resid;
- rp->fcp_rsp_bits |= FCP_RESID_OVERFLOW;
- } else if (resid > 0) {
- rp->fcp_rsp_resid = resid;
- rp->fcp_rsp_bits |= FCP_RESID_UNDERFLOW;
- }
if (sense_length) {
- rp->fcp_rsp_snslen = sense_length;
- rp->fcp_rsp_bits |= FCP_SNSLEN_VALID;
- isp_put_fcp_rsp_iu(isp, rp, atp->ests);
- memcpy(((fcp_rsp_iu_t *)atp->ests)->fcp_rsp_extra, &cso->sense_data, sense_length);
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO2[0x%x] seq %u nc %d CDB0=%x sstatus=0x%x flags=0x%x resid=%d sense: %x %x/%x/%x", __func__,
+ cto->ct_rxid, ATPD_GET_SEQNO(cto), ATPD_GET_NCAM(cto), atp->cdb0, cso->scsi_status, cto->ct_flags, cto->ct_resid,
+ cso->sense_data.error_code, cso->sense_data.sense_buf[1], cso->sense_data.sense_buf[11], cso->sense_data.sense_buf[12]);
} else {
- isp_put_fcp_rsp_iu(isp, rp, atp->ests);
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO2[0x%x] seq %u nc %d CDB0=%x sstatus=0x%x flags=0x%x resid=%d", __func__, cto->ct_rxid,
+ ATPD_GET_SEQNO(cto), ATPD_GET_NCAM(cto), atp->cdb0, cso->scsi_status, cto->ct_flags, cto->ct_resid);
}
- if (isp->isp_dblev & ISP_LOGTDEBUG1) {
- isp_print_bytes(isp, "FCP Response Frame After Swizzling", MIN_FCP_RESPONSE_SIZE + sense_length, atp->ests);
+ atp->state = ATPD_STATE_LAST_CTIO;
+ }
+
+ if (xfrlen != 0) {
+ cto->ct_flags |= CT2_FLAG_MODE0;
+ if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
+ cto->ct_flags |= CT2_DATA_IN;
+ } else {
+ cto->ct_flags |= CT2_DATA_OUT;
}
- addr = isp->isp_osinfo.ecmd_dma;
- addr += ((((isp_ecmd_t *)atp->ests) - isp->isp_osinfo.ecmd_base) * XCMD_SIZE);
- isp_prt(isp, repval, "%s: ests base %p vaddr %p ecmd_dma %jx addr %jx len %u", __func__, isp->isp_osinfo.ecmd_base, atp->ests,
- (uintmax_t) isp->isp_osinfo.ecmd_dma, (uintmax_t)addr, MIN_FCP_RESPONSE_SIZE + sense_length);
- cto->rsp.m2.ct_datalen = MIN_FCP_RESPONSE_SIZE + sense_length;
- if (isp->isp_osinfo.sixtyfourbit) {
- cto->rsp.m2.u.ct_fcp_rsp_iudata_64.ds_base = DMA_LO32(addr);
- cto->rsp.m2.u.ct_fcp_rsp_iudata_64.ds_basehi = DMA_HI32(addr);
- cto->rsp.m2.u.ct_fcp_rsp_iudata_64.ds_count = MIN_FCP_RESPONSE_SIZE + sense_length;
+
+ cto->ct_reloff = atp->bytes_xfered + atp->bytes_in_transit;
+ cto->rsp.m0.ct_xfrlen = xfrlen;
+
+ if (sendstatus) {
+ resid = atp->orig_datalen - atp->bytes_xfered - xfrlen;
+ if (cso->scsi_status == SCSI_STATUS_OK && resid == 0 /*&& fctape == 0*/) {
+ cto->ct_flags |= CT2_SENDSTATUS;
+ atp->state = ATPD_STATE_LAST_CTIO;
+ if (fctape) {
+ cto->ct_flags |= CT2_CONFIRM;
+ }
+ } else {
+ atp->sendst = 1; /* send status later */
+ cto->ct_header.rqs_seqno &= ~ATPD_SEQ_NOTIFY_CAM;
+ atp->state = ATPD_STATE_CTIO;
+ }
} else {
- cto->rsp.m2.u.ct_fcp_rsp_iudata_32.ds_base = DMA_LO32(addr);
- cto->rsp.m2.u.ct_fcp_rsp_iudata_32.ds_count = MIN_FCP_RESPONSE_SIZE + sense_length;
+ atp->state = ATPD_STATE_CTIO;
}
}
- if (sense_length) {
- isp_prt(isp, repval, "%s: CTIO2[0x%x] CDB0=%x sstatus=0x%x flags=0x%x resid=%d sense: %x %x/%x/%x", __func__,
- cto->ct_rxid, atp->cdb0, cso->scsi_status, cto->ct_flags, cto->ct_resid, cso->sense_data.error_code,
- cso->sense_data.sense_buf[1], cso->sense_data.sense_buf[11], cso->sense_data.sense_buf[12]);
- } else {
- isp_prt(isp, repval, "%s: CTIO2[0x%x] CDB0=%x sstatus=0x%x flags=0x%x resid=%d", __func__,
- cto->ct_rxid, atp->cdb0, cso->scsi_status, cto->ct_flags, cto->ct_resid);
- }
- atp->state = ATPD_STATE_LAST_CTIO;
- }
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO2[%x] seq %u nc %d CDB0=%x scsi status %x flags %x resid %d xfrlen %u offset %u", __func__, cto->ct_rxid,
+ ATPD_GET_SEQNO(cto), ATPD_GET_NCAM(cto), atp->cdb0, cso->scsi_status, cto->ct_flags, cto->ct_resid, cso->dxfer_len, atp->bytes_xfered);
+ } else {
+ ct_entry_t *cto = (ct_entry_t *) local;
- if (xfrlen != 0) {
- int resid = 0;
- cto->ct_flags |= CT2_FLAG_MODE0;
- if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- cto->ct_flags |= CT2_DATA_IN;
- } else {
- cto->ct_flags |= CT2_DATA_OUT;
+ cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
+ cto->ct_header.rqs_entry_count = 1;
+ cto->ct_header.rqs_seqno |= ATPD_SEQ_NOTIFY_CAM;
+ ATPD_SET_SEQNO(cto, atp);
+ cto->ct_iid = cso->init_id;
+ cto->ct_iid |= XS_CHANNEL(ccb) << 7;
+ cto->ct_tgt = ccb->ccb_h.target_id;
+ cto->ct_lun = ccb->ccb_h.target_lun;
+ cto->ct_fwhandle = cso->tag_id;
+ if (atp->rxid) {
+ cto->ct_tag_val = atp->rxid;
+ cto->ct_flags |= CT_TQAE;
}
-
- /*
- * Don't overrun the limits placed on us, but record it as
- * if we had so that we can set an overflow bit later.
- */
- atp->last_xframt = xfrlen;
- if (atp->bytes_xfered + xfrlen > atp->orig_datalen) {
- resid = 1;
- xfrlen = atp->orig_datalen - atp->bytes_xfered;
+ if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) {
+ cto->ct_flags |= CT_NODISC;
}
- cto->ct_reloff = atp->bytes_xfered;
- cto->rsp.m0.ct_xfrlen = xfrlen;
-
- if (sendstatus) {
- if (cso->scsi_status == SCSI_STATUS_OK && resid == 0 && fctape == 0) {
- cto->ct_flags |= CT2_SENDSTATUS;
- atp->state = ATPD_STATE_LAST_CTIO;
- } else {
- atp->sendst = 1; /* send status later */
- cto->ct_header.rqs_seqno = 0;
- atp->state = ATPD_STATE_CTIO;
- }
+ if (cso->dxfer_len == 0) {
+ cto->ct_flags |= CT_NO_DATA;
+ } else if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
+ cto->ct_flags |= CT_DATA_IN;
} else {
- atp->state = ATPD_STATE_CTIO;
+ cto->ct_flags |= CT_DATA_OUT;
}
+ if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
+ cto->ct_flags |= CT_SENDSTATUS|CT_CCINCR;
+ cto->ct_scsi_status = cso->scsi_status;
+ cto->ct_resid = atp->orig_datalen - atp->bytes_xfered - atp->bytes_in_transit - xfrlen;
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO[%x] seq %u nc %d scsi status %x resid %d tag_id %x", __func__,
+ cto->ct_fwhandle, ATPD_GET_SEQNO(cto), ATPD_GET_NCAM(cto), cso->scsi_status, cso->resid, cso->tag_id);
+ }
+ ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
+ cto->ct_timeout = 10;
}
- isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO2[%x] CDB0=%x scsi status %x flags %x resid %d xfrlen %u offset %u", __func__, cto->ct_rxid,
- atp->cdb0, cso->scsi_status, cto->ct_flags, cto->ct_resid, cso->dxfer_len, atp->bytes_xfered);
- } else {
- ct_entry_t *cto = (ct_entry_t *) local;
- cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
- cto->ct_header.rqs_entry_count = 1;
- cto->ct_header.rqs_seqno = 1;
- cto->ct_iid = cso->init_id;
- cto->ct_iid |= XS_CHANNEL(ccb) << 7;
- cto->ct_tgt = ccb->ccb_h.target_id;
- cto->ct_lun = ccb->ccb_h.target_lun;
- cto->ct_fwhandle = cso->tag_id;
- if (atp->rxid) {
- cto->ct_tag_val = atp->rxid;
- cto->ct_flags |= CT_TQAE;
+ if (isp_get_pcmd(isp, ccb)) {
+ ISP_PATH_PRT(isp, ISP_LOGWARN, ccb->ccb_h.path, "out of PCMDs\n");
+ TAILQ_INSERT_HEAD(&tptr->waitq, &ccb->ccb_h, periph_links.tqe);
+ break;
}
- if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) {
- cto->ct_flags |= CT_NODISC;
+ if (isp_allocate_xs_tgt(isp, ccb, &handle)) {
+ ISP_PATH_PRT(isp, ISP_LOGWARN, ccb->ccb_h.path, "No XFLIST pointers for %s\n", __func__);
+ TAILQ_INSERT_HEAD(&tptr->waitq, &ccb->ccb_h, periph_links.tqe);
+ isp_free_pcmd(isp, ccb);
+ break;
}
- if (cso->dxfer_len == 0) {
- cto->ct_flags |= CT_NO_DATA;
- } else if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- cto->ct_flags |= CT_DATA_IN;
- } else {
- cto->ct_flags |= CT_DATA_OUT;
- }
- if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
- cto->ct_flags |= CT_SENDSTATUS|CT_CCINCR;
- cto->ct_scsi_status = cso->scsi_status;
- cto->ct_resid = cso->resid;
- isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO[%x] scsi status %x resid %d tag_id %x", __func__,
- cto->ct_fwhandle, cso->scsi_status, cso->resid, cso->tag_id);
- }
- ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
- cto->ct_timeout = 10;
- }
+ atp->bytes_in_transit += xfrlen;
+ PISP_PCMD(ccb)->datalen = xfrlen;
- if (isp_allocate_xs_tgt(isp, ccb, &handle)) {
- ISP_PATH_PRT(isp, ISP_LOGWARN, ccb->ccb_h.path, "No XFLIST pointers for %s\n", __func__);
- goto restart_delay;
- }
- /*
- * Call the dma setup routines for this entry (and any subsequent
- * CTIOs) if there's data to move, and then tell the f/w it's got
- * new things to play with. As with isp_start's usage of DMA setup,
- * any swizzling is done in the machine dependent layer. Because
- * of this, we put the request onto the queue area first in native
- * format.
- */
+ /*
+ * Call the dma setup routines for this entry (and any subsequent
+ * CTIOs) if there's data to move, and then tell the f/w it's got
+ * new things to play with. As with isp_start's usage of DMA setup,
+ * any swizzling is done in the machine dependent layer. Because
+ * of this, we put the request onto the queue area first in native
+ * format.
+ */
- if (IS_24XX(isp)) {
- ct7_entry_t *cto = (ct7_entry_t *) local;
- cto->ct_syshandle = handle;
- } else if (IS_FC(isp)) {
- ct2_entry_t *cto = (ct2_entry_t *) local;
- cto->ct_syshandle = handle;
- } else {
- ct_entry_t *cto = (ct_entry_t *) local;
- cto->ct_syshandle = handle;
- }
+ if (IS_24XX(isp)) {
+ ct7_entry_t *cto = (ct7_entry_t *) local;
+ cto->ct_syshandle = handle;
+ } else if (IS_FC(isp)) {
+ ct2_entry_t *cto = (ct2_entry_t *) local;
+ cto->ct_syshandle = handle;
+ } else {
+ ct_entry_t *cto = (ct_entry_t *) local;
+ cto->ct_syshandle = handle;
+ }
- dmaresult = ISP_DMASETUP(isp, cso, (ispreq_t *) local);
- if (dmaresult == CMD_QUEUED) {
+ dmaresult = ISP_DMASETUP(isp, cso, (ispreq_t *) local);
+ if (dmaresult != CMD_QUEUED) {
+ isp_destroy_tgt_handle(isp, handle);
+ isp_free_pcmd(isp, ccb);
+ if (dmaresult == CMD_EAGAIN) {
+ TAILQ_INSERT_HEAD(&tptr->waitq, &ccb->ccb_h, periph_links.tqe);
+ break;
+ }
+ ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+ xpt_done(ccb);
+ continue;
+ }
isp->isp_nactive++;
+ ccb->ccb_h.status = CAM_REQ_INPROG | CAM_SIM_QUEUED;
if (xfrlen) {
ccb->ccb_h.spriv_field0 = atp->bytes_xfered;
} else {
ccb->ccb_h.spriv_field0 = ~0;
}
- ccb->ccb_h.status = CAM_REQ_INPROG | CAM_SIM_QUEUED;
atp->ctcnt++;
- rls_lun_statep(isp, tptr);
- return;
+ atp->seqno++;
}
- isp_destroy_tgt_handle(isp, handle);
- if (dmaresult != CMD_EAGAIN) {
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
- goto out;
- }
-restart_delay:
- cam_freeze_devq(ccb->ccb_h.path);
- cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 250, 0);
- ccb->ccb_h.status = CAM_REQUEUE_REQ;
-out:
rls_lun_statep(isp, tptr);
- isp_free_pcmd(isp, ccb);
- xpt_done(ccb);
}
static void
@@ -2262,7 +2287,6 @@
}
atp->orig_datalen = 0;
atp->bytes_xfered = 0;
- atp->last_xframt = 0;
atp->lun = aep->at_lun;
atp->nphdl = aep->at_iid;
atp->portid = PORT_NONE;
@@ -2426,7 +2450,6 @@
atp->orig_datalen = aep->at_datalen;
atp->bytes_xfered = 0;
- atp->last_xframt = 0;
atp->lun = lun;
atp->nphdl = atiop->init_id;
atp->sid = PORT_ANY;
@@ -2648,7 +2671,6 @@
}
atp->orig_datalen = aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl;
atp->bytes_xfered = 0;
- atp->last_xframt = 0;
atp->lun = lun;
atp->nphdl = nphdl;
atp->portid = sid;
@@ -2697,7 +2719,7 @@
atp->srr_ccb = NULL;
atp->nsrr++;
if (ccb == NULL) {
- isp_prt(isp, ISP_LOGWARN, "SRR[0x%08x] null ccb", atp->tag);
+ isp_prt(isp, ISP_LOGWARN, "SRR[0x%x] null ccb", atp->tag);
goto fail;
}
@@ -2711,20 +2733,19 @@
* We have to restart a FCP_DATA data out transaction
*/
atp->sendst = 0;
- atp->last_xframt = 0;
atp->bytes_xfered = srr_off;
if (ccb_len == 0) {
- isp_prt(isp, ISP_LOGWARN, "SRR[0x%08x] SRR offset 0x%x but current CCB doesn't transfer data", atp->tag, srr_off);
+ isp_prt(isp, ISP_LOGWARN, "SRR[0x%x] SRR offset 0x%x but current CCB doesn't transfer data", atp->tag, srr_off);
goto mdp;
}
if (srr_off < ccb_off || ccb_off > srr_off + ccb_len) {
- isp_prt(isp, ISP_LOGWARN, "SRR[0x%08x] SRR offset 0x%x not covered by current CCB data range [0x%x..0x%x]", atp->tag, srr_off, ccb_off, ccb_end);
+ isp_prt(isp, ISP_LOGWARN, "SRR[0x%x] SRR offset 0x%x not covered by current CCB data range [0x%x..0x%x]", atp->tag, srr_off, ccb_off, ccb_end);
goto mdp;
}
- isp_prt(isp, ISP_LOGWARN, "SRR[0x%08x] SRR offset 0x%x covered by current CCB data range [0x%x..0x%x]", atp->tag, srr_off, ccb_off, ccb_end);
+ isp_prt(isp, ISP_LOGWARN, "SRR[0x%x] SRR offset 0x%x covered by current CCB data range [0x%x..0x%x]", atp->tag, srr_off, ccb_off, ccb_end);
break;
case R_CTL_INFO_COMMAND_STATUS:
- isp_prt(isp, ISP_LOGTINFO, "SRR[0x%08x] Got an FCP RSP SRR- resending status", atp->tag);
+ isp_prt(isp, ISP_LOGTINFO, "SRR[0x%x] Got an FCP RSP SRR- resending status", atp->tag);
atp->sendst = 1;
/*
* We have to restart a FCP_RSP IU transaction
@@ -2812,7 +2833,7 @@
}
atp->srr_notify_rcvd = 1;
memcpy(atp->srr, inot, sizeof (atp->srr));
- isp_prt(isp, ISP_LOGTINFO /* ISP_LOGTDEBUG0 */, "SRR[0x%08x] inot->in_rxid flags 0x%x srr_iu=%x reloff 0x%x", inot->in_rxid, inot->in_flags, inot->in_srr_iu,
+ isp_prt(isp, ISP_LOGTINFO /* ISP_LOGTDEBUG0 */, "SRR[0x%x] inot->in_rxid flags 0x%x srr_iu=%x reloff 0x%x", inot->in_rxid, inot->in_flags, inot->in_srr_iu,
inot->in_srr_reloff_lo | (inot->in_srr_reloff_hi << 16));
if (atp->srr_ccb)
isp_handle_srr_start(isp, tptr, atp);
@@ -2823,11 +2844,11 @@
isp_handle_platform_ctio(ispsoftc_t *isp, void *arg)
{
union ccb *ccb;
- int sentstatus = 0, ok = 0, notify_cam = 0, resid = 0, moved_data = 0, failure = 0;
+ int sentstatus = 0, ok = 0, notify_cam = 0, resid = 0, failure = 0;
tstate_t *tptr = NULL;
atio_private_data_t *atp = NULL;
int bus;
- uint32_t handle;
+ uint32_t handle, moved_data = 0, data_requested;
/*
* CTIO handles are 16 bits.
@@ -2845,6 +2866,7 @@
return;
}
isp_destroy_tgt_handle(isp, handle);
+ data_requested = PISP_PCMD(ccb)->datalen;
isp_free_pcmd(isp, ccb);
if (isp->isp_nactive) {
isp->isp_nactive--;
@@ -2873,6 +2895,7 @@
return;
}
KASSERT((atp->ctcnt > 0), ("ctio count not greater than zero"));
+ atp->bytes_in_transit -= data_requested;
atp->ctcnt -= 1;
ccb->ccb_h.status &= ~CAM_STATUS_MASK;
@@ -2891,14 +2914,14 @@
} else {
sentstatus = ct->ct_flags & CT7_SENDSTATUS;
ok = (ct->ct_nphdl == CT7_OK);
- notify_cam = ct->ct_header.rqs_seqno & 0x1;
+ notify_cam = (ct->ct_header.rqs_seqno & ATPD_SEQ_NOTIFY_CAM) != 0;
if ((ct->ct_flags & CT7_DATAMASK) != CT7_NO_DATA) {
resid = ct->ct_resid;
- moved_data = 1;
+ moved_data = data_requested - resid;
}
}
- isp_prt(isp, ok? ISP_LOGTDEBUG0 : ISP_LOGWARN, "%s: CTIO7[%x] sts 0x%x flg 0x%x sns %d resid %d %s", __func__,
- ct->ct_rxid, ct->ct_nphdl, ct->ct_flags, (ccb->ccb_h.status & CAM_SENT_SENSE) != 0, resid, sentstatus? "FIN" : "MID");
+ isp_prt(isp, ok? ISP_LOGTDEBUG0 : ISP_LOGWARN, "%s: CTIO7[%x] seq %u nc %d sts 0x%x flg 0x%x sns %d resid %d %s", __func__, ct->ct_rxid, ATPD_GET_SEQNO(ct),
+ notify_cam, ct->ct_nphdl, ct->ct_flags, (ccb->ccb_h.status & CAM_SENT_SENSE) != 0, resid, sentstatus? "FIN" : "MID");
} else if (IS_FC(isp)) {
ct2_entry_t *ct = arg;
if (ct->ct_status == CT_SRR) {
@@ -2914,14 +2937,14 @@
} else {
sentstatus = ct->ct_flags & CT2_SENDSTATUS;
ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK;
- notify_cam = ct->ct_header.rqs_seqno & 0x1;
+ notify_cam = (ct->ct_header.rqs_seqno & ATPD_SEQ_NOTIFY_CAM) != 0;
if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) {
resid = ct->ct_resid;
- moved_data = 1;
+ moved_data = data_requested - resid;
}
}
- isp_prt(isp, ok? ISP_LOGTDEBUG0 : ISP_LOGWARN, "%s: CTIO2[%x] sts 0x%x flg 0x%x sns %d resid %d %s", __func__,
- ct->ct_rxid, ct->ct_status, ct->ct_flags, (ccb->ccb_h.status & CAM_SENT_SENSE) != 0, resid, sentstatus? "FIN" : "MID");
+ isp_prt(isp, ok? ISP_LOGTDEBUG0 : ISP_LOGWARN, "%s: CTIO2[%x] seq %u nc %d sts 0x%x flg 0x%x sns %d resid %d %s", __func__, ct->ct_rxid, ATPD_GET_SEQNO(ct),
+ notify_cam, ct->ct_status, ct->ct_flags, (ccb->ccb_h.status & CAM_SENT_SENSE) != 0, resid, sentstatus? "FIN" : "MID");
} else {
ct_entry_t *ct = arg;
@@ -2930,20 +2953,19 @@
} else {
sentstatus = ct->ct_flags & CT_SENDSTATUS;
ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK;
- notify_cam = ct->ct_header.rqs_seqno & 0x1;
+ notify_cam = (ct->ct_header.rqs_seqno & ATPD_SEQ_NOTIFY_CAM) != 0;
}
if ((ct->ct_flags & CT_DATAMASK) != CT_NO_DATA) {
resid = ct->ct_resid;
- moved_data = 1;
+ moved_data = data_requested - resid;
}
- isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO[%x] tag %x S_ID 0x%x lun %d sts %x flg %x resid %d %s", __func__,
- ct->ct_fwhandle, ct->ct_tag_val, ct->ct_iid, ct->ct_lun, ct->ct_status, ct->ct_flags, resid, sentstatus? "FIN" : "MID");
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO[%x] seq %u nc %d tag %x S_ID 0x%x lun %d sts %x flg %x resid %d %s", __func__, ct->ct_fwhandle, ATPD_GET_SEQNO(ct),
+ notify_cam, ct->ct_tag_val, ct->ct_iid, ct->ct_lun, ct->ct_status, ct->ct_flags, resid, sentstatus? "FIN" : "MID");
}
if (ok) {
if (moved_data) {
- ccb->csio.resid += resid;
- atp->bytes_xfered += (atp->last_xframt - resid);
- atp->last_xframt = 0;
+ atp->bytes_xfered += moved_data;
+ ccb->csio.resid = atp->orig_datalen - atp->bytes_xfered - atp->bytes_in_transit;
}
if (sentstatus && (ccb->ccb_h.flags & CAM_SEND_SENSE)) {
ccb->ccb_h.status |= CAM_SENT_SENSE;
@@ -2963,7 +2985,8 @@
* We never *not* notify CAM when there has been any error (ok == 0),
* so we never need to do an ATIO putback if we're not notifying CAM.
*/
- isp_prt(isp, ISP_LOGTDEBUG0, "%s CTIO[0x%x] done (notify_cam=%d nowsendstatus=%d)", (sentstatus)? " FINAL " : "MIDTERM ", atp->tag, notify_cam, atp->sendst);
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s CTIO[0x%x] done (ok=%d nc=%d nowsendstatus=%d ccb ss=%d)",
+ (sentstatus)? " FINAL " : "MIDTERM ", atp->tag, ok, notify_cam, atp->sendst, (ccb->ccb_h.flags & CAM_SEND_STATUS) != 0);
if (notify_cam == 0) {
if (atp->sendst) {
isp_target_start_ctio(isp, ccb, FROM_CTIO_DONE);
@@ -3522,25 +3545,47 @@
#ifdef ISP_INTERNAL_TARGET
-// #define ISP_FORCE_TIMEOUT 1
-// #define ISP_TEST_WWNS 1
-// #define ISP_TEST_SEPARATE_STATUS 1
+//#define ISP_SEPARATE_STATUS 1
+#define ISP_MULTI_CCBS 1
+#if defined(ISP_MULTI_CCBS) && !defined(ISP_SEPARATE_STATUS)
+#define ISP_SEPARATE_STATUS 1
+#endif
-#define ccb_data_offset ppriv_field0
+typedef struct periph_private_data_t {
+ union ccb *ccb; /* original ATIO or Immediate Notify */
+ unsigned long offset; /* current offset */
+ int sequence; /* current CTIO sequence */
+ int ctio_cnt; /* current # of ctio's outstanding */
+ int
+ status_sent : 1,
+ on_queue : 1; /* on restart queue */
+} ppd_t;
+/*
+ * Each ATIO we allocate will have periph private data associated with it
+ * that maintains per-command state. This private to each ATIO.
+ */
+#define ATIO_PPD(ccb) ((ppd_t *)(((struct ccb_hdr *)ccb)->ppriv_ptr0))
+/*
+ * Each CTIO we send downstream will get a pointer to the ATIO itself
+ * so that on completion we can retrieve that pointer.
+ */
#define ccb_atio ppriv_ptr1
#define ccb_inot ppriv_ptr1
+/*
+ * Each CTIO we send downstream will contain a sequence number
+ */
+#define CTIO_SEQ(ccb) ccb->ccb_h.ppriv_field0
+
#define MAX_ISP_TARG_TRANSFER (2 << 20)
-#define NISP_TARG_CMDS 1024
-#define NISP_TARG_NOTIFIES 1024
+#define NISP_TARG_CMDS 64
+#define NISP_TARG_NOTIFIES 64
#define DISK_SHIFT 9
#define JUNK_SIZE 256
+#define MULTI_CCB_DATA_LIM 8192
+//#define MULTI_CCB_DATA_CNT 64
+#define MULTI_CCB_DATA_CNT 8
-#ifndef VERIFY_10
-#define VERIFY_10 0x2f
-#endif
-
-TAILQ_HEAD(ccb_queue, ccb_hdr);
extern u_int vm_kmem_size;
static int ca;
static uint32_t disk_size;
@@ -3549,10 +3594,10 @@
static MALLOC_DEFINE(M_ISPTARG, "ISPTARG", "ISP TARGET data");
struct isptarg_softc {
/* CCBs (CTIOs, ATIOs, INOTs) pending on the controller */
- struct ccb_queue work_queue;
- struct ccb_queue rework_queue;
- struct ccb_queue running_queue;
- struct ccb_queue inot_queue;
+ struct isp_ccbq work_queue;
+ struct isp_ccbq rework_queue;
+ struct isp_ccbq running_queue;
+ struct isp_ccbq inot_queue;
struct cam_periph *periph;
struct cam_path *path;
ispsoftc_t *isp;
@@ -3569,7 +3614,7 @@
static struct periph_driver isptargdriver =
{
- isptarginit, "isptarg", TAILQ_HEAD_INITIALIZER(isptargdriver.units), /* generation */ 0
+ isptarginit, "isptarg", TAILQ_HEAD_INITIALIZER(isptargdriver.units), 0
};
static void
@@ -3613,7 +3658,8 @@
'O', 'R', 'Y', ' ', 'D', 'I', 'S', 'K',
'0', '0', '0', '1'
};
- int r, i, more = 0, last;
+ int r, i, more = 0, last, is_data_cmd = 0, is_write;
+ char *queue;
struct isptarg_softc *softc = periph->softc;
struct ccb_scsiio *csio;
lun_id_t return_lun;
@@ -3647,10 +3693,10 @@
atio = (struct ccb_accept_tio *)ccbh;
TAILQ_REMOVE(&softc->rework_queue, ccbh, periph_links.tqe);
more = TAILQ_FIRST(&softc->work_queue) || TAILQ_FIRST(&softc->rework_queue);
+ queue = "rework";
} else {
ccbh = TAILQ_FIRST(&softc->work_queue);
if (ccbh == NULL) {
- ISP_PATH_PRT(softc->isp, ISP_LOGWARN, iccb->ccb_h.path, "%s: woken up but no work?\n", __func__);
xpt_release_ccb(iccb);
return;
}
@@ -3657,22 +3703,23 @@
atio = (struct ccb_accept_tio *)ccbh;
TAILQ_REMOVE(&softc->work_queue, ccbh, periph_links.tqe);
more = TAILQ_FIRST(&softc->work_queue) != NULL;
- atio->ccb_h.ccb_data_offset = 0;
+ queue = "work";
}
+ ATIO_PPD(atio)->on_queue = 0;
if (atio->tag_id == 0xffffffff || atio->ccb_h.func_code != XPT_ACCEPT_TARGET_IO) {
panic("BAD ATIO");
}
+ data_len = is_write = 0;
data_ptr = NULL;
- data_len = 0;
csio = &iccb->csio;
status = SCSI_STATUS_OK;
flags = CAM_SEND_STATUS;
memset(&atio->sense_data, 0, sizeof (atio->sense_data));
cdb = atio->cdb_io.cdb_bytes;
- ISP_PATH_PRT(softc->isp, ISP_LOGTDEBUG1, ccbh->path, "%s: [0x%x] processing ATIO from 0x%x CDB=0x%x data_offset=%u\n", __func__, atio->tag_id, atio->init_id,
- cdb[0], atio->ccb_h.ccb_data_offset);
+ ISP_PATH_PRT(softc->isp, ISP_LOGTDEBUG0, ccbh->path, "%s: [0x%x] processing ATIO from %s queue initiator 0x%x CDB=0x%x data_offset=%u\n", __func__, atio->tag_id,
+ queue, atio->init_id, cdb[0], ATIO_PPD(atio)->offset);
return_lun = XS_LUN(atio);
if (return_lun != 0) {
@@ -3700,11 +3747,18 @@
data_ptr = junk_data;
}
break;
+ case WRITE_6:
+ case WRITE_10:
+ case WRITE_12:
+ case WRITE_16:
+ is_write = 1;
+ /* FALLTHROUGH */
case READ_6:
case READ_10:
case READ_12:
case READ_16:
- r = isptarg_rwparm(cdb, disk_data, disk_size, atio->ccb_h.ccb_data_offset, &data_ptr, &data_len, &last);
+ is_data_cmd = 1;
+ r = isptarg_rwparm(cdb, disk_data, disk_size, ATIO_PPD(atio)->offset, &data_ptr, &data_len, &last);
if (r != 0) {
status = SCSI_STATUS_CHECK_COND;
SDFIXED(atio->sense_data)->error_code = SSD_ERRCODE_VALID|SSD_CURRENT_ERROR;
@@ -3716,19 +3770,7 @@
}
atio->sense_len = SSD_MIN_SIZE;
} else {
-#ifdef ISP_FORCE_TIMEOUT
- {
- static int foo;
- if (foo++ == 500) {
- if (more) {
- xpt_schedule(periph, 1);
- }
- foo = 0;
- return;
- }
- }
-#endif
-#ifdef ISP_TEST_SEPARATE_STATUS
+#ifdef ISP_SEPARATE_STATUS
if (last && data_len) {
last = 0;
}
@@ -3737,57 +3779,16 @@
flags &= ~CAM_SEND_STATUS;
}
if (data_len) {
- atio->ccb_h.ccb_data_offset += data_len;
- flags |= CAM_DIR_IN;
+ ATIO_PPD(atio)->offset += data_len;
+ if (is_write)
+ flags |= CAM_DIR_OUT;
+ else
+ flags |= CAM_DIR_IN;
} else {
flags |= CAM_DIR_NONE;
}
}
break;
- case WRITE_6:
- case WRITE_10:
- case WRITE_12:
- case WRITE_16:
- r = isptarg_rwparm(cdb, disk_data, disk_size, atio->ccb_h.ccb_data_offset, &data_ptr, &data_len, &last);
- if (r != 0) {
- status = SCSI_STATUS_CHECK_COND;
- SDFIXED(atio->sense_data)->error_code = SSD_ERRCODE_VALID|SSD_CURRENT_ERROR;
- SDFIXED(atio->sense_data)->flags = SSD_KEY_ILLEGAL_REQUEST;
- if (r == -1) {
- SDFIXED(atio->sense_data)->add_sense_code = 0x21; /* LOGICAL BLOCK ADDRESS OUT OF RANGE */
- } else {
- SDFIXED(atio->sense_data)->add_sense_code = 0x20; /* INVALID COMMAND OPERATION CODE */
- }
- atio->sense_len = SSD_MIN_SIZE;
- } else {
-#ifdef ISP_FORCE_TIMEOUT
- {
- static int foo;
- if (foo++ == 500) {
- if (more) {
- xpt_schedule(periph, 1);
- }
- foo = 0;
- return;
- }
- }
-#endif
-#ifdef ISP_TEST_SEPARATE_STATUS
- if (last && data_len) {
- last = 0;
- }
-#endif
- if (last == 0) {
- flags &= ~CAM_SEND_STATUS;
- }
- if (data_len) {
- atio->ccb_h.ccb_data_offset += data_len;
- flags |= CAM_DIR_OUT;
- } else {
- flags |= CAM_DIR_NONE;
- }
- }
- break;
case INQUIRY:
flags |= CAM_DIR_IN;
if (cdb[1] || cdb[2] || cdb[3]) {
@@ -3875,7 +3876,7 @@
junk_data[3] = (1 << 3);
ptr = NULL;
for (i = 0; i < 1; i++) {
- ptr = &junk_data[8 + (1 << 3)];
+ ptr = &junk_data[8 + (i << 3)];
if (i >= 256) {
ptr[0] = 0x40 | ((i >> 8) & 0x3f);
}
@@ -3909,10 +3910,17 @@
data_len = 0;
data_ptr = NULL;
}
- cam_fill_ctio(csio, 0, isptarg_done, flags, MSG_SIMPLE_Q_TAG, atio->tag_id, atio->init_id, status, data_ptr, data_len, 0);
+ cam_fill_ctio(csio, 0, isptarg_done, flags, MSG_SIMPLE_Q_TAG, atio->tag_id, atio->init_id, status, data_ptr, data_len, 30 * hz);
iccb->ccb_h.target_id = atio->ccb_h.target_id;
iccb->ccb_h.target_lun = return_lun;
iccb->ccb_h.ccb_atio = atio;
+ CTIO_SEQ(iccb) = ATIO_PPD(atio)->sequence++;
+ ATIO_PPD(atio)->ctio_cnt++;
+ if (flags & CAM_SEND_STATUS) {
+ KASSERT((ATIO_PPD(atio)->status_sent == 0), ("we have already sent status for 0x%x in %s", atio->tag_id, __func__));
+ ATIO_PPD(atio)->status_sent = 1;
+ }
+ ISP_PATH_PRT(softc->isp, ISP_LOGTDEBUG0, atio->ccb_h.path, "%s: sending downstream for 0x%x sequence %u len %u flags %x\n", __func__, atio->tag_id, CTIO_SEQ(iccb), data_len, flags);
xpt_action(iccb);
if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) {
@@ -3919,6 +3927,14 @@
cam_release_devq(periph->path, 0, 0, 0, 0);
atio->ccb_h.status &= ~CAM_DEV_QFRZN;
}
+#ifdef ISP_MULTI_CCBS
+ if (is_data_cmd && ATIO_PPD(atio)->status_sent == 0 && ATIO_PPD(atio)->ctio_cnt < MULTI_CCB_DATA_CNT && ATIO_PPD(atio)->on_queue == 0) {
+ ISP_PATH_PRT(softc->isp, ISP_LOGTDEBUG0, atio->ccb_h.path, "%s: more still to do for 0x%x\n", __func__, atio->tag_id);
+ TAILQ_INSERT_TAIL(&softc->rework_queue, &atio->ccb_h, periph_links.tqe);
+ ATIO_PPD(atio)->on_queue = 1;
+ more = 1;
+ }
+#endif
if (more) {
xpt_schedule(periph, 1);
}
@@ -3953,6 +3969,7 @@
{
struct isptarg_softc *softc;
ispsoftc_t *isp;
+ uint32_t newoff;
struct ccb_accept_tio *atio;
struct ccb_immediate_notify *inot;
cam_status status;
@@ -3964,41 +3981,56 @@
switch (ccb->ccb_h.func_code) {
case XPT_ACCEPT_TARGET_IO:
atio = (struct ccb_accept_tio *) ccb;
- ISP_PATH_PRT(isp, ISP_LOGTDEBUG1, ccb->ccb_h.path, "[0x%x] ATIO seen in %s\n", atio->tag_id, __func__);
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "[0x%x] ATIO seen in %s\n", atio->tag_id, __func__);
+ memset(ATIO_PPD(atio), 0, sizeof (ppd_t));
TAILQ_INSERT_TAIL(&softc->work_queue, &ccb->ccb_h, periph_links.tqe);
+ ATIO_PPD(atio)->on_queue = 1;
xpt_schedule(periph, 1);
break;
case XPT_IMMEDIATE_NOTIFY:
inot = (struct ccb_immediate_notify *) ccb;
- ISP_PATH_PRT(isp, ISP_LOGTDEBUG1, ccb->ccb_h.path, "[0x%x] INOT for 0x%x seen in %s\n", inot->tag_id, inot->seq_id, __func__);
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "[0x%x] INOT for 0x%x seen in %s\n", inot->tag_id, inot->seq_id, __func__);
TAILQ_INSERT_TAIL(&softc->inot_queue, &ccb->ccb_h, periph_links.tqe);
xpt_schedule(periph, 1);
break;
case XPT_CONT_TARGET_IO:
- if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
- cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0);
- ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
- }
atio = ccb->ccb_h.ccb_atio;
+ KASSERT((ATIO_PPD(atio)->ctio_cnt != 0), ("ctio zero when finishing a CTIO"));
+ ATIO_PPD(atio)->ctio_cnt--;
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
- if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_MESSAGE_RECV) {
- uint32_t newoff = (ccb->csio.msg_ptr[3] << 24) | (ccb->csio.msg_ptr[4] << 16) | (ccb->csio.msg_ptr[5] << 8) | (ccb->csio.msg_ptr[6]);
- ISP_PATH_PRT(isp, ISP_LOGWARN, ccb->ccb_h.path, "[0x%08x] got message to return to reset offset to 0x%x\n", atio->tag_id, newoff);
- atio->ccb_h.ccb_data_offset = newoff;
- TAILQ_INSERT_TAIL(&softc->rework_queue, &atio->ccb_h, periph_links.tqe);
+ switch (ccb->ccb_h.status & CAM_STATUS_MASK) {
+ case CAM_MESSAGE_RECV:
+ newoff = (ccb->csio.msg_ptr[3] << 24) | (ccb->csio.msg_ptr[4] << 16) | (ccb->csio.msg_ptr[5] << 8) | (ccb->csio.msg_ptr[6]);
+ ISP_PATH_PRT(isp, ISP_LOGWARN, ccb->ccb_h.path, "[0x%x] got message to return to reset offset to 0x%x at sequence %u\n", atio->tag_id, newoff, CTIO_SEQ(ccb));
+ ATIO_PPD(atio)->offset = newoff;
+ ATIO_PPD(atio)->status_sent = 0;
+ if (ATIO_PPD(atio)->on_queue == 0) {
+ TAILQ_INSERT_TAIL(&softc->rework_queue, &atio->ccb_h, periph_links.tqe);
+ ATIO_PPD(atio)->on_queue = 1;
+ }
xpt_schedule(periph, 1);
- } else {
+ break;
+ default:
cam_error_print(ccb, CAM_ESF_ALL, CAM_EPF_ALL);
xpt_action((union ccb *)atio);
+ break;
}
} else if ((ccb->ccb_h.flags & CAM_SEND_STATUS) == 0) {
- ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "[0x%x] MID CTIO seen in %s\n", atio->tag_id, __func__);
- TAILQ_INSERT_TAIL(&softc->rework_queue, &atio->ccb_h, periph_links.tqe);
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "[0x%x] MID CTIO sequence %u seen in %s\n", atio->tag_id, CTIO_SEQ(ccb), __func__);
+ if (ATIO_PPD(atio)->status_sent == 0 && ATIO_PPD(atio)->on_queue == 0) {
+ TAILQ_INSERT_TAIL(&softc->rework_queue, &atio->ccb_h, periph_links.tqe);
+ ATIO_PPD(atio)->on_queue = 1;
+ }
xpt_schedule(periph, 1);
} else {
- ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "[0x%x] FINAL CTIO seen in %s\n", atio->tag_id, __func__);
+ KASSERT((ATIO_PPD(atio)->ctio_cnt == 0), ("ctio count still %d when we think we've sent the STATUS ctio", ATIO_PPD(atio)->ctio_cnt));
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "[0x%x] FINAL CTIO sequence %u seen in %s\n", atio->tag_id, CTIO_SEQ(ccb), __func__);
xpt_action((union ccb *)atio);
}
+ if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+ cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0);
+ ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
+ }
xpt_release_ccb(ccb);
break;
case XPT_NOTIFY_ACKNOWLEDGE:
@@ -4133,13 +4165,7 @@
xpt_setup_ccb(&ccb->ccb_h, periph->path, 10);
ccb->ccb_h.func_code = XPT_SET_SIM_KNOB;
ccb->knob.xport_specific.fc.role = KNOB_ROLE_NONE;
-#ifdef ISP_TEST_WWNS
- ccb->knob.xport_specific.fc.valid = KNOB_VALID_ROLE | KNOB_VALID_ADDRESS;
- ccb->knob.xport_specific.fc.wwnn = 0x508004d000000000ULL | (device_get_unit(isp->isp_osinfo.dev) << 8) | (chan << 16);
- ccb->knob.xport_specific.fc.wwpn = 0x508004d000000001ULL | (device_get_unit(isp->isp_osinfo.dev) << 8) | (chan << 16);
-#else
ccb->knob.xport_specific.fc.valid = KNOB_VALID_ROLE;
-#endif
ISP_LOCK(isp);
xpt_action(ccb);
@@ -4182,6 +4208,7 @@
xpt_setup_ccb(&ccb->ccb_h, wperiph->path, 1);
ccb->ccb_h.func_code = XPT_ACCEPT_TARGET_IO;
ccb->ccb_h.cbfcnp = isptarg_done;
+ ccb->ccb_h.ppriv_ptr0 = malloc(sizeof (ppd_t), M_ISPTARG, M_WAITOK | M_ZERO);
ISP_LOCK(isp);
xpt_action(ccb);
ISP_UNLOCK(isp);
@@ -4191,6 +4218,7 @@
xpt_setup_ccb(&ccb->ccb_h, periph->path, 1);
ccb->ccb_h.func_code = XPT_ACCEPT_TARGET_IO;
ccb->ccb_h.cbfcnp = isptarg_done;
+ ccb->ccb_h.ppriv_ptr0 = malloc(sizeof (ppd_t), M_ISPTARG, M_WAITOK | M_ZERO);
ISP_LOCK(isp);
xpt_action(ccb);
ISP_UNLOCK(isp);
@@ -4342,7 +4370,6 @@
return (-2);
}
-
curcnt = MAX_ISP_TARG_TRANSFER;
if (offset + curcnt >= cnt) {
curcnt = cnt - offset;
@@ -4350,6 +4377,10 @@
} else {
*lp = 0;
}
+#ifdef ISP_MULTI_CCBS
+ if (curcnt > MULTI_CCB_DATA_LIM)
+ curcnt = MULTI_CCB_DATA_LIM;
+#endif
*tl = curcnt;
*kp = &dp[lba + offset];
return (0);
@@ -4646,7 +4677,7 @@
if (dbidx != (FCPARAM(isp, chan)->isp_dev_map[XS_TGT(xs)] - 1)) {
continue;
}
- isp_prt(isp, ISP_LOGWARN, "command handle 0x%08x for %d.%d.%d orphaned by loop down timeout",
+ isp_prt(isp, ISP_LOGWARN, "command handle 0x%x for %d.%d.%d orphaned by loop down timeout",
isp->isp_xflist[i].handle, chan, XS_TGT(xs), XS_LUN(xs));
}
@@ -4962,6 +4993,7 @@
SLIST_INSERT_HEAD(&tptr->atios, &ccb->ccb_h, sim_links.sle);
ISP_PATH_PRT(isp, ISP_LOGTDEBUG2, ccb->ccb_h.path, "Put FREE ATIO (tag id 0x%x), count now %d\n",
ccb->atio.tag_id, tptr->atio_count);
+ ccb->atio.tag_id = 0;
} else if (ccb->ccb_h.func_code == XPT_IMMEDIATE_NOTIFY) {
if (ccb->cin1.tag_id) {
inot_private_data_t *ntp = isp_find_ntpd(isp, tptr, ccb->cin1.tag_id, ccb->cin1.seq_id);
@@ -4973,11 +5005,13 @@
SLIST_INSERT_HEAD(&tptr->inots, &ccb->ccb_h, sim_links.sle);
ISP_PATH_PRT(isp, ISP_LOGTDEBUG2, ccb->ccb_h.path, "Put FREE INOT, (seq id 0x%x) count now %d\n",
ccb->cin1.seq_id, tptr->inot_count);
+ ccb->cin1.seq_id = 0;
} else if (ccb->ccb_h.func_code == XPT_IMMED_NOTIFY) {
tptr->inot_count++;
SLIST_INSERT_HEAD(&tptr->inots, &ccb->ccb_h, sim_links.sle);
ISP_PATH_PRT(isp, ISP_LOGTDEBUG2, ccb->ccb_h.path, "Put FREE INOT, (seq id 0x%x) count now %d\n",
ccb->cin1.seq_id, tptr->inot_count);
+ ccb->cin1.seq_id = 0;
}
rls_lun_statep(isp, tptr);
ccb->ccb_h.status = CAM_REQ_INPROG;
@@ -6330,6 +6364,9 @@
return (-1);
}
+/*
+ * We enter with the lock held
+ */
void
isp_timer(void *arg)
{
@@ -6337,7 +6374,7 @@
#ifdef ISP_TARGET_MODE
isp_tmcmd_restart(isp);
#endif
- callout_reset(&isp->isp_osinfo.tmo, hz, isp_timer, isp);
+ callout_reset(&isp->isp_osinfo.tmo, isp_timer_count, isp_timer, isp);
}
isp_ecmd_t *
Modified: trunk/sys/dev/isp/isp_freebsd.h
===================================================================
--- trunk/sys/dev/isp/isp_freebsd.h 2016-09-15 08:26:26 UTC (rev 7986)
+++ trunk/sys/dev/isp/isp_freebsd.h 2016-09-15 08:27:12 UTC (rev 7987)
@@ -102,7 +102,7 @@
void * next;
uint32_t orig_datalen;
uint32_t bytes_xfered;
- uint32_t last_xframt;
+ uint32_t bytes_in_transit;
uint32_t tag; /* typically f/w RX_ID */
uint32_t lun;
uint32_t nphdl;
@@ -112,6 +112,7 @@
uint16_t oxid; /* wire oxid */
uint16_t word3; /* PRLI word3 params */
uint16_t ctcnt; /* number of CTIOs currently active */
+ uint8_t seqno; /* CTIO sequence number */
uint32_t
srr_notify_rcvd : 1,
cdb0 : 8,
@@ -134,6 +135,14 @@
#define ATPD_STATE_LAST_CTIO 4
#define ATPD_STATE_PDON 5
+#define ATPD_CCB_OUTSTANDING 16
+
+#define ATPD_SEQ_MASK 0x7f
+#define ATPD_SEQ_NOTIFY_CAM 0x80
+#define ATPD_SET_SEQNO(hdrp, atp) ((isphdr_t *)hdrp)->rqs_seqno &= ~ATPD_SEQ_MASK, ((isphdr_t *)hdrp)->rqs_seqno |= (atp)->seqno
+#define ATPD_GET_SEQNO(hdrp) (((isphdr_t *)hdrp)->rqs_seqno & ATPD_SEQ_MASK)
+#define ATPD_GET_NCAM(hdrp) ((((isphdr_t *)hdrp)->rqs_seqno & ATPD_SEQ_NOTIFY_CAM) != 0)
+
typedef union inot_private_data inot_private_data_t;
union inot_private_data {
inot_private_data_t *next;
@@ -149,9 +158,11 @@
uint8_t data[64]; /* sb QENTRY_LEN, but order of definitions is wrong */
} isp_tna_t;
+TAILQ_HEAD(isp_ccbq, ccb_hdr);
typedef struct tstate {
SLIST_ENTRY(tstate) next;
struct cam_path *owner;
+ struct isp_ccbq waitq; /* waiting CCBs */
struct ccb_hdr_slist atios;
struct ccb_hdr_slist inots;
uint32_t hold;
@@ -179,6 +190,7 @@
bus_dmamap_t dmap; /* dma map for this command */
struct ispsoftc * isp; /* containing isp */
struct callout wdog; /* watchdog timer */
+ uint32_t datalen; /* data length for this command (target mode only) */
uint8_t totslen; /* sense length on status response */
uint8_t cumslen; /* sense length on status response */
uint8_t crn; /* command reference number */
More information about the Midnightbsd-cvs
mailing list