Date: Sun, 2 Sep 2012 15:04:39 +0000 (UTC) From: Matt Jacob <mjacob@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r240016 - stable/9/sys/dev/isp Message-ID: <201209021504.q82F4dSe022166@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mjacob Date: Sun Sep 2 15:04:39 2012 New Revision: 240016 URL: http://svn.freebsd.org/changeset/base/240016 Log: MFC of 239143 More rototilling with target mode in an attemp to get multiple... Modified: stable/9/sys/dev/isp/isp_freebsd.c stable/9/sys/dev/isp/isp_freebsd.h Directory Properties: stable/9/sys/ (props changed) stable/9/sys/dev/ (props changed) stable/9/sys/dev/isp/ (props changed) Modified: stable/9/sys/dev/isp/isp_freebsd.c ============================================================================== --- stable/9/sys/dev/isp/isp_freebsd.c Sun Sep 2 15:03:40 2012 (r240015) +++ stable/9/sys/dev/isp/isp_freebsd.c Sun Sep 2 15:04:39 2012 (r240016) @@ -74,6 +74,7 @@ static void isp_action(struct cam_sim *, 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 @@ isp_attach(ispsoftc_t *isp) } 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 @@ static ISP_INLINE void 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_putback_atio 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 @@ static void 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 @@ isp_tmcmd_restart(ispsoftc_t *isp) 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 @@ isp_tmcmd_restart(ispsoftc_t *isp) 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 @@ isp_dump_atpd(ispsoftc_t *isp, tstate_t 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 @@ create_lun_state(ispsoftc_t *isp, int bu } 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 @@ isp_ledone(ispsoftc_t *isp, lun_entry_t 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; - } - - /* - * 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; + 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; } - /* - * 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; - } + while (TAILQ_FIRST(&tptr->waitq) != NULL) { + ccb = (union ccb *) TAILQ_FIRST(&tptr->waitq); + TAILQ_REMOVE(&tptr->waitq, &ccb->ccb_h, periph_links.tqe); - /* - * 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; - } + 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; + } + } + 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; + } - /* - * 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); + /* + * 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; + } - /* - * 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; - } + /* + * 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; + } - /* - * 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; - } + /* + * 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 (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; + } + if (ccb->ccb_h.flags & CAM_SEND_STATUS) { + sendstatus = 1; + } else { + sendstatus = 0; } - } else { - sense_length = 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 (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) { - 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 |= 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; + 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; } 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); - } - if (isp->isp_dblev & ISP_LOGTDEBUG1) { - isp_print_bytes(isp, "FCP Response Frame After Swizzling", MIN_FCP_RESPONSE_SIZE + sense_length, 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); } - 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; - } - 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; + atp->state = ATPD_STATE_LAST_CTIO; } /* - * 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); - } - if (isp->isp_dblev & ISP_LOGTDEBUG1) { - isp_print_bytes(isp, "FCP Response Frame After Swizzling", MIN_FCP_RESPONSE_SIZE + sense_length, 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); } - 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; + 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->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; + cto->ct_flags |= CT2_DATA_OUT; } - } - 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; - } - 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_reloff = atp->bytes_xfered + atp->bytes_in_transit; + cto->rsp.m0.ct_xfrlen = xfrlen; - /* - * 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; - } - 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; + 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 { - atp->sendst = 1; /* send status later */ - cto->ct_header.rqs_seqno = 0; atp->state = ATPD_STATE_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; + + 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; + } + if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) { + cto->ct_flags |= CT_NODISC; + } + 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 (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) { - cto->ct_flags |= CT_NODISC; - } - 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 (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_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); + 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; } - 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 *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201209021504.q82F4dSe022166>